forked from boostorg/container
Fixes #156: ("Compile error with vector") and remove warnings about precission loss due to integer narrowing
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
[/
|
||||
/ Copyright (c) 2009-2018 Ion Gaztañaga
|
||||
/ Copyright (c) 2009-2020 Ion Gazta<EFBFBD>aga
|
||||
/
|
||||
/ Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
/ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
@@ -1342,12 +1342,14 @@ use [*Boost.Container]? There are several reasons for that:
|
||||
|
||||
* New [classref boost::container::devector devector] container.
|
||||
* Fixed bugs/issues:
|
||||
* [@https://github.com/boostorg/container/issues/156 GitHub #156: ['"Compile error with vector"]].
|
||||
* [@https://github.com/boostorg/container/pull/157 GitHub #157: ['"Add missing include"]].
|
||||
* [@https://github.com/boostorg/container/issues/159 GitHub #159: ['"pmr::monotonic_buffer_resource crashes on large single allocations"]].
|
||||
* [@https://github.com/boostorg/container/issues/160 GitHub #160: ['"Usage of uses_allocator needs a remove_cvref_t"]].
|
||||
* [@https://github.com/boostorg/container/issues/161 GitHub #161: ['"polymorphic_allocator(memory_resource*) non-standard extension causes headache"]].
|
||||
* [@https://github.com/boostorg/container/pull/163 GitHub #163: ['"container_rebind for small_vector with options"]].
|
||||
|
||||
* [@https://github.com/boostorg/container/pull/167 GitHub #167: ['"error: the address of 'msg' will always evaluate as 'true' warning with GCC 4.4"]].
|
||||
|
||||
[endsect]
|
||||
|
||||
[section:release_notes_boost_1_74_00 Boost 1.74 Release]
|
||||
|
@@ -426,7 +426,6 @@ struct insert_emplace_proxy_arg##N\
|
||||
{\
|
||||
BOOST_ASSERT(n == 1); (void)n;\
|
||||
typename dtl::aligned_storage<sizeof(value_type), dtl::alignment_of<value_type>::value>::type v;\
|
||||
BOOST_ASSERT((((size_type)(&v)) % alignment_of<value_type>::value) == 0);\
|
||||
value_type *vp = reinterpret_cast<value_type *>(v.data);\
|
||||
alloc_traits::construct(a, vp BOOST_MOVE_I##N BOOST_MOVE_MFWD##N);\
|
||||
BOOST_TRY{\
|
||||
|
@@ -26,6 +26,7 @@
|
||||
#include <boost/container/detail/mpl.hpp>
|
||||
#include <boost/container/detail/type_traits.hpp>
|
||||
#include <boost/container/detail/construct_in_place.hpp>
|
||||
#include <boost/container/detail/destroyers.hpp>
|
||||
|
||||
// move
|
||||
#include <boost/move/adl_move_swap.hpp>
|
||||
@@ -180,7 +181,7 @@ BOOST_CONTAINER_FORCEINLINE F memmove(I f, I l, F r) BOOST_NOEXCEPT_OR_NOTHROW
|
||||
if(BOOST_LIKELY(beg_raw != end_raw && dest_raw && beg_raw)){
|
||||
const typename boost::container::iterator_traits<I>::difference_type n = end_raw - beg_raw;
|
||||
std::memmove(dest_raw, beg_raw, sizeof(value_type)*n);
|
||||
boost::container::iterator_advance(r, n);
|
||||
r += n;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
@@ -194,7 +195,7 @@ BOOST_CONTAINER_FORCEINLINE F memmove_n(I f, U n, F r) BOOST_NOEXCEPT_OR_NOTHROW
|
||||
typedef typename boost::container::iterator_traits<I>::value_type value_type;
|
||||
if(BOOST_LIKELY(n)){
|
||||
std::memmove(boost::movelib::iterator_to_raw_pointer(r), boost::movelib::iterator_to_raw_pointer(f), sizeof(value_type)*n);
|
||||
boost::container::iterator_advance(r, n);
|
||||
r += n;
|
||||
}
|
||||
|
||||
return r;
|
||||
@@ -209,7 +210,7 @@ BOOST_CONTAINER_FORCEINLINE I memmove_n_source(I f, U n, F r) BOOST_NOEXCEPT_OR_
|
||||
if(BOOST_LIKELY(n)){
|
||||
typedef typename boost::container::iterator_traits<I>::value_type value_type;
|
||||
std::memmove(boost::movelib::iterator_to_raw_pointer(r), boost::movelib::iterator_to_raw_pointer(f), sizeof(value_type)*n);
|
||||
boost::container::iterator_advance(f, n);
|
||||
f += n;
|
||||
}
|
||||
return f;
|
||||
}
|
||||
@@ -223,8 +224,8 @@ BOOST_CONTAINER_FORCEINLINE I memmove_n_source_dest(I f, U n, F &r) BOOST_NOEXCE
|
||||
typedef typename boost::container::iterator_traits<I>::value_type value_type;
|
||||
if(BOOST_LIKELY(n)){
|
||||
std::memmove(boost::movelib::iterator_to_raw_pointer(r), boost::movelib::iterator_to_raw_pointer(f), sizeof(value_type)*n);
|
||||
boost::container::iterator_advance(f, n);
|
||||
boost::container::iterator_advance(r, n);
|
||||
f += n;
|
||||
r += n;
|
||||
}
|
||||
return f;
|
||||
}
|
||||
@@ -593,7 +594,7 @@ BOOST_CONTAINER_FORCEINLINE typename dtl::enable_if_memzero_initializable<F, F>:
|
||||
typedef typename boost::container::iterator_traits<F>::value_type value_type;
|
||||
if (BOOST_LIKELY(n)){
|
||||
std::memset((void*)boost::movelib::iterator_to_raw_pointer(r), 0, sizeof(value_type)*n);
|
||||
boost::container::iterator_advance(r, n);
|
||||
r += n;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
@@ -1172,6 +1173,100 @@ void move_assign_range_alloc_n( Allocator &a, I inp_start, typename allocator_tr
|
||||
}
|
||||
}
|
||||
|
||||
template<class Allocator, class Iterator>
|
||||
struct array_destructor
|
||||
{
|
||||
typedef typename ::boost::container::iterator_traits<Iterator>::value_type value_type;
|
||||
typedef typename dtl::if_c
|
||||
<dtl::is_trivially_destructible<value_type>::value
|
||||
,dtl::null_scoped_destructor_range<Allocator>
|
||||
,dtl::scoped_destructor_range<Allocator>
|
||||
>::type type;
|
||||
};
|
||||
|
||||
template
|
||||
<typename Allocator
|
||||
,typename F // F models ForwardIterator
|
||||
,typename O // G models OutputIterator
|
||||
,typename InsertionProxy
|
||||
>
|
||||
void uninitialized_move_and_insert_alloc
|
||||
( Allocator &a
|
||||
, F first
|
||||
, F pos
|
||||
, F last
|
||||
, O d_first
|
||||
, typename allocator_traits<Allocator>::size_type n
|
||||
, InsertionProxy insert_range_proxy)
|
||||
{
|
||||
typedef typename array_destructor<Allocator, F>::type array_destructor_t;
|
||||
|
||||
//Anti-exception rollbacks
|
||||
array_destructor_t new_values_destroyer(d_first, d_first, a);
|
||||
|
||||
//Initialize with [begin(), pos) old buffer
|
||||
//the start of the new buffer
|
||||
O d_last = ::boost::container::uninitialized_move_alloc(a, first, pos, d_first);
|
||||
new_values_destroyer.set_end(d_last);
|
||||
//Initialize new objects, starting from previous point
|
||||
insert_range_proxy.uninitialized_copy_n_and_update(a, d_last, n);
|
||||
d_last += n;
|
||||
new_values_destroyer.set_end(d_last);
|
||||
//Initialize from the rest of the old buffer,
|
||||
//starting from previous point
|
||||
(void) ::boost::container::uninitialized_move_alloc(a, pos, last, d_last);
|
||||
//All construction successful, disable rollbacks
|
||||
new_values_destroyer.release();
|
||||
}
|
||||
|
||||
template
|
||||
<typename Allocator
|
||||
,typename F // F models ForwardIterator
|
||||
,typename InsertionProxy
|
||||
>
|
||||
void expand_forward_and_insert_alloc
|
||||
( Allocator &a
|
||||
, F pos
|
||||
, F last
|
||||
, typename allocator_traits<Allocator>::size_type n
|
||||
, InsertionProxy insert_range_proxy)
|
||||
{
|
||||
typedef typename array_destructor<Allocator, F>::type array_destructor_t;
|
||||
|
||||
if (BOOST_UNLIKELY(!n)){
|
||||
return;
|
||||
}
|
||||
else if (last == pos){
|
||||
insert_range_proxy.uninitialized_copy_n_and_update(a, last, n);
|
||||
}
|
||||
else{
|
||||
typedef typename allocator_traits<Allocator>::size_type alloc_size_type;
|
||||
const alloc_size_type elems_after = static_cast<alloc_size_type>(last - pos);
|
||||
if(elems_after >= n){
|
||||
//New elements can be just copied.
|
||||
//Move to uninitialized memory last objects
|
||||
::boost::container::uninitialized_move_alloc_n(a, last - n, n, last);
|
||||
array_destructor_t on_exception(last, last, a);
|
||||
//Copy previous to last objects to the initialized end
|
||||
boost::container::move_backward(pos, last - n, last);
|
||||
//Insert new objects in the pos
|
||||
insert_range_proxy.copy_n_and_update(a, pos, n);
|
||||
on_exception.release();
|
||||
}
|
||||
else {
|
||||
//The new elements don't fit in the [pos, end()) range.
|
||||
//Copy old [pos, end()) elements to the uninitialized memory (a gap is created)
|
||||
F new_last = ::boost::container::uninitialized_move_alloc(a, pos, last, pos + n);
|
||||
array_destructor_t on_exception(pos + n, new_last, a);
|
||||
//Copy first new elements in pos (gap is still there)
|
||||
insert_range_proxy.copy_n_and_update(a, pos, elems_after);
|
||||
//Copy to the beginning of the unallocated zone the last new elements (the gap is closed).
|
||||
insert_range_proxy.uninitialized_copy_n_and_update(a, last, n - elems_after);
|
||||
on_exception.release();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} //namespace container {
|
||||
} //namespace boost {
|
||||
|
||||
|
@@ -242,6 +242,72 @@ struct null_scoped_destructor_n
|
||||
{}
|
||||
};
|
||||
|
||||
|
||||
//!A deleter for scoped_ptr that destroys
|
||||
//!an object using a STL allocator.
|
||||
template <class Allocator>
|
||||
struct scoped_destructor_range
|
||||
{
|
||||
typedef boost::container::allocator_traits<Allocator> AllocTraits;
|
||||
typedef typename AllocTraits::pointer pointer;
|
||||
typedef typename AllocTraits::value_type value_type;
|
||||
|
||||
BOOST_CONTAINER_FORCEINLINE scoped_destructor_range(pointer p, pointer e, Allocator& a)
|
||||
: m_p(p), m_e(e), m_a(a)
|
||||
{}
|
||||
|
||||
BOOST_CONTAINER_FORCEINLINE void release()
|
||||
{ m_p = pointer(); m_e = pointer(); }
|
||||
|
||||
BOOST_CONTAINER_FORCEINLINE void set_end(pointer e)
|
||||
{ m_e = e; }
|
||||
|
||||
BOOST_CONTAINER_FORCEINLINE void set_begin(pointer b)
|
||||
{ m_p = b; }
|
||||
|
||||
BOOST_CONTAINER_FORCEINLINE void set_range(pointer b, pointer e)
|
||||
{ m_p = b; m_e = e; }
|
||||
|
||||
~scoped_destructor_range()
|
||||
{
|
||||
while(m_p != m_e){
|
||||
value_type *raw_ptr = boost::movelib::to_raw_pointer(m_p);
|
||||
AllocTraits::destroy(m_a, raw_ptr);
|
||||
++m_p;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
pointer m_p;
|
||||
pointer m_e;
|
||||
Allocator & m_a;
|
||||
};
|
||||
|
||||
//!A deleter for scoped_ptr that destroys
|
||||
//!an object using a STL allocator.
|
||||
template <class Allocator>
|
||||
struct null_scoped_destructor_range
|
||||
{
|
||||
typedef boost::container::allocator_traits<Allocator> AllocTraits;
|
||||
typedef typename AllocTraits::pointer pointer;
|
||||
|
||||
BOOST_CONTAINER_FORCEINLINE null_scoped_destructor_range(pointer, pointer, Allocator&)
|
||||
{}
|
||||
|
||||
BOOST_CONTAINER_FORCEINLINE void release()
|
||||
{}
|
||||
|
||||
BOOST_CONTAINER_FORCEINLINE void set_end(pointer)
|
||||
{}
|
||||
|
||||
BOOST_CONTAINER_FORCEINLINE void set_begin(pointer)
|
||||
{}
|
||||
|
||||
BOOST_CONTAINER_FORCEINLINE void set_range(pointer, pointer)
|
||||
{}
|
||||
};
|
||||
|
||||
|
||||
template<class Allocator>
|
||||
class scoped_destructor
|
||||
{
|
||||
|
@@ -56,7 +56,12 @@ struct grow_factor_ratio
|
||||
else{
|
||||
new_cap *= Numerator;
|
||||
}
|
||||
return max_value(SizeType(Minimum), max_value(cur_cap+add_min_cap, min_value(max_cap, new_cap)));
|
||||
return max_value<SizeType>
|
||||
( SizeType(Minimum)
|
||||
, max_value<SizeType>
|
||||
( SizeType(cur_cap+add_min_cap)
|
||||
, min_value<SizeType>(max_cap, new_cap))
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
|
@@ -247,10 +247,6 @@ struct vector_value_traits_base
|
||||
{
|
||||
static const bool trivial_dctr = dtl::is_trivially_destructible<T>::value;
|
||||
static const bool trivial_dctr_after_move = has_trivial_destructor_after_move<T>::value;
|
||||
static const bool trivial_copy = dtl::is_trivially_copy_constructible<T>::value;
|
||||
static const bool nothrow_copy = dtl::is_nothrow_copy_constructible<T>::value || trivial_copy;
|
||||
static const bool trivial_assign = dtl::is_trivially_copy_assignable<T>::value;
|
||||
static const bool nothrow_assign = dtl::is_nothrow_copy_assignable<T>::value || trivial_assign;
|
||||
};
|
||||
|
||||
template <class Allocator>
|
||||
@@ -317,34 +313,41 @@ struct vector_alloc_holder
|
||||
{}
|
||||
|
||||
//Constructor, does not throw
|
||||
template<class AllocConvertible>
|
||||
vector_alloc_holder(vector_uninitialized_size_t, BOOST_FWD_REF(AllocConvertible) a, size_type initial_size)
|
||||
template<class AllocConvertible, class SizeType>
|
||||
vector_alloc_holder(vector_uninitialized_size_t, BOOST_FWD_REF(AllocConvertible) a, SizeType initial_size)
|
||||
: allocator_type(boost::forward<AllocConvertible>(a))
|
||||
, m_start()
|
||||
//Size is initialized here so vector should only call uninitialized_xxx after this
|
||||
, m_size(static_cast<stored_size_type>(initial_size))
|
||||
, m_capacity()
|
||||
{
|
||||
if(initial_size){
|
||||
if (initial_size > size_type(-1)){
|
||||
boost::container::throw_length_error("get_next_capacity, allocator's max size reached");
|
||||
}
|
||||
else if(initial_size){
|
||||
pointer reuse = pointer();
|
||||
size_type final_cap = initial_size;
|
||||
m_start = this->allocation_command(allocate_new, initial_size, final_cap, reuse);
|
||||
size_type final_cap = static_cast<size_type>(initial_size);
|
||||
m_start = this->allocation_command(allocate_new, final_cap, final_cap, reuse);
|
||||
this->set_stored_capacity(final_cap);
|
||||
}
|
||||
}
|
||||
|
||||
//Constructor, does not throw
|
||||
vector_alloc_holder(vector_uninitialized_size_t, size_type initial_size)
|
||||
template<class SizeType>
|
||||
vector_alloc_holder(vector_uninitialized_size_t, SizeType initial_size)
|
||||
: allocator_type()
|
||||
, m_start()
|
||||
//Size is initialized here so vector should only call uninitialized_xxx after this
|
||||
, m_size(static_cast<stored_size_type>(initial_size))
|
||||
, m_capacity()
|
||||
{
|
||||
if(initial_size){
|
||||
if (initial_size > size_type(-1)){
|
||||
boost::container::throw_length_error("get_next_capacity, allocator's max size reached");
|
||||
}
|
||||
else if(initial_size){
|
||||
pointer reuse = pointer();
|
||||
size_type final_cap = initial_size;
|
||||
m_start = this->allocation_command(allocate_new, initial_size, final_cap, reuse);
|
||||
m_start = this->allocation_command(allocate_new, final_cap, final_cap, reuse);
|
||||
this->set_stored_capacity(final_cap);
|
||||
}
|
||||
}
|
||||
@@ -1014,7 +1017,7 @@ private:
|
||||
#endif
|
||||
::boost::container::uninitialized_copy_alloc_n_source
|
||||
( this->m_holder.alloc(), il.begin()
|
||||
, il.size(), this->priv_raw_begin());
|
||||
, static_cast<size_type>(il.size()), this->priv_raw_begin());
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1262,7 +1265,12 @@ private:
|
||||
{
|
||||
//For Fwd iterators the standard only requires EmplaceConstructible and assignable from *first
|
||||
//so we can't do any backwards allocation
|
||||
const size_type input_sz = static_cast<size_type>(boost::container::iterator_distance(first, last));
|
||||
const typename iterator_traits<FwdIt>::size_type sz = boost::container::iterator_distance(first, last);
|
||||
if (sz > size_type(-1)){
|
||||
boost::container::throw_length_error("vector::assign, FwdIt's max length reached");
|
||||
}
|
||||
|
||||
const size_type input_sz = static_cast<size_type>(sz);
|
||||
const size_type old_capacity = this->capacity();
|
||||
if(input_sz > old_capacity){ //If input range is too big, we need to reallocate
|
||||
size_type real_cap = 0;
|
||||
@@ -1968,8 +1976,13 @@ private:
|
||||
)
|
||||
{
|
||||
BOOST_ASSERT(this->priv_in_range_or_end(pos));
|
||||
const typename iterator_traits<FwdIt>::size_type sz = boost::container::iterator_distance(first, last);
|
||||
if (sz > size_type(-1)){
|
||||
boost::container::throw_length_error("vector::insert, FwdIt's max length reached");
|
||||
}
|
||||
|
||||
dtl::insert_range_proxy<allocator_type, FwdIt, T*> proxy(first);
|
||||
return this->priv_insert_forward_range(vector_iterator_get_ptr(pos), boost::container::iterator_distance(first, last), proxy);
|
||||
return this->priv_insert_forward_range(vector_iterator_get_ptr(pos), static_cast<size_type>(sz), proxy);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -2009,7 +2022,7 @@ private:
|
||||
//! <b>Returns</b>: an iterator to the first inserted element or position if first == last.
|
||||
//!
|
||||
//! <b>Complexity</b>: Linear to the range [il.begin(), il.end()).
|
||||
iterator insert(const_iterator position, std::initializer_list<value_type> il)
|
||||
BOOST_CONTAINER_FORCEINLINE iterator insert(const_iterator position, std::initializer_list<value_type> il)
|
||||
{
|
||||
//Assertion done in insert()
|
||||
return this->insert(position, il.begin(), il.end());
|
||||
@@ -2021,11 +2034,12 @@ private:
|
||||
//! <b>Throws</b>: Nothing.
|
||||
//!
|
||||
//! <b>Complexity</b>: Constant time.
|
||||
void pop_back() BOOST_NOEXCEPT_OR_NOTHROW
|
||||
BOOST_CONTAINER_FORCEINLINE void pop_back() BOOST_NOEXCEPT_OR_NOTHROW
|
||||
{
|
||||
BOOST_ASSERT(!this->empty());
|
||||
//Destroy last element
|
||||
this->priv_destroy_last();
|
||||
allocator_traits_type::destroy(this->get_stored_allocator(), this->priv_raw_end() - 1);
|
||||
--this->m_holder.m_size;
|
||||
}
|
||||
|
||||
//! <b>Effects</b>: Erases the element at position pos.
|
||||
@@ -2039,10 +2053,16 @@ private:
|
||||
BOOST_ASSERT(this->priv_in_range(position));
|
||||
const pointer p = vector_iterator_get_ptr(position);
|
||||
T *const pos_ptr = boost::movelib::to_raw_pointer(p);
|
||||
T *const beg_ptr = this->priv_raw_begin();
|
||||
T *const new_end_ptr = ::boost::container::move(pos_ptr + 1, beg_ptr + this->m_holder.m_size, pos_ptr);
|
||||
T *const end_ptr = this->priv_raw_end();
|
||||
|
||||
//Move elements forward and destroy last
|
||||
this->priv_destroy_last(pos_ptr != new_end_ptr);
|
||||
(void)::boost::container::move(pos_ptr + 1, end_ptr, pos_ptr);
|
||||
|
||||
T *const last_ptr = end_ptr-1;
|
||||
if(!value_traits::trivial_dctr_after_move || pos_ptr == last_ptr){
|
||||
allocator_traits_type::destroy(this->get_stored_allocator(), last_ptr);
|
||||
}
|
||||
--this->m_holder.m_size;
|
||||
return iterator(p);
|
||||
}
|
||||
|
||||
@@ -2054,15 +2074,19 @@ private:
|
||||
//! plus linear to the elements between pos and the last element.
|
||||
iterator erase(const_iterator first, const_iterator last)
|
||||
{
|
||||
if (first != last){
|
||||
BOOST_ASSERT(this->priv_in_range(first));
|
||||
BOOST_ASSERT(this->priv_in_range_or_end(last));
|
||||
BOOST_ASSERT(first < last);
|
||||
BOOST_ASSERT(this->priv_in_range_or_end(first));
|
||||
BOOST_ASSERT(this->priv_in_range_or_end(last));
|
||||
BOOST_ASSERT(first <= last);
|
||||
if(first != last){
|
||||
T* const old_end_ptr = this->priv_raw_end();
|
||||
T* const first_ptr = boost::movelib::to_raw_pointer(vector_iterator_get_ptr(first));
|
||||
T* const last_ptr = boost::movelib::to_raw_pointer(vector_iterator_get_ptr(last));
|
||||
T* const ptr = boost::movelib::to_raw_pointer(boost::container::move(last_ptr, old_end_ptr, first_ptr));
|
||||
this->priv_destroy_last_n(old_end_ptr - ptr);
|
||||
T* const new_last_ptr = boost::movelib::to_raw_pointer(boost::container::move(last_ptr, old_end_ptr, first_ptr));
|
||||
const size_type n = static_cast<size_type>(old_end_ptr - new_last_ptr);
|
||||
if(!value_traits::trivial_dctr_after_move || old_end_ptr == last_ptr){
|
||||
boost::container::destroy_alloc_n(this->get_stored_allocator(), new_last_ptr, n);
|
||||
}
|
||||
this->m_holder.dec_stored_size(n);
|
||||
}
|
||||
return iterator(vector_iterator_get_ptr(first));
|
||||
}
|
||||
@@ -2575,24 +2599,10 @@ private:
|
||||
}
|
||||
}
|
||||
|
||||
void priv_destroy_last(const bool moved = false) BOOST_NOEXCEPT_OR_NOTHROW
|
||||
{
|
||||
(void)moved;
|
||||
const bool skip_destructor = value_traits::trivial_dctr || (value_traits::trivial_dctr_after_move && moved);
|
||||
if(!skip_destructor){
|
||||
value_type* const p = this->priv_raw_end() - 1;
|
||||
allocator_traits_type::destroy(this->get_stored_allocator(), p);
|
||||
}
|
||||
--this->m_holder.m_size;
|
||||
}
|
||||
|
||||
void priv_destroy_last_n(const size_type n) BOOST_NOEXCEPT_OR_NOTHROW
|
||||
{
|
||||
BOOST_ASSERT(n <= this->m_holder.m_size);
|
||||
if(!value_traits::trivial_dctr){
|
||||
T* const destroy_pos = this->priv_raw_begin() + (this->m_holder.m_size-n);
|
||||
boost::container::destroy_alloc_n(this->get_stored_allocator(), destroy_pos, n);
|
||||
}
|
||||
boost::container::destroy_alloc_n(this->get_stored_allocator(), this->priv_raw_end() - n, n);
|
||||
this->m_holder.dec_stored_size(n);
|
||||
}
|
||||
|
||||
@@ -2601,7 +2611,7 @@ private:
|
||||
{
|
||||
T* const old_end_pos = this->priv_raw_end();
|
||||
T* const new_end_pos = boost::container::uninitialized_copy_alloc(this->m_holder.alloc(), first, last, old_end_pos);
|
||||
this->m_holder.inc_stored_size(new_end_pos - old_end_pos);
|
||||
this->m_holder.inc_stored_size(static_cast<size_type>(new_end_pos - old_end_pos));
|
||||
}
|
||||
|
||||
void priv_destroy_all() BOOST_NOEXCEPT_OR_NOTHROW
|
||||
@@ -2623,6 +2633,13 @@ private:
|
||||
this->emplace_back(::boost::forward<U>(u));
|
||||
}
|
||||
|
||||
//Overload to support compiler errors that instantiate too much
|
||||
BOOST_CONTAINER_FORCEINLINE void priv_push_back(::boost::move_detail::nat)
|
||||
{}
|
||||
|
||||
BOOST_CONTAINER_FORCEINLINE iterator priv_insert(const_iterator, ::boost::move_detail::nat)
|
||||
{ return iterator(); }
|
||||
|
||||
BOOST_CONTAINER_FORCEINLINE dtl::insert_n_copies_proxy<allocator_type, T*> priv_resize_proxy(const T &x)
|
||||
{ return dtl::insert_n_copies_proxy<allocator_type, T*>(x); }
|
||||
|
||||
@@ -2689,7 +2706,7 @@ private:
|
||||
(T *const raw_pos, const size_type n, const InsertionProxy insert_range_proxy, version_1)
|
||||
{
|
||||
//Check if we have enough memory or try to expand current memory
|
||||
const size_type n_pos = raw_pos - this->priv_raw_begin();
|
||||
const size_type n_pos = static_cast<size_type>(raw_pos - this->priv_raw_begin());
|
||||
|
||||
const size_type new_cap = this->m_holder.template next_capacity<growth_factor_type>(n);
|
||||
//Pass the hint so that allocators can take advantage of this.
|
||||
@@ -2898,16 +2915,17 @@ private:
|
||||
BOOST_ASSERT(this->room_enough());
|
||||
//There is enough memory
|
||||
T* const old_finish = this->priv_raw_end();
|
||||
allocator_type & a = this->m_holder.alloc();
|
||||
|
||||
if (old_finish == raw_pos){
|
||||
insert_range_proxy.uninitialized_copy_n_and_update(this->m_holder.alloc(), old_finish, 1);
|
||||
insert_range_proxy.uninitialized_copy_n_and_update(a, old_finish, 1);
|
||||
++this->m_holder.m_size;
|
||||
}
|
||||
else{
|
||||
//New elements can be just copied.
|
||||
//Move to uninitialized memory last objects
|
||||
T * const before_old_finish = old_finish-1;
|
||||
allocator_type & a = this->m_holder.alloc();
|
||||
|
||||
allocator_traits_type::construct(a, old_finish, ::boost::move(*before_old_finish));
|
||||
++this->m_holder.m_size;
|
||||
//Copy previous to last objects to the initialized end
|
||||
@@ -2918,45 +2936,12 @@ private:
|
||||
}
|
||||
|
||||
template <class InsertionProxy>
|
||||
void priv_insert_forward_range_expand_forward(T* const raw_pos, const size_type n, InsertionProxy insert_range_proxy, dtl::false_type)
|
||||
BOOST_CONTAINER_FORCEINLINE void priv_insert_forward_range_expand_forward(T* const raw_pos, const size_type n, InsertionProxy insert_range_proxy, dtl::false_type)
|
||||
{
|
||||
//In case n is 0 there is nothing to do
|
||||
if(BOOST_UNLIKELY(!n))
|
||||
return;
|
||||
|
||||
//There is enough memory
|
||||
T* const raw_old_finish = this->priv_raw_end();
|
||||
|
||||
if (raw_old_finish == raw_pos){
|
||||
insert_range_proxy.uninitialized_copy_n_and_update(this->m_holder.alloc(), raw_old_finish, n);
|
||||
this->m_holder.inc_stored_size(n);
|
||||
}
|
||||
else{
|
||||
const size_type elems_after = raw_old_finish - raw_pos;
|
||||
allocator_type & a = this->m_holder.alloc();
|
||||
if(elems_after >= n){
|
||||
//New elements can be just copied.
|
||||
//Move to uninitialized memory last objects
|
||||
::boost::container::uninitialized_move_alloc_n(a, raw_old_finish - n, n, raw_old_finish);
|
||||
this->m_holder.inc_stored_size(n);
|
||||
//Copy previous to last objects to the initialized end
|
||||
boost::container::move_backward(raw_pos, raw_old_finish - n, raw_old_finish);
|
||||
//Insert new objects in the raw_pos
|
||||
insert_range_proxy.copy_n_and_update(a, raw_pos, n);
|
||||
}
|
||||
else {
|
||||
//The new elements don't fit in the [raw_pos, end()) range.
|
||||
//Copy old [raw_pos, end()) elements to the uninitialized memory (a gap is created)
|
||||
::boost::container::uninitialized_move_alloc(a, raw_pos, raw_old_finish, raw_pos + n);
|
||||
typename value_traits::ArrayDestructor on_exception(raw_pos + n, a, elems_after);
|
||||
//Copy first new elements in raw_pos (gap is still there)
|
||||
insert_range_proxy.copy_n_and_update(a, raw_pos, elems_after);
|
||||
//Copy to the beginning of the unallocated zone the last new elements (the gap is closed).
|
||||
insert_range_proxy.uninitialized_copy_n_and_update(a, raw_old_finish, n - elems_after);
|
||||
this->m_holder.inc_stored_size(n);
|
||||
on_exception.release();
|
||||
}
|
||||
}
|
||||
boost::container::expand_forward_and_insert_alloc
|
||||
( this->m_holder.alloc(), raw_pos, this->priv_raw_end(), n, insert_range_proxy);
|
||||
this->m_holder.inc_stored_size(n);
|
||||
}
|
||||
|
||||
template <class InsertionProxy>
|
||||
@@ -2964,45 +2949,24 @@ private:
|
||||
(T* const new_start, size_type new_cap, T* const pos, const size_type n, InsertionProxy insert_range_proxy)
|
||||
{
|
||||
//n can be zero, if we want to reallocate!
|
||||
T *new_finish = new_start;
|
||||
T *old_finish;
|
||||
|
||||
allocator_type &a = this->m_holder.alloc();
|
||||
T * const raw_old_buffer = this->priv_raw_begin();
|
||||
|
||||
//Anti-exception rollbacks
|
||||
typename value_traits::ArrayDeallocator new_buffer_deallocator(new_start, a, new_cap);
|
||||
typename value_traits::ArrayDestructor new_values_destroyer(new_start, a, 0u);
|
||||
boost::container::uninitialized_move_and_insert_alloc
|
||||
(a, raw_old_buffer, pos, this->priv_raw_end(), new_start, n, insert_range_proxy);
|
||||
new_buffer_deallocator.release();
|
||||
|
||||
//Initialize with [begin(), pos) old buffer
|
||||
//the start of the new buffer
|
||||
T * const old_buffer = this->priv_raw_begin();
|
||||
if(old_buffer){
|
||||
new_finish = ::boost::container::uninitialized_move_alloc
|
||||
(a, this->priv_raw_begin(), pos, old_finish = new_finish);
|
||||
new_values_destroyer.increment_size(new_finish - old_finish);
|
||||
}
|
||||
//Initialize new objects, starting from previous point
|
||||
old_finish = new_finish;
|
||||
insert_range_proxy.uninitialized_copy_n_and_update(a, old_finish, n);
|
||||
new_finish += n;
|
||||
new_values_destroyer.increment_size(new_finish - old_finish);
|
||||
//Initialize from the rest of the old buffer,
|
||||
//starting from previous point
|
||||
if(old_buffer){
|
||||
new_finish = ::boost::container::uninitialized_move_alloc
|
||||
(a, pos, old_buffer + this->m_holder.m_size, new_finish);
|
||||
//Destroy and deallocate old elements
|
||||
//If there is allocated memory, destroy and deallocate
|
||||
if(!value_traits::trivial_dctr_after_move)
|
||||
boost::container::destroy_alloc_n(this->get_stored_allocator(), old_buffer, this->m_holder.m_size);
|
||||
//Destroy and deallocate old elements
|
||||
if(raw_old_buffer){
|
||||
BOOST_IF_CONSTEXPR(!has_trivial_destructor_after_move<value_type>::value)
|
||||
boost::container::destroy_alloc_n(a, raw_old_buffer, this->m_holder.m_size);
|
||||
this->m_holder.deallocate(this->m_holder.start(), this->m_holder.capacity());
|
||||
}
|
||||
|
||||
this->m_holder.start(new_start);
|
||||
m_holder.set_stored_size(new_finish - new_start);
|
||||
this->m_holder.inc_stored_size(n);
|
||||
this->m_holder.capacity(new_cap);
|
||||
//All construction successful, disable rollbacks
|
||||
new_values_destroyer.release();
|
||||
new_buffer_deallocator.release();
|
||||
}
|
||||
|
||||
template <class InsertionProxy>
|
||||
@@ -3314,7 +3278,7 @@ private:
|
||||
//Copy to the old_end part to the uninitialized zone leaving a gap.
|
||||
::boost::container::uninitialized_move_alloc(a, pos, old_finish, old_finish + mid_last_dist);
|
||||
|
||||
array_destructor_t old_end_destroyer(old_finish + mid_last_dist, a, old_finish - pos);
|
||||
array_destructor_t old_end_destroyer(old_finish + mid_last_dist, a, static_cast<size_type>(old_finish - pos));
|
||||
|
||||
//Copy the first part to the already constructed old_end zone
|
||||
insert_range_proxy.copy_n_and_update(a, pos, elemsafter);
|
||||
|
@@ -23,6 +23,29 @@ volatile ::boost::container::vector<empty> dummy;
|
||||
#include "movable_int.hpp"
|
||||
#include "dummy_test_allocator.hpp"
|
||||
|
||||
class CustomAllocator
|
||||
{
|
||||
public:
|
||||
typedef int value_type;
|
||||
typedef value_type* pointer;
|
||||
typedef const value_type* const_pointer;
|
||||
typedef unsigned short size_type;
|
||||
typedef short difference_type;
|
||||
|
||||
pointer allocate(size_type count)
|
||||
{ return (pointer)new char[sizeof(value_type)*count]; }
|
||||
|
||||
void deallocate(pointer ptr, size_type )
|
||||
{ delete [](char*)ptr; }
|
||||
|
||||
friend bool operator==(CustomAllocator const&, CustomAllocator const&) BOOST_NOEXCEPT
|
||||
{ return true; }
|
||||
|
||||
friend bool operator!=(CustomAllocator const& x, CustomAllocator const& y) BOOST_NOEXCEPT
|
||||
{ return !(x == y); }
|
||||
};
|
||||
|
||||
|
||||
namespace boost {
|
||||
namespace container {
|
||||
|
||||
@@ -44,6 +67,9 @@ template class boost::container::vector< test::movable_and_copyable_int
|
||||
, vector_options< stored_size<unsigned short> >::type
|
||||
>;
|
||||
|
||||
//test custom allocator with small size_type
|
||||
template class boost::container::vector<int, CustomAllocator>;
|
||||
|
||||
} //namespace boost {
|
||||
} //namespace container {
|
||||
|
||||
|
Reference in New Issue
Block a user