- Simplified code using new priv_raw_begin(), renamed back_raw to priv_back_raw to match it.

- Avoid dynamic allocation in priv_merge when there is enough capacity for new elements.
This commit is contained in:
Ion Gaztañaga
2015-10-12 18:57:44 +02:00
parent 7764e05444
commit d517bf46a8

View File

@@ -216,7 +216,7 @@ struct vector_merge_cursor
typedef SizeType size_type; typedef SizeType size_type;
typedef typename iterator_traits<BiDirValueIt>::reference reference; typedef typename iterator_traits<BiDirValueIt>::reference reference;
vector_merge_cursor(T *pbeg, T *plast, BiDirValueIt valueit, Comp cmp) vector_merge_cursor(T *pbeg, T *plast, BiDirValueIt valueit, Comp &cmp)
: m_pbeg(pbeg), m_pcur(--plast), m_valueit(valueit), m_cmp(cmp) : m_pbeg(pbeg), m_pcur(--plast), m_valueit(valueit), m_cmp(cmp)
{} {}
@@ -241,7 +241,7 @@ struct vector_merge_cursor
T *const m_pbeg; T *const m_pbeg;
T *m_pcur; T *m_pcur;
BiDirValueIt m_valueit; BiDirValueIt m_valueit;
Comp m_cmp; Comp &m_cmp;
}; };
} //namespace container_detail { } //namespace container_detail {
@@ -818,7 +818,7 @@ class vector
this->num_alloc += n != 0; this->num_alloc += n != 0;
#endif #endif
boost::container::uninitialized_value_init_alloc_n boost::container::uninitialized_value_init_alloc_n
(this->m_holder.alloc(), n, container_detail::to_raw_pointer(this->m_holder.start())); (this->m_holder.alloc(), n, this->priv_raw_begin());
} }
//! <b>Effects</b>: Constructs a vector that will use a copy of allocator a //! <b>Effects</b>: Constructs a vector that will use a copy of allocator a
@@ -837,7 +837,7 @@ class vector
this->num_alloc += n != 0; this->num_alloc += n != 0;
#endif #endif
boost::container::uninitialized_default_init_alloc_n boost::container::uninitialized_default_init_alloc_n
(this->m_holder.alloc(), n, container_detail::to_raw_pointer(this->m_holder.start())); (this->m_holder.alloc(), n, this->priv_raw_begin());
} }
//! <b>Effects</b>: Constructs a vector that will use a copy of allocator a //! <b>Effects</b>: Constructs a vector that will use a copy of allocator a
@@ -854,7 +854,7 @@ class vector
this->num_alloc += n != 0; this->num_alloc += n != 0;
#endif #endif
boost::container::uninitialized_value_init_alloc_n boost::container::uninitialized_value_init_alloc_n
(this->m_holder.alloc(), n, container_detail::to_raw_pointer(this->m_holder.start())); (this->m_holder.alloc(), n, this->priv_raw_begin());
} }
//! <b>Effects</b>: Constructs a vector that will use a copy of allocator a //! <b>Effects</b>: Constructs a vector that will use a copy of allocator a
@@ -873,7 +873,7 @@ class vector
this->num_alloc += n != 0; this->num_alloc += n != 0;
#endif #endif
boost::container::uninitialized_default_init_alloc_n boost::container::uninitialized_default_init_alloc_n
(this->m_holder.alloc(), n, container_detail::to_raw_pointer(this->m_holder.start())); (this->m_holder.alloc(), n, this->priv_raw_begin());
} }
//! <b>Effects</b>: Constructs a vector //! <b>Effects</b>: Constructs a vector
@@ -890,7 +890,7 @@ class vector
this->num_alloc += n != 0; this->num_alloc += n != 0;
#endif #endif
boost::container::uninitialized_fill_alloc_n boost::container::uninitialized_fill_alloc_n
(this->m_holder.alloc(), value, n, container_detail::to_raw_pointer(this->m_holder.start())); (this->m_holder.alloc(), value, n, this->priv_raw_begin());
} }
//! <b>Effects</b>: Constructs a vector that will use a copy of allocator a //! <b>Effects</b>: Constructs a vector that will use a copy of allocator a
@@ -907,7 +907,7 @@ class vector
this->num_alloc += n != 0; this->num_alloc += n != 0;
#endif #endif
boost::container::uninitialized_fill_alloc_n boost::container::uninitialized_fill_alloc_n
(this->m_holder.alloc(), value, n, container_detail::to_raw_pointer(this->m_holder.start())); (this->m_holder.alloc(), value, n, this->priv_raw_begin());
} }
//! <b>Effects</b>: Constructs a vector //! <b>Effects</b>: Constructs a vector
@@ -951,8 +951,8 @@ class vector
this->num_alloc += x.size() != 0; this->num_alloc += x.size() != 0;
#endif #endif
::boost::container::uninitialized_copy_alloc_n ::boost::container::uninitialized_copy_alloc_n
( this->m_holder.alloc(), container_detail::to_raw_pointer(x.m_holder.start()) ( this->m_holder.alloc(), x.priv_raw_begin()
, x.size(), container_detail::to_raw_pointer(this->m_holder.start())); , x.size(), this->priv_raw_begin());
} }
//! <b>Effects</b>: Move constructor. Moves x's resources to *this. //! <b>Effects</b>: Move constructor. Moves x's resources to *this.
@@ -1012,8 +1012,8 @@ class vector
this->num_alloc += x.size() != 0; this->num_alloc += x.size() != 0;
#endif #endif
::boost::container::uninitialized_copy_alloc_n_source ::boost::container::uninitialized_copy_alloc_n_source
( this->m_holder.alloc(), container_detail::to_raw_pointer(x.m_holder.start()) ( this->m_holder.alloc(), x.priv_raw_begin()
, x.size(), container_detail::to_raw_pointer(this->m_holder.start())); , x.size(), this->priv_raw_begin());
} }
//! <b>Effects</b>: Move constructor using the specified allocator. //! <b>Effects</b>: Move constructor using the specified allocator.
@@ -1037,8 +1037,8 @@ class vector
this->num_alloc += n != 0; this->num_alloc += n != 0;
#endif #endif
::boost::container::uninitialized_move_alloc_n_source ::boost::container::uninitialized_move_alloc_n_source
( this->m_holder.alloc(), container_detail::to_raw_pointer(x.m_holder.start()) ( this->m_holder.alloc(), x.priv_raw_begin()
, n, container_detail::to_raw_pointer(this->m_holder.start())); , n, this->priv_raw_begin());
} }
} }
@@ -1051,7 +1051,7 @@ class vector
~vector() BOOST_NOEXCEPT_OR_NOTHROW ~vector() BOOST_NOEXCEPT_OR_NOTHROW
{ {
boost::container::destroy_alloc_n boost::container::destroy_alloc_n
(this->get_stored_allocator(), container_detail::to_raw_pointer(this->m_holder.start()), this->m_holder.m_size); (this->get_stored_allocator(), this->priv_raw_begin(), this->m_holder.m_size);
//vector_alloc_holder deallocates the data //vector_alloc_holder deallocates the data
} }
@@ -1177,7 +1177,7 @@ class vector
if (first == last){ if (first == last){
//There are no more elements in the sequence, erase remaining //There are no more elements in the sequence, erase remaining
T* const end_pos = this->back_raw(); T* const end_pos = this->priv_raw_end();
const size_type n = static_cast<size_type>(end_pos - container_detail::iterator_to_raw_pointer(cur)); const size_type n = static_cast<size_type>(end_pos - container_detail::iterator_to_raw_pointer(cur));
this->priv_destroy_last_n(n); this->priv_destroy_last_n(n);
} }
@@ -1696,7 +1696,7 @@ class vector
//! //!
//! <b>Complexity</b>: Constant. //! <b>Complexity</b>: Constant.
T* data() BOOST_NOEXCEPT_OR_NOTHROW T* data() BOOST_NOEXCEPT_OR_NOTHROW
{ return container_detail::to_raw_pointer(this->m_holder.start()); } { return this->priv_raw_begin(); }
//! <b>Returns</b>: A pointer such that [data(),data() + size()) is a valid range. //! <b>Returns</b>: A pointer such that [data(),data() + size()) is a valid range.
//! For a non-empty vector, data() == &front(). //! For a non-empty vector, data() == &front().
@@ -1705,7 +1705,7 @@ class vector
//! //!
//! <b>Complexity</b>: Constant. //! <b>Complexity</b>: Constant.
const T * data() const BOOST_NOEXCEPT_OR_NOTHROW const T * data() const BOOST_NOEXCEPT_OR_NOTHROW
{ return container_detail::to_raw_pointer(this->m_holder.start()); } { return this->priv_raw_begin(); }
////////////////////////////////////////////// //////////////////////////////////////////////
// //
@@ -1726,7 +1726,7 @@ class vector
{ {
if (BOOST_LIKELY(this->room_enough())){ if (BOOST_LIKELY(this->room_enough())){
//There is more memory, just construct a new object at the end //There is more memory, just construct a new object at the end
allocator_traits_type::construct(this->m_holder.alloc(), this->back_raw(), ::boost::forward<Args>(args)...); allocator_traits_type::construct(this->m_holder.alloc(), this->priv_raw_end(), ::boost::forward<Args>(args)...);
++this->m_holder.m_size; ++this->m_holder.m_size;
} }
else{ else{
@@ -1750,7 +1750,7 @@ class vector
const bool is_room_enough = this->room_enough() || (alloc_version::value == 2 && this->m_holder.try_expand_fwd(1u)); const bool is_room_enough = this->room_enough() || (alloc_version::value == 2 && this->m_holder.try_expand_fwd(1u));
if (BOOST_LIKELY(is_room_enough)){ if (BOOST_LIKELY(is_room_enough)){
//There is more memory, just construct a new object at the end //There is more memory, just construct a new object at the end
allocator_traits_type::construct(this->m_holder.alloc(), this->back_raw(), ::boost::forward<Args>(args)...); allocator_traits_type::construct(this->m_holder.alloc(), this->priv_raw_end(), ::boost::forward<Args>(args)...);
++this->m_holder.m_size; ++this->m_holder.m_size;
} }
return is_room_enough; return is_room_enough;
@@ -1784,7 +1784,7 @@ class vector
{\ {\
if (BOOST_LIKELY(this->room_enough())){\ if (BOOST_LIKELY(this->room_enough())){\
allocator_traits_type::construct (this->m_holder.alloc()\ allocator_traits_type::construct (this->m_holder.alloc()\
, this->back_raw() BOOST_MOVE_I##N BOOST_MOVE_FWD##N);\ , this->priv_raw_end() BOOST_MOVE_I##N BOOST_MOVE_FWD##N);\
++this->m_holder.m_size;\ ++this->m_holder.m_size;\
}\ }\
else{\ else{\
@@ -1800,7 +1800,7 @@ class vector
const bool is_room_enough = this->room_enough() || (alloc_version::value == 2 && this->m_holder.try_expand_fwd(1u));\ const bool is_room_enough = this->room_enough() || (alloc_version::value == 2 && this->m_holder.try_expand_fwd(1u));\
if (BOOST_LIKELY(is_room_enough)){\ if (BOOST_LIKELY(is_room_enough)){\
allocator_traits_type::construct (this->m_holder.alloc()\ allocator_traits_type::construct (this->m_holder.alloc()\
, this->back_raw() BOOST_MOVE_I##N BOOST_MOVE_FWD##N);\ , this->priv_raw_end() BOOST_MOVE_I##N BOOST_MOVE_FWD##N);\
++this->m_holder.m_size;\ ++this->m_holder.m_size;\
}\ }\
return is_room_enough;\ return is_room_enough;\
@@ -1993,7 +1993,7 @@ class vector
BOOST_ASSERT(this->priv_in_range(position)); BOOST_ASSERT(this->priv_in_range(position));
const pointer p = vector_iterator_get_ptr(position); const pointer p = vector_iterator_get_ptr(position);
T *const pos_ptr = container_detail::to_raw_pointer(p); T *const pos_ptr = container_detail::to_raw_pointer(p);
T *const beg_ptr = container_detail::to_raw_pointer(this->m_holder.start()); 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 new_end_ptr = ::boost::container::move(pos_ptr + 1, beg_ptr + this->m_holder.m_size, pos_ptr);
//Move elements forward and destroy last //Move elements forward and destroy last
this->priv_destroy_last(pos_ptr == new_end_ptr); this->priv_destroy_last(pos_ptr == new_end_ptr);
@@ -2008,11 +2008,10 @@ class vector
//! plus linear to the elements between pos and the last element. //! plus linear to the elements between pos and the last element.
iterator erase(const_iterator first, const_iterator last) iterator erase(const_iterator first, const_iterator last)
{ {
BOOST_ASSERT(first <= last); BOOST_ASSERT(first == last ||
BOOST_ASSERT(first == last || this->priv_in_range(first)); (first < last && this->priv_in_range(first) && this->priv_in_range_or_end(last)));
BOOST_ASSERT(first == last || this->priv_in_range_or_end(last));
if (first != last){ if (first != last){
T* const old_end_ptr = this->back_raw(); T* const old_end_ptr = this->priv_raw_end();
T* const first_ptr = container_detail::to_raw_pointer(vector_iterator_get_ptr(first)); T* const first_ptr = container_detail::to_raw_pointer(vector_iterator_get_ptr(first));
T* const last_ptr = container_detail::to_raw_pointer(vector_iterator_get_ptr(last)); T* const last_ptr = container_detail::to_raw_pointer(vector_iterator_get_ptr(last));
T* const ptr = container_detail::to_raw_pointer(boost::container::move(last_ptr, old_end_ptr, first_ptr)); T* const ptr = container_detail::to_raw_pointer(boost::container::move(last_ptr, old_end_ptr, first_ptr));
@@ -2159,7 +2158,7 @@ class vector
{ {
const size_type old_size_pos = this->size(); const size_type old_size_pos = this->size();
this->reserve(old_size_pos + element_count); this->reserve(old_size_pos + element_count);
T* const begin_ptr = container_detail::to_raw_pointer(this->m_holder.start()); T* const begin_ptr = this->priv_raw_begin();
size_type insertions_left = element_count; size_type insertions_left = element_count;
size_type prev_pos = old_size_pos; size_type prev_pos = old_size_pos;
size_type old_hole_size = element_count; size_type old_hole_size = element_count;
@@ -2215,48 +2214,55 @@ class vector
void priv_merge(UniqueBool, BidirIt first, BidirIt last, Compare comp) void priv_merge(UniqueBool, BidirIt first, BidirIt last, Compare comp)
{ {
size_type const n = static_cast<size_type>(boost::container::iterator_distance(first, last)); size_type const n = static_cast<size_type>(boost::container::iterator_distance(first, last));
if(BOOST_LIKELY(n)){ size_type const s = this->size();
size_type const s = this->size(); if(BOOST_LIKELY(s)){
if(BOOST_LIKELY(s)){ size_type const c = this->capacity();
size_type const c = this->capacity(); size_type const free_c = (c - s);
size_type const free_c = (c - s); //Use a new buffer if current one is too small for new elements,
//Use a new buffer if current one is too small for new elements, //or there is no room for position indexes
//or there is no room for position indexes if(free_c < n){
bool new_buffer = false; size_type const new_size = s + n;
if(free_c < n){ size_type new_cap = new_size;
new_buffer = true; pointer p = pointer();
} p = this->m_holder.allocation_command(allocate_new, new_size, new_cap, p);
else if(!UniqueBool::value && free_c >= n){ this->priv_merge_in_new_buffer(UniqueBool(), first, n, comp, p, new_cap);
typedef container_detail::vector_merge_cursor<T, size_type, BidirIt, Compare> inserter_t; }
T* const pbeg = container_detail::to_raw_pointer(m_holder.start()); else if(!UniqueBool::value && free_c >= n){
return this->priv_insert_ordered_at(n, inserter_t(pbeg, pbeg + s, last, comp)); typedef container_detail::vector_merge_cursor<T, size_type, BidirIt, Compare> inserter_t;
} T* const pbeg = this->priv_raw_begin();
else if(UniqueBool::value){ //Query for room to store n + 1 indexes (+1 to guarantee potential alignment overhead). return this->priv_insert_ordered_at(n, inserter_t(pbeg, pbeg + s, last, comp));
//No need to destroy them as they are integral types, which simplifies things a lot. }
std::size_t const sz_vlt = sizeof(value_type); else{ //UniqueBool::value == true and free_c >= n
std::size_t const sz_szt = sizeof(size_type); std::size_t remaining = n;
new_buffer = (c-s-n)*sz_vlt/sz_szt < (n+1); static const std::size_t PosCount = 64u;
} size_type positions[PosCount];
size_type *indexes = 0;
if(new_buffer){ while(remaining){
size_type const new_size = s + n; //Query for room to store indexes in the remaining buffer
size_type new_cap = new_size;
pointer p = pointer();
p = this->m_holder.allocation_command(allocate_new, new_size, new_cap, p);
this->priv_merge_in_new_buffer(UniqueBool(), first, n, comp, p, new_cap);
}
else{
//Use trailing memory to store position offsets
uintptr_t const szt_align_mask = container_detail::alignment_of<size_type>::value - 1; uintptr_t const szt_align_mask = container_detail::alignment_of<size_type>::value - 1;
boost::uintptr_t const addr = boost::uintptr_t(container_detail::to_raw_pointer(m_holder.start()) + s + n); boost::uintptr_t const addr = boost::uintptr_t(this->priv_raw_begin() + s + n);
//Align memory before casting to address boost::uintptr_t const capaddr = boost::uintptr_t(this->priv_raw_begin() + c);
size_type *const paddr = reinterpret_cast<size_type *>((addr + szt_align_mask) & ~szt_align_mask); boost::uintptr_t const aligned_addr = (addr + szt_align_mask) & ~szt_align_mask;
this->priv_insert_ordered_range(UniqueBool(), n, first, last, paddr, comp); indexes = reinterpret_cast<size_type *>(aligned_addr);
std::size_t index_capacity = (aligned_addr >= capaddr) ? 0u : (capaddr - addr)/sizeof(size_type);
//Capacity is constant, we're not going to change it
if(index_capacity < PosCount){
indexes = positions;
index_capacity = PosCount;
}
if(index_capacity > remaining)
index_capacity = remaining;
BidirIt limit = first;
boost::container::iterator_advance(limit, index_capacity);
this->priv_insert_ordered_range(UniqueBool(), index_capacity, first, limit, indexes, comp);
first = limit;
remaining -= index_capacity;
} }
} }
else{ }
this->insert(this->cend(), n, first, last); else{
} this->insert(this->cend(), n, first, last);
} }
} }
@@ -2276,7 +2282,7 @@ class vector
//bool const linear = !s || !n || (s <= n) || ((s+n)/n/2 < logN); //bool const linear = !s || !n || (s <= n) || ((s+n)/n/2 < logN);
size_type const s = this->size(); size_type const s = this->size();
size_type remaining = n; size_type remaining = n;
T* const pbeg = container_detail::to_raw_pointer(m_holder.start()); T* const pbeg = this->priv_raw_begin();
T* const pend = pbeg + s; T* const pend = pbeg + s;
T* pcur = pbeg; T* pcur = pbeg;
size_type *position = positions; size_type *position = positions;
@@ -2315,7 +2321,7 @@ class vector
allocator_type &a = this->m_holder.alloc(); allocator_type &a = this->m_holder.alloc();
typename value_traits::ArrayDeallocator new_buffer_deallocator(new_storage, a, new_cap); typename value_traits::ArrayDeallocator new_buffer_deallocator(new_storage, a, new_cap);
typename value_traits::ArrayDestructor new_values_destroyer(new_storage, a, 0u); typename value_traits::ArrayDestructor new_values_destroyer(new_storage, a, 0u);
T* pbeg = container_detail::to_raw_pointer(m_holder.start()); T* pbeg = this->priv_raw_begin();
size_type const old_size = this->size(); size_type const old_size = this->size();
T* const pend = pbeg + old_size; T* const pend = pbeg + old_size;
T* d_first = container_detail::to_raw_pointer(new_storage); T* d_first = container_detail::to_raw_pointer(new_storage);
@@ -2369,9 +2375,6 @@ class vector
pointer back_ptr() const pointer back_ptr() const
{ return this->m_holder.start() + this->m_holder.m_size; } { return this->m_holder.start() + this->m_holder.m_size; }
T* back_raw() const
{ return container_detail::to_raw_pointer(this->m_holder.start()) + this->m_holder.m_size; }
size_type priv_index_of(pointer p) const size_type priv_index_of(pointer p) const
{ {
BOOST_ASSERT(this->m_holder.start() <= p); BOOST_ASSERT(this->m_holder.start() <= p);
@@ -2388,8 +2391,8 @@ class vector
this->capacity() < x.size()){ this->capacity() < x.size()){
throw_bad_alloc(); throw_bad_alloc();
} }
T* const this_start = container_detail::to_raw_pointer(m_holder.start()); T* const this_start = this->priv_raw_begin();
T* const other_start = container_detail::to_raw_pointer(x.m_holder.start()); T* const other_start = x.priv_raw_begin();
const size_type this_sz = m_holder.m_size; const size_type this_sz = m_holder.m_size;
const size_type other_sz = static_cast<size_type>(x.m_holder.m_size); const size_type other_sz = static_cast<size_type>(x.m_holder.m_size);
boost::container::move_assign_range_alloc_n(this->m_holder.alloc(), other_start, other_sz, this_start, this_sz); boost::container::move_assign_range_alloc_n(this->m_holder.alloc(), other_start, other_sz, this_start, this_sz);
@@ -2445,8 +2448,8 @@ class vector
this->capacity() < x.size()){ this->capacity() < x.size()){
throw_bad_alloc(); throw_bad_alloc();
} }
T* const this_start = container_detail::to_raw_pointer(m_holder.start()); T* const this_start = this->priv_raw_begin();
T* const other_start = container_detail::to_raw_pointer(x.m_holder.start()); T* const other_start = x.priv_raw_begin();
const size_type this_sz = m_holder.m_size; const size_type this_sz = m_holder.m_size;
const size_type other_sz = static_cast<size_type>(x.m_holder.m_size); const size_type other_sz = static_cast<size_type>(x.m_holder.m_size);
boost::container::copy_assign_range_alloc_n(this->m_holder.alloc(), other_start, other_sz, this_start, this_sz); boost::container::copy_assign_range_alloc_n(this->m_holder.alloc(), other_start, other_sz, this_start, this_sz);
@@ -2470,8 +2473,7 @@ class vector
this->shrink_to_fit(); this->shrink_to_fit();
} }
container_detail::assign_alloc(this_alloc, x_alloc, flag); container_detail::assign_alloc(this_alloc, x_alloc, flag);
this->assign( container_detail::to_raw_pointer(x.m_holder.start()) this->assign( x.priv_raw_begin(), x.priv_raw_end() );
, container_detail::to_raw_pointer(x.m_holder.start() + x.m_holder.m_size));
} }
template<class Vector> //Template it to avoid it in explicit instantiations template<class Vector> //Template it to avoid it in explicit instantiations
@@ -2525,7 +2527,7 @@ class vector
pointer const p = allocator_traits_type::allocate(this->m_holder.alloc(), new_cap, this->m_holder.m_start); pointer const p = allocator_traits_type::allocate(this->m_holder.alloc(), new_cap, this->m_holder.m_start);
//We will reuse insert code, so create a dummy input iterator //We will reuse insert code, so create a dummy input iterator
this->priv_forward_range_insert_new_allocation this->priv_forward_range_insert_new_allocation
( container_detail::to_raw_pointer(p), new_cap, this->back_raw(), 0, this->priv_dummy_empty_proxy()); ( container_detail::to_raw_pointer(p), new_cap, this->priv_raw_end(), 0, this->priv_dummy_empty_proxy());
} }
void priv_reserve_no_capacity(size_type new_cap, version_2) void priv_reserve_no_capacity(size_type new_cap, version_2)
@@ -2547,7 +2549,7 @@ class vector
} }
else{ //If there is no forward expansion, move objects, we will reuse insertion code else{ //If there is no forward expansion, move objects, we will reuse insertion code
T * const new_mem = container_detail::to_raw_pointer(ret); T * const new_mem = container_detail::to_raw_pointer(ret);
T * const ins_pos = this->back_raw(); T * const ins_pos = this->priv_raw_end();
if(reuse){ //Backwards (and possibly forward) expansion if(reuse){ //Backwards (and possibly forward) expansion
#ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
++this->num_expand_bwd; ++this->num_expand_bwd;
@@ -2569,7 +2571,7 @@ class vector
{ {
(void)moved; (void)moved;
if(!(value_traits::trivial_dctr || (value_traits::trivial_dctr_after_move && moved))){ if(!(value_traits::trivial_dctr || (value_traits::trivial_dctr_after_move && moved))){
value_type* const p = this->back_raw() - 1; value_type* const p = this->priv_raw_end() - 1;
allocator_traits_type::destroy(this->get_stored_allocator(), p); allocator_traits_type::destroy(this->get_stored_allocator(), p);
} }
--this->m_holder.m_size; --this->m_holder.m_size;
@@ -2579,7 +2581,7 @@ class vector
{ {
BOOST_ASSERT(n <= this->m_holder.m_size); BOOST_ASSERT(n <= this->m_holder.m_size);
if(!value_traits::trivial_dctr){ if(!value_traits::trivial_dctr){
T* const destroy_pos = container_detail::to_raw_pointer(this->m_holder.start()) + (this->m_holder.m_size-n); 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(), destroy_pos, n);
} }
this->m_holder.m_size -= n; this->m_holder.m_size -= n;
@@ -2588,7 +2590,7 @@ class vector
template<class InpIt> template<class InpIt>
void priv_uninitialized_construct_at_end(InpIt first, InpIt last) void priv_uninitialized_construct_at_end(InpIt first, InpIt last)
{ {
T* const old_end_pos = this->back_raw(); 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); T* const new_end_pos = boost::container::uninitialized_copy_alloc(this->m_holder.alloc(), first, last, old_end_pos);
this->m_holder.m_size += new_end_pos - old_end_pos; this->m_holder.m_size += new_end_pos - old_end_pos;
} }
@@ -2596,7 +2598,7 @@ class vector
void priv_destroy_all() BOOST_NOEXCEPT_OR_NOTHROW void priv_destroy_all() BOOST_NOEXCEPT_OR_NOTHROW
{ {
boost::container::destroy_alloc_n boost::container::destroy_alloc_n
(this->get_stored_allocator(), container_detail::to_raw_pointer(this->m_holder.start()), this->m_holder.m_size); (this->get_stored_allocator(), this->priv_raw_begin(), this->m_holder.m_size);
this->m_holder.m_size = 0; this->m_holder.m_size = 0;
} }
@@ -2620,9 +2622,7 @@ class vector
if (BOOST_LIKELY(this->room_enough())){ if (BOOST_LIKELY(this->room_enough())){
//There is more memory, just construct a new object at the end //There is more memory, just construct a new object at the end
allocator_traits_type::construct allocator_traits_type::construct
( this->m_holder.alloc() ( this->m_holder.alloc(), this->priv_raw_end(), ::boost::forward<U>(u) );
, container_detail::to_raw_pointer(this->m_holder.start() + this->m_holder.m_size)
, ::boost::forward<U>(u) );
++this->m_holder.m_size; ++this->m_holder.m_size;
} }
else{ else{
@@ -2679,8 +2679,7 @@ class vector
#endif #endif
this->priv_forward_range_insert_new_allocation this->priv_forward_range_insert_new_allocation
( container_detail::to_raw_pointer(p), sz ( container_detail::to_raw_pointer(p), sz
, container_detail::to_raw_pointer(this->m_holder.start()) , this->priv_raw_begin(), 0, this->priv_dummy_empty_proxy());
, 0, this->priv_dummy_empty_proxy());
} }
} }
} }
@@ -2727,7 +2726,8 @@ class vector
const size_type new_cap = this->m_holder.next_capacity(n); const size_type new_cap = this->m_holder.next_capacity(n);
//Pass the hint so that allocators can take advantage of this. //Pass the hint so that allocators can take advantage of this.
T * const new_buf = container_detail::to_raw_pointer(allocator_traits_type::allocate(this->m_holder.alloc(), new_cap, this->m_holder.m_start)); T * const new_buf = container_detail::to_raw_pointer
(allocator_traits_type::allocate(this->m_holder.alloc(), new_cap, this->m_holder.m_start));
#ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
++this->num_alloc; ++this->num_alloc;
#endif #endif
@@ -2742,7 +2742,7 @@ class vector
{ {
//Check if we have enough memory or try to expand current memory //Check if we have enough memory or try to expand current memory
T *const raw_pos = container_detail::to_raw_pointer(pos); T *const raw_pos = container_detail::to_raw_pointer(pos);
const size_type n_pos = raw_pos - container_detail::to_raw_pointer(this->m_holder.start()); const size_type n_pos = raw_pos - this->priv_raw_begin();
//There is not enough memory, allocate a new //There is not enough memory, allocate a new
//buffer or expand the old one. //buffer or expand the old one.
@@ -2798,7 +2798,7 @@ class vector
else{ else{
//Expand forward //Expand forward
T *const raw_pos = container_detail::to_raw_pointer(pos); T *const raw_pos = container_detail::to_raw_pointer(pos);
const size_type n_pos = raw_pos - container_detail::to_raw_pointer(this->m_holder.start()); const size_type n_pos = raw_pos - this->priv_raw_begin();
this->priv_forward_range_insert_expand_forward(raw_pos, n, insert_range_proxy); this->priv_forward_range_insert_expand_forward(raw_pos, n, insert_range_proxy);
return iterator(this->m_holder.start() + n_pos); return iterator(this->m_holder.start() + n_pos);
} }
@@ -2883,7 +2883,7 @@ class vector
BOOST_ASSERT(first_pos <= last_pos); BOOST_ASSERT(first_pos <= last_pos);
BOOST_ASSERT(last_pos <= limit_pos); BOOST_ASSERT(last_pos <= limit_pos);
// //
T* const begin_ptr = container_detail::to_raw_pointer(this->m_holder.start()); T* const begin_ptr = this->priv_raw_begin();
T* const first_ptr = begin_ptr + first_pos; T* const first_ptr = begin_ptr + first_pos;
T* const last_ptr = begin_ptr + last_pos; T* const last_ptr = begin_ptr + last_pos;
@@ -2913,10 +2913,16 @@ class vector
} }
private: private:
T *priv_raw_begin() const
{ return container_detail::to_raw_pointer(m_holder.start()); }
T* priv_raw_end() const
{ return this->priv_raw_begin() + this->m_holder.m_size; }
template <class InsertionProxy> template <class InsertionProxy>
void priv_forward_range_insert_at_end_expand_forward(const size_type n, InsertionProxy insert_range_proxy) void priv_forward_range_insert_at_end_expand_forward(const size_type n, InsertionProxy insert_range_proxy)
{ {
T* const old_finish = this->back_raw(); T* const old_finish = this->priv_raw_end();
insert_range_proxy.uninitialized_copy_n_and_update(this->m_holder.alloc(), old_finish, n); insert_range_proxy.uninitialized_copy_n_and_update(this->m_holder.alloc(), old_finish, n);
this->m_holder.m_size += n; this->m_holder.m_size += n;
} }
@@ -2927,7 +2933,7 @@ class vector
//n can't be 0, because there is nothing to do in that case //n can't be 0, because there is nothing to do in that case
if(BOOST_UNLIKELY(!n)) return; if(BOOST_UNLIKELY(!n)) return;
//There is enough memory //There is enough memory
T* const old_finish = this->back_raw(); T* const old_finish = this->priv_raw_end();
const size_type elems_after = old_finish - pos; const size_type elems_after = old_finish - pos;
if (!elems_after){ if (!elems_after){
@@ -2978,10 +2984,10 @@ class vector
//Initialize with [begin(), pos) old buffer //Initialize with [begin(), pos) old buffer
//the start of the new buffer //the start of the new buffer
T * const old_buffer = container_detail::to_raw_pointer(this->m_holder.start()); T * const old_buffer = this->priv_raw_begin();
if(old_buffer){ if(old_buffer){
new_finish = ::boost::container::uninitialized_move_alloc new_finish = ::boost::container::uninitialized_move_alloc
(this->m_holder.alloc(), container_detail::to_raw_pointer(this->m_holder.start()), pos, old_finish = new_finish); (this->m_holder.alloc(), this->priv_raw_begin(), pos, old_finish = new_finish);
new_values_destroyer.increment_size(new_finish - old_finish); new_values_destroyer.increment_size(new_finish - old_finish);
} }
//Initialize new objects, starting from previous point //Initialize new objects, starting from previous point
@@ -3015,7 +3021,7 @@ class vector
{ {
//n can be zero to just expand capacity //n can be zero to just expand capacity
//Backup old data //Backup old data
T* const old_start = container_detail::to_raw_pointer(this->m_holder.start()); T* const old_start = this->priv_raw_begin();
const size_type old_size = this->m_holder.m_size; const size_type old_size = this->m_holder.m_size;
T* const old_finish = old_start + old_size; T* const old_finish = old_start + old_size;