src/cxx_supportlib/vendor-modified/boost/container/vector.hpp in passenger-5.3.3 vs src/cxx_supportlib/vendor-modified/boost/container/vector.hpp in passenger-5.3.4

- old
+ new

@@ -25,23 +25,25 @@ // container #include <boost/container/container_fwd.hpp> #include <boost/container/allocator_traits.hpp> #include <boost/container/new_allocator.hpp> //new_allocator #include <boost/container/throw_exception.hpp> +#include <boost/container/options.hpp> // container detail #include <boost/container/detail/advanced_insert_int.hpp> #include <boost/container/detail/algorithm.hpp> //equal() #include <boost/container/detail/alloc_helpers.hpp> #include <boost/container/detail/allocation_type.hpp> #include <boost/container/detail/copy_move_algo.hpp> #include <boost/container/detail/destroyers.hpp> #include <boost/container/detail/iterator.hpp> #include <boost/container/detail/iterators.hpp> -#include <boost/container/detail/iterator_to_raw_pointer.hpp> +#include <boost/move/detail/iterator_to_raw_pointer.hpp> #include <boost/container/detail/mpl.hpp> #include <boost/container/detail/next_capacity.hpp> -#include <boost/container/detail/to_raw_pointer.hpp> +#include <boost/container/detail/value_functors.hpp> +#include <boost/move/detail/to_raw_pointer.hpp> #include <boost/container/detail/type_traits.hpp> #include <boost/container/detail/version_type.hpp> // intrusive #include <boost/intrusive/pointer_traits.hpp> // move @@ -52,10 +54,15 @@ // move/detail #if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) #include <boost/move/detail/fwd_macros.hpp> #endif #include <boost/move/detail/move_helpers.hpp> +// move/algo +#include <boost/move/algo/adaptive_merge.hpp> +#include <boost/move/algo/unique.hpp> +#include <boost/move/algo/predicate.hpp> +#include <boost/move/algo/detail/set_difference.hpp> // other #include <boost/core/no_exceptions_support.hpp> #include <boost/assert.hpp> #include <boost/cstdint.hpp> @@ -67,24 +74,19 @@ namespace boost { namespace container { #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED -//#define BOOST_CONTAINER_VECTOR_ITERATOR_IS_POINTER -namespace container_detail { - -#ifndef BOOST_CONTAINER_VECTOR_ITERATOR_IS_POINTER - template <class Pointer, bool IsConst> class vec_iterator { public: typedef std::random_access_iterator_tag iterator_category; typedef typename boost::intrusive::pointer_traits<Pointer>::element_type value_type; typedef typename boost::intrusive::pointer_traits<Pointer>::difference_type difference_type; - typedef typename if_c + typedef typename dtl::if_c < IsConst , typename boost::intrusive::pointer_traits<Pointer>::template rebind_pointer<const value_type>::type , Pointer >::type pointer; @@ -208,138 +210,65 @@ BiDirPosConstIt last_position_it; BiDirValueIt last_value_it; }; -template<class T, class SizeType, class BiDirValueIt, class Comp> -struct vector_merge_cursor -{ - typedef SizeType size_type; - typedef typename iterator_traits<BiDirValueIt>::reference reference; +struct initial_capacity_t{}; - BOOST_CONTAINER_FORCEINLINE vector_merge_cursor(T *pbeg, T *plast, BiDirValueIt valueit, Comp &cmp) - : m_pbeg(pbeg), m_pcur(--plast), m_valueit(valueit), m_cmp(cmp) - {} - - void operator --() - { - --m_valueit; - const T &t = *m_valueit; - while((m_pcur + 1) != m_pbeg){ - if(!m_cmp(t, *m_pcur)){ - break; - } - --m_pcur; - } - } - - BOOST_CONTAINER_FORCEINLINE size_type get_pos() const - { return static_cast<size_type>((m_pcur + 1) - m_pbeg); } - - BOOST_CONTAINER_FORCEINLINE reference get_val() - { return *m_valueit; } - - T *const m_pbeg; - T *m_pcur; - BiDirValueIt m_valueit; - Comp &m_cmp; -}; - -} //namespace container_detail { - template<class Pointer, bool IsConst> -BOOST_CONTAINER_FORCEINLINE const Pointer &vector_iterator_get_ptr(const container_detail::vec_iterator<Pointer, IsConst> &it) BOOST_NOEXCEPT_OR_NOTHROW +BOOST_CONTAINER_FORCEINLINE const Pointer &vector_iterator_get_ptr(const vec_iterator<Pointer, IsConst> &it) BOOST_NOEXCEPT_OR_NOTHROW { return it.get_ptr(); } template<class Pointer, bool IsConst> -BOOST_CONTAINER_FORCEINLINE Pointer &get_ptr(container_detail::vec_iterator<Pointer, IsConst> &it) BOOST_NOEXCEPT_OR_NOTHROW +BOOST_CONTAINER_FORCEINLINE Pointer &get_ptr(vec_iterator<Pointer, IsConst> &it) BOOST_NOEXCEPT_OR_NOTHROW { return it.get_ptr(); } -namespace container_detail { +struct vector_uninitialized_size_t {}; +static const vector_uninitialized_size_t vector_uninitialized_size = vector_uninitialized_size_t(); -#else //ifndef BOOST_CONTAINER_VECTOR_ITERATOR_IS_POINTER - -template< class MaybeConstPointer - , bool ElementTypeIsConst - = is_const< typename boost::intrusive::pointer_traits<MaybeConstPointer>::element_type>::value > -struct vector_get_ptr_pointer_to_non_const -{ - typedef MaybeConstPointer const_pointer; - typedef boost::intrusive::pointer_traits<const_pointer> pointer_traits_t; - typedef typename pointer_traits_t::element_type element_type; - typedef typename remove_const<element_type>::type non_const_element_type; - typedef typename pointer_traits_t - ::template rebind_pointer<non_const_element_type>::type return_type; - - BOOST_CONTAINER_FORCEINLINE static return_type get_ptr(const const_pointer &ptr) BOOST_NOEXCEPT_OR_NOTHROW - { return boost::intrusive::pointer_traits<return_type>::const_cast_from(ptr); } -}; - -template<class Pointer> -struct vector_get_ptr_pointer_to_non_const<Pointer, false> -{ - typedef const Pointer & return_type; - BOOST_CONTAINER_FORCEINLINE static return_type get_ptr(const Pointer &ptr) BOOST_NOEXCEPT_OR_NOTHROW - { return ptr; } -}; - -} //namespace container_detail { - -template<class MaybeConstPointer> -BOOST_CONTAINER_FORCEINLINE typename container_detail::vector_get_ptr_pointer_to_non_const<MaybeConstPointer>::return_type - vector_iterator_get_ptr(const MaybeConstPointer &ptr) BOOST_NOEXCEPT_OR_NOTHROW -{ - return container_detail::vector_get_ptr_pointer_to_non_const<MaybeConstPointer>::get_ptr(ptr); -} - -namespace container_detail { - -#endif //#ifndef BOOST_CONTAINER_VECTOR_ITERATOR_IS_POINTER - -struct uninitialized_size_t {}; -static const uninitialized_size_t uninitialized_size = uninitialized_size_t(); - template <class T> struct vector_value_traits_base { - static const bool trivial_dctr = is_trivially_destructible<T>::value; + 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 = is_trivially_copy_constructible<T>::value; - static const bool nothrow_copy = is_nothrow_copy_constructible<T>::value || trivial_copy; - static const bool trivial_assign = is_trivially_copy_assignable<T>::value; - static const bool nothrow_assign = is_nothrow_copy_assignable<T>::value || trivial_assign; + 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> struct vector_value_traits : public vector_value_traits_base<typename Allocator::value_type> { typedef vector_value_traits_base<typename Allocator::value_type> base_t; //This is the anti-exception array destructor //to deallocate values already constructed - typedef typename container_detail::if_c + typedef typename dtl::if_c <base_t::trivial_dctr - ,container_detail::null_scoped_destructor_n<Allocator> - ,container_detail::scoped_destructor_n<Allocator> + ,dtl::null_scoped_destructor_n<Allocator> + ,dtl::scoped_destructor_n<Allocator> >::type ArrayDestructor; //This is the anti-exception array deallocator - typedef container_detail::scoped_array_deallocator<Allocator> ArrayDeallocator; + typedef dtl::scoped_array_deallocator<Allocator> ArrayDeallocator; }; //!This struct deallocates and allocated memory template < class Allocator - , class AllocatorVersion = typename container_detail::version<Allocator>::type + , class StoredSizeType + , class AllocatorVersion = typename dtl::version<Allocator>::type > struct vector_alloc_holder : public Allocator { private: BOOST_MOVABLE_BUT_NOT_COPYABLE(vector_alloc_holder) public: - typedef Allocator allocator_type; + typedef Allocator allocator_type; + typedef StoredSizeType stored_size_type; typedef boost::container::allocator_traits<Allocator> allocator_traits_type; typedef typename allocator_traits_type::pointer pointer; typedef typename allocator_traits_type::size_type size_type; typedef typename allocator_traits_type::value_type value_type; @@ -359,11 +288,11 @@ return all_storage_propagable && (propagate_allocator || allocator_traits_type::equal(l_a, r_a)); } //Constructor, does not throw vector_alloc_holder() - BOOST_NOEXCEPT_IF(container_detail::is_nothrow_default_constructible<Allocator>::value) + BOOST_NOEXCEPT_IF(dtl::is_nothrow_default_constructible<Allocator>::value) : Allocator(), m_start(), m_size(), m_capacity() {} //Constructor, does not throw template<class AllocConvertible> @@ -371,32 +300,38 @@ : Allocator(boost::forward<AllocConvertible>(a)), m_start(), m_size(), m_capacity() {} //Constructor, does not throw template<class AllocConvertible> - vector_alloc_holder(uninitialized_size_t, BOOST_FWD_REF(AllocConvertible) a, size_type initial_size) + vector_alloc_holder(vector_uninitialized_size_t, BOOST_FWD_REF(AllocConvertible) a, size_type initial_size) : Allocator(boost::forward<AllocConvertible>(a)) , m_start() - , m_size(initial_size) //Size is initialized here so vector should only call uninitialized_xxx after this + //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){ pointer reuse = pointer(); - m_start = this->allocation_command(allocate_new, initial_size, m_capacity = initial_size, reuse); + size_type final_cap = initial_size; + m_start = this->allocation_command(allocate_new, initial_size, final_cap, reuse); + m_capacity = static_cast<stored_size_type>(final_cap); } } //Constructor, does not throw - vector_alloc_holder(uninitialized_size_t, size_type initial_size) + vector_alloc_holder(vector_uninitialized_size_t, size_type initial_size) : Allocator() , m_start() - , m_size(initial_size) //Size is initialized here so vector should only call uninitialized_xxx after this + //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){ pointer reuse = pointer(); - m_start = this->allocation_command(allocate_new, initial_size, m_capacity = initial_size, reuse); + size_type final_cap = initial_size; + m_start = this->allocation_command(allocate_new, initial_size, final_cap, reuse); + m_capacity = static_cast<stored_size_type>(final_cap); } } vector_alloc_holder(BOOST_RV_REF(vector_alloc_holder) holder) BOOST_NOEXCEPT_OR_NOTHROW : Allocator(BOOST_MOVE_BASE(Allocator, holder)) @@ -406,67 +341,85 @@ { holder.m_start = pointer(); holder.m_size = holder.m_capacity = 0; } - vector_alloc_holder(pointer p, size_type capacity, BOOST_RV_REF(vector_alloc_holder) holder) + vector_alloc_holder(initial_capacity_t, pointer p, size_type capacity, BOOST_RV_REF(vector_alloc_holder) holder) : Allocator(BOOST_MOVE_BASE(Allocator, holder)) , m_start(p) , m_size(holder.m_size) - , m_capacity(capacity) + , m_capacity(static_cast<stored_size_type>(capacity)) { allocator_type &this_alloc = this->alloc(); allocator_type &x_alloc = holder.alloc(); if(this->is_propagable_from(x_alloc, holder.start(), this_alloc, true)){ if(this->m_capacity){ - this->alloc().deallocate(this->m_start, this->m_capacity); + this->deallocate(this->m_start, this->m_capacity); } m_start = holder.m_start; m_capacity = holder.m_capacity; holder.m_start = pointer(); holder.m_capacity = holder.m_size = 0; } else if(this->m_capacity < holder.m_size){ size_type const n = holder.m_size; pointer reuse = pointer(); - m_start = this->allocation_command(allocate_new, n, m_capacity = n, reuse); + size_type final_cap = n; + m_start = this->allocation_command(allocate_new, n, final_cap, reuse); + m_capacity = static_cast<stored_size_type>(final_cap); #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS this->num_alloc += n != 0; #endif } } - vector_alloc_holder(pointer p, size_type n) - BOOST_NOEXCEPT_IF(container_detail::is_nothrow_default_constructible<Allocator>::value) + vector_alloc_holder(initial_capacity_t, pointer p, size_type n) + BOOST_NOEXCEPT_IF(dtl::is_nothrow_default_constructible<Allocator>::value) : Allocator() , m_start(p) , m_size() - , m_capacity(n) + //n is guaranteed to fit into stored_size_type + , m_capacity(static_cast<stored_size_type>(n)) {} template<class AllocFwd> - vector_alloc_holder(pointer p, size_type n, BOOST_FWD_REF(AllocFwd) a) + vector_alloc_holder(initial_capacity_t, pointer p, size_type n, BOOST_FWD_REF(AllocFwd) a) : Allocator(::boost::forward<AllocFwd>(a)) , m_start(p) , m_size() , m_capacity(n) {} BOOST_CONTAINER_FORCEINLINE ~vector_alloc_holder() BOOST_NOEXCEPT_OR_NOTHROW { if(this->m_capacity){ - this->alloc().deallocate(this->m_start, this->m_capacity); + this->deallocate(this->m_start, this->m_capacity); } } BOOST_CONTAINER_FORCEINLINE pointer allocation_command(boost::container::allocation_type command, size_type limit_size, size_type &prefer_in_recvd_out_size, pointer &reuse) { - typedef typename container_detail::version<Allocator>::type alloc_version; + typedef typename dtl::version<Allocator>::type alloc_version; return this->priv_allocation_command(alloc_version(), command, limit_size, prefer_in_recvd_out_size, reuse); } + BOOST_CONTAINER_FORCEINLINE pointer allocate(size_type n) + { + const size_type max_alloc = allocator_traits_type::max_size(this->alloc()); + const size_type max = max_alloc <= stored_size_type(-1) ? max_alloc : stored_size_type(-1); + if ( max < n ) + boost::container::throw_length_error("get_next_capacity, allocator's max size reached"); + + return allocator_traits_type::allocate(this->alloc(), n); + } + + BOOST_CONTAINER_FORCEINLINE void deallocate(const pointer &p, size_type n) + { + allocator_traits_type::deallocate(this->alloc(), p, n); + } + bool try_expand_fwd(size_type at_least) { //There is not enough memory, try to expand the old one const size_type new_cap = this->capacity() + at_least; size_type real_cap = new_cap; @@ -480,21 +433,28 @@ this->capacity(real_cap); } return success; } - BOOST_CONTAINER_FORCEINLINE size_type next_capacity(size_type additional_objects) const + template<class GrowthFactorType> + size_type next_capacity(size_type additional_objects) const { - return next_capacity_calculator - <size_type, NextCapacityDouble //NextCapacity60Percent - >::get( allocator_traits_type::max_size(this->alloc()) - , this->m_capacity, additional_objects ); + BOOST_ASSERT(additional_objects > size_type(this->m_capacity - this->m_size)); + size_type max = allocator_traits_type::max_size(this->alloc()); + (clamp_by_stored_size_type)(max, stored_size_type()); + const size_type remaining_cap = max - size_type(this->m_capacity); + const size_type min_additional_cap = additional_objects - size_type(this->m_capacity - this->m_size); + + if ( remaining_cap < min_additional_cap ) + boost::container::throw_length_error("get_next_capacity, allocator's max size reached"); + + return GrowthFactorType()( size_type(this->m_capacity), min_additional_cap, max); } - pointer m_start; - size_type m_size; - size_type m_capacity; + pointer m_start; + stored_size_type m_size; + stored_size_type m_capacity; void swap_resources(vector_alloc_holder &x) BOOST_NOEXCEPT_OR_NOTHROW { boost::adl_move_swap(this->m_start, x.m_start); boost::adl_move_swap(this->m_size, x.m_size); @@ -514,14 +474,18 @@ { return *this; } BOOST_CONTAINER_FORCEINLINE const Allocator &alloc() const BOOST_NOEXCEPT_OR_NOTHROW { return *this; } - const pointer &start() const BOOST_NOEXCEPT_OR_NOTHROW { return m_start; } - const size_type &capacity() const BOOST_NOEXCEPT_OR_NOTHROW { return m_capacity; } - void start(const pointer &p) BOOST_NOEXCEPT_OR_NOTHROW { m_start = p; } - void capacity(const size_type &c) BOOST_NOEXCEPT_OR_NOTHROW { m_capacity = c; } + BOOST_CONTAINER_FORCEINLINE const pointer &start() const BOOST_NOEXCEPT_OR_NOTHROW + { return m_start; } + BOOST_CONTAINER_FORCEINLINE size_type capacity() const BOOST_NOEXCEPT_OR_NOTHROW + { return m_capacity; } + BOOST_CONTAINER_FORCEINLINE void start(const pointer &p) BOOST_NOEXCEPT_OR_NOTHROW + { m_start = p; } + BOOST_CONTAINER_FORCEINLINE void capacity(const size_type &c) BOOST_NOEXCEPT_OR_NOTHROW + { BOOST_ASSERT( c <= stored_size_type(-1)); m_capacity = c; } private: void priv_first_allocation(size_type cap) { if(cap){ @@ -532,52 +496,77 @@ ++this->num_alloc; #endif } } + BOOST_CONTAINER_FORCEINLINE static void clamp_by_stored_size_type(size_type &, size_type) + {} + + template<class SomeStoredSizeType> + BOOST_CONTAINER_FORCEINLINE static void clamp_by_stored_size_type(size_type &s, SomeStoredSizeType) + { + if (s >= SomeStoredSizeType(-1) ) + s = SomeStoredSizeType(-1); + } + BOOST_CONTAINER_FORCEINLINE pointer priv_allocation_command(version_1, boost::container::allocation_type command, - size_type , + size_type limit_size, size_type &prefer_in_recvd_out_size, pointer &reuse) { (void)command; BOOST_ASSERT( (command & allocate_new)); BOOST_ASSERT(!(command & nothrow_allocation)); - pointer const p = allocator_traits_type::allocate(this->alloc(), prefer_in_recvd_out_size, reuse); + //First detect overflow on smaller stored_size_types + if (limit_size > stored_size_type(-1)){ + boost::container::throw_length_error("get_next_capacity, allocator's max size reached"); + } + (clamp_by_stored_size_type)(prefer_in_recvd_out_size, stored_size_type()); + pointer const p = this->allocate(prefer_in_recvd_out_size); reuse = pointer(); return p; } pointer priv_allocation_command(version_2, boost::container::allocation_type command, size_type limit_size, size_type &prefer_in_recvd_out_size, pointer &reuse) { - return this->alloc().allocation_command(command, limit_size, prefer_in_recvd_out_size, reuse); + //First detect overflow on smaller stored_size_types + if (limit_size > stored_size_type(-1)){ + boost::container::throw_length_error("get_next_capacity, allocator's max size reached"); + } + (clamp_by_stored_size_type)(prefer_in_recvd_out_size, stored_size_type()); + //Allocate memory + pointer p = this->alloc().allocation_command(command, limit_size, prefer_in_recvd_out_size, reuse); + //If after allocation prefer_in_recvd_out_size is not representable by stored_size_type, truncate it. + (clamp_by_stored_size_type)(prefer_in_recvd_out_size, stored_size_type()); + return p; } }; //!This struct deallocates and allocated memory -template <class Allocator> -struct vector_alloc_holder<Allocator, version_0> +template <class Allocator, class StoredSizeType> +struct vector_alloc_holder<Allocator, StoredSizeType, version_0> : public Allocator { private: BOOST_MOVABLE_BUT_NOT_COPYABLE(vector_alloc_holder) public: typedef boost::container::allocator_traits<Allocator> allocator_traits_type; typedef typename allocator_traits_type::pointer pointer; typedef typename allocator_traits_type::size_type size_type; typedef typename allocator_traits_type::value_type value_type; + typedef StoredSizeType stored_size_type; - template <class OtherAllocator, class OtherAllocatorVersion> + template <class OtherAllocator, class OtherStoredSizeType, class OtherAllocatorVersion> friend struct vector_alloc_holder; //Constructor, does not throw vector_alloc_holder() - BOOST_NOEXCEPT_IF(container_detail::is_nothrow_default_constructible<Allocator>::value) + BOOST_NOEXCEPT_IF(dtl::is_nothrow_default_constructible<Allocator>::value) : Allocator(), m_size() {} //Constructor, does not throw template<class AllocConvertible> @@ -585,20 +574,20 @@ : Allocator(boost::forward<AllocConvertible>(a)), m_size() {} //Constructor, does not throw template<class AllocConvertible> - vector_alloc_holder(uninitialized_size_t, BOOST_FWD_REF(AllocConvertible) a, size_type initial_size) + vector_alloc_holder(vector_uninitialized_size_t, BOOST_FWD_REF(AllocConvertible) a, size_type initial_size) : Allocator(boost::forward<AllocConvertible>(a)) , m_size(initial_size) //Size is initialized here... { //... and capacity here, so vector, must call uninitialized_xxx in the derived constructor this->priv_first_allocation(initial_size); } //Constructor, does not throw - vector_alloc_holder(uninitialized_size_t, size_type initial_size) + vector_alloc_holder(vector_uninitialized_size_t, size_type initial_size) : Allocator() , m_size(initial_size) //Size is initialized here... { //... and capacity here, so vector, must call uninitialized_xxx in the derived constructor this->priv_first_allocation(initial_size); @@ -607,23 +596,23 @@ vector_alloc_holder(BOOST_RV_REF(vector_alloc_holder) holder) : Allocator(BOOST_MOVE_BASE(Allocator, holder)) , m_size(holder.m_size) //Size is initialized here so vector should only call uninitialized_xxx after this { ::boost::container::uninitialized_move_alloc_n - (this->alloc(), container_detail::to_raw_pointer(holder.start()), m_size, container_detail::to_raw_pointer(this->start())); + (this->alloc(), boost::movelib::to_raw_pointer(holder.start()), m_size, boost::movelib::to_raw_pointer(this->start())); } - template<class OtherAllocator, class OtherAllocatorVersion> - vector_alloc_holder(BOOST_RV_REF_BEG vector_alloc_holder<OtherAllocator, OtherAllocatorVersion> BOOST_RV_REF_END holder) + template<class OtherAllocator, class OtherStoredSizeType, class OtherAllocatorVersion> + vector_alloc_holder(BOOST_RV_REF_BEG vector_alloc_holder<OtherAllocator, OtherStoredSizeType, OtherAllocatorVersion> BOOST_RV_REF_END holder) : Allocator() , m_size(holder.m_size) //Initialize it to m_size as first_allocation can only succeed or abort { //Different allocator type so we must check we have enough storage const size_type n = holder.m_size; this->priv_first_allocation(n); ::boost::container::uninitialized_move_alloc_n - (this->alloc(), container_detail::to_raw_pointer(holder.start()), n, container_detail::to_raw_pointer(this->start())); + (this->alloc(), boost::movelib::to_raw_pointer(holder.start()), n, boost::movelib::to_raw_pointer(this->start())); } BOOST_CONTAINER_FORCEINLINE void priv_first_allocation(size_type cap) { if(cap > Allocator::internal_capacity){ @@ -634,12 +623,12 @@ BOOST_CONTAINER_FORCEINLINE void deep_swap(vector_alloc_holder &x) { this->priv_deep_swap(x); } - template<class OtherAllocator, class OtherAllocatorVersion> - void deep_swap(vector_alloc_holder<OtherAllocator, OtherAllocatorVersion> &x) + template<class OtherAllocator, class OtherStoredSizeType, class OtherAllocatorVersion> + void deep_swap(vector_alloc_holder<OtherAllocator, OtherStoredSizeType, OtherAllocatorVersion> &x) { if(this->m_size > OtherAllocator::internal_capacity || x.m_size > Allocator::internal_capacity){ throw_bad_alloc(); } this->priv_deep_swap(x); @@ -665,20 +654,20 @@ BOOST_CONTAINER_FORCEINLINE bool try_expand_fwd(size_type at_least) { return !at_least; } BOOST_CONTAINER_FORCEINLINE pointer start() const BOOST_NOEXCEPT_OR_NOTHROW { return Allocator::internal_storage(); } BOOST_CONTAINER_FORCEINLINE size_type capacity() const BOOST_NOEXCEPT_OR_NOTHROW { return Allocator::internal_capacity; } - size_type m_size; + stored_size_type m_size; private: - template<class OtherAllocator, class OtherAllocatorVersion> - void priv_deep_swap(vector_alloc_holder<OtherAllocator, OtherAllocatorVersion> &x) + template<class OtherAllocator, class OtherStoredSizeType, class OtherAllocatorVersion> + void priv_deep_swap(vector_alloc_holder<OtherAllocator, OtherStoredSizeType, OtherAllocatorVersion> &x) { const size_type MaxTmpStorage = sizeof(value_type)*Allocator::internal_capacity; - value_type *const first_this = container_detail::to_raw_pointer(this->start()); - value_type *const first_x = container_detail::to_raw_pointer(x.start()); + value_type *const first_this = boost::movelib::to_raw_pointer(this->start()); + value_type *const first_x = boost::movelib::to_raw_pointer(x.start()); if(this->m_size < x.m_size){ boost::container::deep_swap_alloc_n<MaxTmpStorage>(this->alloc(), first_this, this->m_size, first_x, x.m_size); } else{ @@ -686,43 +675,74 @@ } boost::adl_move_swap(this->m_size, x.m_size); } }; -} //namespace container_detail { +struct growth_factor_60; +template<class T, class Default> +struct default_if_void +{ + typedef T type; +}; + +template<class Default> +struct default_if_void<void, Default> +{ + typedef Default type; +}; + +template<class Options, class AllocatorSizeType> +struct get_vector_opt +{ + typedef vector_opt< typename default_if_void<typename Options::growth_factor_type, growth_factor_60>::type + , typename default_if_void<typename Options::stored_size_type, AllocatorSizeType>::type + > type; +}; + +template<class AllocatorSizeType> +struct get_vector_opt<void, AllocatorSizeType> +{ + typedef vector_opt<growth_factor_60, AllocatorSizeType> type; +}; + + #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED //! A vector is a sequence that supports random access to elements, constant //! time insertion and removal of elements at the end, and linear time insertion //! and removal of elements at the beginning or in the middle. The number of //! elements in a vector may vary dynamically; memory management is automatic. //! //! \tparam T The type of object that is stored in the vector //! \tparam Allocator The allocator used for all internal memory management -template <class T, class Allocator BOOST_CONTAINER_DOCONLY(= new_allocator<T>) > +//! \tparam Options A type produced from \c boost::container::vector_options. +template <class T, class Allocator BOOST_CONTAINER_DOCONLY(= new_allocator<T>), class Options BOOST_CONTAINER_DOCONLY(= void) > class vector { #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED - struct value_less - { - typedef typename boost::container::allocator_traits<Allocator>::value_type value_type; - bool operator()(const value_type &a, const value_type &b) const - { return a < b; } - }; + typedef typename boost::container::allocator_traits<Allocator>::size_type alloc_size_type; + typedef typename get_vector_opt<Options, alloc_size_type>::type options_type; + typedef typename options_type::growth_factor_type growth_factor_type; + typedef typename options_type::stored_size_type stored_size_type; + typedef value_less<T> value_less_t; - typedef typename container_detail::version<Allocator>::type alloc_version; - typedef boost::container::container_detail::vector_alloc_holder<Allocator> alloc_holder_t; + //If provided the stored_size option must specify a type that is equal or a type that is smaller. + BOOST_STATIC_ASSERT( (sizeof(stored_size_type) < sizeof(alloc_size_type) || + dtl::is_same<stored_size_type, alloc_size_type>::value) ); + + typedef typename dtl::version<Allocator>::type alloc_version; + typedef boost::container::vector_alloc_holder<Allocator, stored_size_type> alloc_holder_t; alloc_holder_t m_holder; typedef allocator_traits<Allocator> allocator_traits_type; - template <class U, class UAllocator> + template <class U, class UAllocator, class UOptions> friend class vector; typedef typename allocator_traits_type::pointer pointer_impl; - typedef container_detail::vec_iterator<pointer_impl, false> iterator_impl; - typedef container_detail::vec_iterator<pointer_impl, true > const_iterator_impl; + typedef vec_iterator<pointer_impl, false> iterator_impl; + typedef vec_iterator<pointer_impl, true > const_iterator_impl; protected: static bool is_propagable_from(const Allocator &from_alloc, pointer_impl p, const Allocator &to_alloc, bool const propagate_allocator) { return alloc_holder_t::is_propagable_from(from_alloc, p, to_alloc, propagate_allocator); } @@ -745,39 +765,33 @@ typedef typename ::boost::container::allocator_traits<Allocator>::const_reference const_reference; typedef typename ::boost::container::allocator_traits<Allocator>::size_type size_type; typedef typename ::boost::container::allocator_traits<Allocator>::difference_type difference_type; typedef Allocator allocator_type; typedef Allocator stored_allocator_type; - #if defined BOOST_CONTAINER_VECTOR_ITERATOR_IS_POINTER - typedef BOOST_CONTAINER_IMPDEF(pointer) iterator; - typedef BOOST_CONTAINER_IMPDEF(const_pointer) const_iterator; - #else typedef BOOST_CONTAINER_IMPDEF(iterator_impl) iterator; typedef BOOST_CONTAINER_IMPDEF(const_iterator_impl) const_iterator; - #endif typedef BOOST_CONTAINER_IMPDEF(boost::container::reverse_iterator<iterator>) reverse_iterator; typedef BOOST_CONTAINER_IMPDEF(boost::container::reverse_iterator<const_iterator>) const_reverse_iterator; #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED private: BOOST_COPYABLE_AND_MOVABLE(vector) - typedef container_detail::vector_value_traits<Allocator> value_traits; + typedef vector_value_traits<Allocator> value_traits; typedef constant_iterator<T, difference_type> cvalue_iterator; protected: BOOST_CONTAINER_FORCEINLINE void steal_resources(vector &x) { return this->m_holder.steal_resources(x.m_holder); } - struct initial_capacity_t{}; template<class AllocFwd> BOOST_CONTAINER_FORCEINLINE vector(initial_capacity_t, pointer initial_memory, size_type capacity, BOOST_FWD_REF(AllocFwd) a) - : m_holder(initial_memory, capacity, ::boost::forward<AllocFwd>(a)) + : m_holder(initial_capacity_t(), initial_memory, capacity, ::boost::forward<AllocFwd>(a)) {} BOOST_CONTAINER_FORCEINLINE vector(initial_capacity_t, pointer initial_memory, size_type capacity) - : m_holder(initial_memory, capacity) + : m_holder(initial_capacity_t(), initial_memory, capacity) {} #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED public: @@ -790,11 +804,11 @@ //! <b>Effects</b>: Constructs a vector taking the allocator as parameter. //! //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - vector() BOOST_NOEXCEPT_IF(container_detail::is_nothrow_default_constructible<Allocator>::value) + vector() BOOST_NOEXCEPT_IF(dtl::is_nothrow_default_constructible<Allocator>::value) : m_holder() {} //! <b>Effects</b>: Constructs a vector taking the allocator as parameter. //! @@ -810,11 +824,11 @@ //! <b>Throws</b>: If allocator_type's allocation //! throws or T's value initialization throws. //! //! <b>Complexity</b>: Linear to n. explicit vector(size_type n) - : m_holder(container_detail::uninitialized_size, n) + : m_holder(vector_uninitialized_size, n) { #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS this->num_alloc += n != 0; #endif boost::container::uninitialized_value_init_alloc_n @@ -827,11 +841,11 @@ //! <b>Throws</b>: If allocator_type's allocation //! throws or T's value initialization throws. //! //! <b>Complexity</b>: Linear to n. explicit vector(size_type n, const allocator_type &a) - : m_holder(container_detail::uninitialized_size, a, n) + : m_holder(vector_uninitialized_size, a, n) { #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS this->num_alloc += n != 0; #endif boost::container::uninitialized_value_init_alloc_n @@ -846,11 +860,11 @@ //! //! <b>Complexity</b>: Linear to n. //! //! <b>Note</b>: Non-standard extension vector(size_type n, default_init_t) - : m_holder(container_detail::uninitialized_size, n) + : m_holder(vector_uninitialized_size, n) { #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS this->num_alloc += n != 0; #endif boost::container::uninitialized_default_init_alloc_n @@ -865,11 +879,11 @@ //! //! <b>Complexity</b>: Linear to n. //! //! <b>Note</b>: Non-standard extension vector(size_type n, default_init_t, const allocator_type &a) - : m_holder(container_detail::uninitialized_size, a, n) + : m_holder(vector_uninitialized_size, a, n) { #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS this->num_alloc += n != 0; #endif boost::container::uninitialized_default_init_alloc_n @@ -882,11 +896,11 @@ //! <b>Throws</b>: If allocator_type's allocation //! throws or T's copy constructor throws. //! //! <b>Complexity</b>: Linear to n. vector(size_type n, const T& value) - : m_holder(container_detail::uninitialized_size, n) + : m_holder(vector_uninitialized_size, n) { #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS this->num_alloc += n != 0; #endif boost::container::uninitialized_fill_alloc_n @@ -899,11 +913,11 @@ //! <b>Throws</b>: If allocation //! throws or T's copy constructor throws. //! //! <b>Complexity</b>: Linear to n. vector(size_type n, const T& value, const allocator_type& a) - : m_holder(container_detail::uninitialized_size, a, n) + : m_holder(vector_uninitialized_size, a, n) { #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS this->num_alloc += n != 0; #endif boost::container::uninitialized_fill_alloc_n @@ -917,13 +931,13 @@ //! throws or T's constructor taking a dereferenced InIt throws. //! //! <b>Complexity</b>: Linear to the range [first, last). template <class InIt> vector(InIt first, InIt last - BOOST_CONTAINER_DOCIGN(BOOST_MOVE_I typename container_detail::disable_if_c - < container_detail::is_convertible<InIt BOOST_MOVE_I size_type>::value - BOOST_MOVE_I container_detail::nat >::type * = 0) + BOOST_CONTAINER_DOCIGN(BOOST_MOVE_I typename dtl::disable_if_c + < dtl::is_convertible<InIt BOOST_MOVE_I size_type>::value + BOOST_MOVE_I dtl::nat >::type * = 0) ) : m_holder() { this->assign(first, last); } //! <b>Effects</b>: Constructs a vector that will use a copy of allocator a @@ -933,13 +947,13 @@ //! throws or T's constructor taking a dereferenced InIt throws. //! //! <b>Complexity</b>: Linear to the range [first, last). template <class InIt> vector(InIt first, InIt last, const allocator_type& a - BOOST_CONTAINER_DOCIGN(BOOST_MOVE_I typename container_detail::disable_if_c - < container_detail::is_convertible<InIt BOOST_MOVE_I size_type>::value - BOOST_MOVE_I container_detail::nat >::type * = 0) + BOOST_CONTAINER_DOCIGN(BOOST_MOVE_I typename dtl::disable_if_c + < dtl::is_convertible<InIt BOOST_MOVE_I size_type>::value + BOOST_MOVE_I dtl::nat >::type * = 0) ) : m_holder(a) { this->assign(first, last); } //! <b>Effects</b>: Copy constructs a vector. @@ -949,11 +963,11 @@ //! <b>Throws</b>: If allocator_type's allocation //! throws or T's copy constructor throws. //! //! <b>Complexity</b>: Linear to the elements x contains. vector(const vector &x) - : m_holder( container_detail::uninitialized_size + : m_holder( vector_uninitialized_size , allocator_traits_type::select_on_container_copy_construction(x.m_holder.alloc()) , x.size()) { #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS this->num_alloc += x.size() != 0; @@ -995,12 +1009,12 @@ //! <b>Complexity</b>: Linear. //! //! <b>Note</b>: Non-standard extension to support static_vector template<class OtherAllocator> vector(BOOST_RV_REF_BEG vector<T, OtherAllocator> BOOST_RV_REF_END x - , typename container_detail::enable_if_c - < container_detail::is_version<OtherAllocator, 0>::value>::type * = 0 + , typename dtl::enable_if_c + < dtl::is_version<OtherAllocator, 0>::value>::type * = 0 ) : m_holder(boost::move(x.m_holder)) {} #endif //!defined(BOOST_CONTAINER_DOXYGEN_INVOKED) @@ -1012,11 +1026,11 @@ //! <b>Throws</b>: If allocation //! throws or T's copy constructor throws. //! //! <b>Complexity</b>: Linear to the elements x contains. vector(const vector &x, const allocator_type &a) - : m_holder(container_detail::uninitialized_size, a, x.size()) + : m_holder(vector_uninitialized_size, a, x.size()) { #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS this->num_alloc += x.size() != 0; #endif ::boost::container::uninitialized_copy_alloc_n_source @@ -1030,11 +1044,11 @@ //! //! <b>Throws</b>: If allocation or T's copy constructor throws. //! //! <b>Complexity</b>: Constant if a == x.get_allocator(), linear otherwise. vector(BOOST_RV_REF(vector) x, const allocator_type &a) - : m_holder( container_detail::uninitialized_size, a + : m_holder( vector_uninitialized_size, a , is_propagable_from(x.get_stored_allocator(), x.m_holder.start(), a, true) ? 0 : x.size() ) { if(is_propagable_from(x.get_stored_allocator(), x.m_holder.start(), a, true)){ this->m_holder.steal_resources(x.m_holder); @@ -1121,14 +1135,14 @@ //! //! <b>Complexity</b>: Linear. //! //! <b>Note</b>: Non-standard extension to support static_vector template<class OtherAllocator> - BOOST_CONTAINER_FORCEINLINE typename container_detail::enable_if_and + BOOST_CONTAINER_FORCEINLINE typename dtl::enable_if_and < vector& - , container_detail::is_version<OtherAllocator, 0> - , container_detail::is_different<OtherAllocator, allocator_type> + , dtl::is_version<OtherAllocator, 0> + , dtl::is_different<OtherAllocator, allocator_type> >::type operator=(BOOST_RV_REF_BEG vector<value_type, OtherAllocator> BOOST_RV_REF_END x) { this->priv_move_assign(boost::move(x)); return *this; @@ -1143,14 +1157,14 @@ //! //! <b>Complexity</b>: Linear. //! //! <b>Note</b>: Non-standard extension to support static_vector template<class OtherAllocator> - BOOST_CONTAINER_FORCEINLINE typename container_detail::enable_if_and + BOOST_CONTAINER_FORCEINLINE typename dtl::enable_if_and < vector& - , container_detail::is_version<OtherAllocator, 0> - , container_detail::is_different<OtherAllocator, allocator_type> + , dtl::is_version<OtherAllocator, 0> + , dtl::is_different<OtherAllocator, allocator_type> >::type operator=(const vector<value_type, OtherAllocator> &x) { this->priv_copy_assign(x); return *this; @@ -1164,16 +1178,16 @@ //! T's constructor/assignment from dereferencing InpIt throws. //! //! <b>Complexity</b>: Linear to n. template <class InIt> void assign(InIt first, InIt last - BOOST_CONTAINER_DOCIGN(BOOST_MOVE_I typename container_detail::disable_if_or + BOOST_CONTAINER_DOCIGN(BOOST_MOVE_I typename dtl::disable_if_or < void - BOOST_MOVE_I container_detail::is_convertible<InIt BOOST_MOVE_I size_type> - BOOST_MOVE_I container_detail::and_ - < container_detail::is_different<alloc_version BOOST_MOVE_I version_0> - BOOST_MOVE_I container_detail::is_not_input_iterator<InIt> + BOOST_MOVE_I dtl::is_convertible<InIt BOOST_MOVE_I size_type> + BOOST_MOVE_I dtl::and_ + < dtl::is_different<alloc_version BOOST_MOVE_I version_0> + BOOST_MOVE_I dtl::is_not_input_iterator<InIt> > >::type * = 0) ) { //Overwrite all elements we can from [first, last) @@ -1184,11 +1198,11 @@ } if (first == last){ //There are no more elements in the sequence, erase remaining 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 - boost::movelib::iterator_to_raw_pointer(cur)); this->priv_destroy_last_n(n); } else{ //There are more elements in the range, insert the remaining ones this->insert(this->cend(), first, last); @@ -1213,15 +1227,15 @@ //! T's constructor/assignment from dereferencing InpIt throws. //! //! <b>Complexity</b>: Linear to n. template <class FwdIt> void assign(FwdIt first, FwdIt last - BOOST_CONTAINER_DOCIGN(BOOST_MOVE_I typename container_detail::disable_if_or + BOOST_CONTAINER_DOCIGN(BOOST_MOVE_I typename dtl::disable_if_or < void - BOOST_MOVE_I container_detail::is_same<alloc_version BOOST_MOVE_I version_0> - BOOST_MOVE_I container_detail::is_convertible<FwdIt BOOST_MOVE_I size_type> - BOOST_MOVE_I container_detail::is_input_iterator<FwdIt> + BOOST_MOVE_I dtl::is_same<alloc_version BOOST_MOVE_I version_0> + BOOST_MOVE_I dtl::is_convertible<FwdIt BOOST_MOVE_I size_type> + BOOST_MOVE_I dtl::is_input_iterator<FwdIt> >::type * = 0) ) { //For Fwd iterators the standard only requires EmplaceConstructible and assignable from *first //so we can't do any backwards allocation @@ -1236,11 +1250,11 @@ ++this->num_alloc; #endif pointer const old_p = this->m_holder.start(); if(old_p){ this->priv_destroy_all(); - this->m_holder.alloc().deallocate(old_p, old_capacity); + this->m_holder.deallocate(old_p, old_capacity); } this->m_holder.start(ret); this->m_holder.capacity(real_cap); this->m_holder.m_size = 0; this->priv_uninitialized_construct_at_end(first, last); @@ -1739,11 +1753,11 @@ allocator_traits_type::construct(this->m_holder.alloc(), p, ::boost::forward<Args>(args)...); ++this->m_holder.m_size; return *p; } else{ - typedef container_detail::insert_emplace_proxy<Allocator, T*, Args...> type; + typedef dtl::insert_emplace_proxy<Allocator, T*, Args...> type; return *this->priv_forward_range_insert_no_capacity (this->back_ptr(), 1, type(::boost::forward<Args>(args)...), alloc_version()); } } @@ -1780,11 +1794,11 @@ template<class ...Args> iterator emplace(const_iterator position, BOOST_FWD_REF(Args) ...args) { BOOST_ASSERT(this->priv_in_range_or_end(position)); //Just call more general insert(pos, size, value) and return iterator - typedef container_detail::insert_emplace_proxy<Allocator, T*, Args...> type; + typedef dtl::insert_emplace_proxy<Allocator, T*, Args...> type; return this->priv_forward_range_insert( vector_iterator_get_ptr(position), 1 , type(::boost::forward<Args>(args)...)); } #else // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) @@ -1799,11 +1813,11 @@ , this->priv_raw_end() BOOST_MOVE_I##N BOOST_MOVE_FWD##N);\ ++this->m_holder.m_size;\ return *p;\ }\ else{\ - typedef container_detail::insert_emplace_proxy_arg##N<Allocator, T* BOOST_MOVE_I##N BOOST_MOVE_TARG##N> type;\ + typedef dtl::insert_emplace_proxy_arg##N<Allocator, T* BOOST_MOVE_I##N BOOST_MOVE_TARG##N> type;\ return *this->priv_forward_range_insert_no_capacity\ ( this->back_ptr(), 1, type(BOOST_MOVE_FWD##N), alloc_version());\ }\ }\ \ @@ -1821,11 +1835,11 @@ \ BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \ iterator emplace(const_iterator pos BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\ {\ BOOST_ASSERT(this->priv_in_range_or_end(pos));\ - typedef container_detail::insert_emplace_proxy_arg##N<Allocator, T* BOOST_MOVE_I##N BOOST_MOVE_TARG##N> type;\ + typedef dtl::insert_emplace_proxy_arg##N<Allocator, T* BOOST_MOVE_I##N BOOST_MOVE_TARG##N> type;\ return this->priv_forward_range_insert(vector_iterator_get_ptr(pos), 1, type(BOOST_MOVE_FWD##N));\ }\ // BOOST_MOVE_ITERATE_0TO9(BOOST_CONTAINER_VECTOR_EMPLACE_CODE) #undef BOOST_CONTAINER_VECTOR_EMPLACE_CODE @@ -1887,11 +1901,11 @@ //! //! <b>Complexity</b>: Linear to n. iterator insert(const_iterator p, size_type n, const T& x) { BOOST_ASSERT(this->priv_in_range_or_end(p)); - container_detail::insert_n_copies_proxy<Allocator, T*> proxy(x); + dtl::insert_n_copies_proxy<Allocator, T*> proxy(x); return this->priv_forward_range_insert(vector_iterator_get_ptr(p), n, proxy); } //! <b>Requires</b>: p must be a valid iterator of *this. //! @@ -1904,14 +1918,14 @@ //! //! <b>Complexity</b>: Linear to boost::container::iterator_distance [first, last). template <class InIt> iterator insert(const_iterator pos, InIt first, InIt last #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED) - , typename container_detail::disable_if_or + , typename dtl::disable_if_or < void - , container_detail::is_convertible<InIt, size_type> - , container_detail::is_not_input_iterator<InIt> + , dtl::is_convertible<InIt, size_type> + , dtl::is_not_input_iterator<InIt> >::type * = 0 #endif ) { BOOST_ASSERT(this->priv_in_range_or_end(pos)); @@ -1925,19 +1939,19 @@ } #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED) template <class FwdIt> iterator insert(const_iterator pos, FwdIt first, FwdIt last - , typename container_detail::disable_if_or + , typename dtl::disable_if_or < void - , container_detail::is_convertible<FwdIt, size_type> - , container_detail::is_input_iterator<FwdIt> + , dtl::is_convertible<FwdIt, size_type> + , dtl::is_input_iterator<FwdIt> >::type * = 0 ) { BOOST_ASSERT(this->priv_in_range_or_end(pos)); - container_detail::insert_range_proxy<Allocator, FwdIt, T*> proxy(first); + dtl::insert_range_proxy<Allocator, FwdIt, T*> proxy(first); return this->priv_forward_range_insert(vector_iterator_get_ptr(pos), boost::container::iterator_distance(first, last), proxy); } #endif //! <b>Requires</b>: p must be a valid iterator of *this. num, must @@ -1958,14 +1972,14 @@ #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED) template <class InIt> iterator insert(const_iterator pos, size_type num, InIt first, InIt last) { BOOST_ASSERT(this->priv_in_range_or_end(pos)); - BOOST_ASSERT(container_detail::is_input_iterator<InIt>::value || + BOOST_ASSERT(dtl::is_input_iterator<InIt>::value || num == static_cast<size_type>(boost::container::iterator_distance(first, last))); (void)last; - container_detail::insert_range_proxy<Allocator, InIt, T*> proxy(first); + dtl::insert_range_proxy<Allocator, InIt, T*> proxy(first); return this->priv_forward_range_insert(vector_iterator_get_ptr(pos), num, proxy); } #endif #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) @@ -2003,15 +2017,15 @@ //! last element. Constant if pos is the last element. iterator erase(const_iterator position) { BOOST_ASSERT(this->priv_in_range(position)); const pointer p = vector_iterator_get_ptr(position); - T *const pos_ptr = container_detail::to_raw_pointer(p); + 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); //Move elements forward and destroy last - this->priv_destroy_last(pos_ptr == new_end_ptr); + this->priv_destroy_last(pos_ptr != new_end_ptr); return iterator(p); } //! <b>Effects</b>: Erases the elements pointed by [first, last). //! @@ -2023,29 +2037,29 @@ { BOOST_ASSERT(first == last || (first < last && this->priv_in_range(first) && this->priv_in_range_or_end(last))); if (first != last){ 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 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 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); } return iterator(vector_iterator_get_ptr(first)); } //! <b>Effects</b>: Swaps the contents of *this and x. //! //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Constant. - void swap(vector& x) + BOOST_CONTAINER_FORCEINLINE void swap(vector& x) BOOST_NOEXCEPT_IF( ((allocator_traits_type::propagate_on_container_swap::value || allocator_traits_type::is_always_equal::value) && - !container_detail::is_version<Allocator, 0>::value)) + !dtl::is_version<Allocator, 0>::value)) { - this->priv_swap(x, container_detail::bool_<container_detail::is_version<Allocator, 0>::value>()); + this->priv_swap(x, dtl::bool_<dtl::is_version<Allocator, 0>::value>()); } #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED //! <b>Effects</b>: Swaps the contents of *this and x. @@ -2054,15 +2068,15 @@ //! //! <b>Complexity</b>: Linear //! //! <b>Note</b>: Non-standard extension to support static_vector template<class OtherAllocator> - void swap(vector<T, OtherAllocator> & x - , typename container_detail::enable_if_and + BOOST_CONTAINER_FORCEINLINE void swap(vector<T, OtherAllocator> & x + , typename dtl::enable_if_and < void - , container_detail::is_version<OtherAllocator, 0> - , container_detail::is_different<OtherAllocator, allocator_type> + , dtl::is_version<OtherAllocator, 0> + , dtl::is_different<OtherAllocator, allocator_type> >::type * = 0 ) { this->m_holder.deep_swap(x.m_holder); } #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED @@ -2070,23 +2084,23 @@ //! <b>Effects</b>: Erases all the elements of the vector. //! //! <b>Throws</b>: Nothing. //! //! <b>Complexity</b>: Linear to the number of elements in the container. - void clear() BOOST_NOEXCEPT_OR_NOTHROW + BOOST_CONTAINER_FORCEINLINE void clear() BOOST_NOEXCEPT_OR_NOTHROW { this->priv_destroy_all(); } //! <b>Effects</b>: Returns true if x and y are equal //! //! <b>Complexity</b>: Linear to the number of elements in the container. - friend bool operator==(const vector& x, const vector& y) + BOOST_CONTAINER_FORCEINLINE friend bool operator==(const vector& x, const vector& y) { return x.size() == y.size() && ::boost::container::algo_equal(x.begin(), x.end(), y.begin()); } //! <b>Effects</b>: Returns true if x and y are unequal //! //! <b>Complexity</b>: Linear to the number of elements in the container. - friend bool operator!=(const vector& x, const vector& y) + BOOST_CONTAINER_FORCEINLINE friend bool operator!=(const vector& x, const vector& y) { return !(x == y); } //! <b>Effects</b>: Returns true if x is less than y //! //! <b>Complexity</b>: Linear to the number of elements in the container. @@ -2102,29 +2116,29 @@ } //! <b>Effects</b>: Returns true if x is greater than y //! //! <b>Complexity</b>: Linear to the number of elements in the container. - friend bool operator>(const vector& x, const vector& y) + BOOST_CONTAINER_FORCEINLINE friend bool operator>(const vector& x, const vector& y) { return y < x; } //! <b>Effects</b>: Returns true if x is equal or less than y //! //! <b>Complexity</b>: Linear to the number of elements in the container. - friend bool operator<=(const vector& x, const vector& y) + BOOST_CONTAINER_FORCEINLINE friend bool operator<=(const vector& x, const vector& y) { return !(y < x); } //! <b>Effects</b>: Returns true if x is equal or greater than y //! //! <b>Complexity</b>: Linear to the number of elements in the container. - friend bool operator>=(const vector& x, const vector& y) + BOOST_CONTAINER_FORCEINLINE friend bool operator>=(const vector& x, const vector& y) { return !(x < y); } //! <b>Effects</b>: x.swap(y) //! //! <b>Complexity</b>: Constant. - friend void swap(vector& x, vector& y) + BOOST_CONTAINER_FORCEINLINE friend void swap(vector& x, vector& y) { x.swap(y); } #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED //! <b>Effects</b>: If n is less than or equal to capacity(), this call has no //! effect. Otherwise, it is a request for allocation of additional memory @@ -2141,31 +2155,55 @@ return cp >= new_cap || (alloc_version::value == 2 && this->m_holder.try_expand_fwd(new_cap - cp)); } //Absolutely experimental. This function might change, disappear or simply crash! template<class BiDirPosConstIt, class BiDirValueIt> - void insert_ordered_at(const size_type element_count, BiDirPosConstIt last_position_it, BiDirValueIt last_value_it) + BOOST_CONTAINER_FORCEINLINE void insert_ordered_at(const size_type element_count, BiDirPosConstIt last_position_it, BiDirValueIt last_value_it) { - typedef container_detail::vector_insert_ordered_cursor<BiDirPosConstIt, BiDirValueIt> inserter_t; + typedef vector_insert_ordered_cursor<BiDirPosConstIt, BiDirValueIt> inserter_t; return this->priv_insert_ordered_at(element_count, inserter_t(last_position_it, last_value_it)); } - template<class BidirIt> - void merge(BidirIt first, BidirIt last) - { this->merge(first, last, value_less()); } + template<class InputIt> + BOOST_CONTAINER_FORCEINLINE void merge(InputIt first, InputIt last) + { this->merge(first, last, value_less_t()); } - template<class BidirIt, class Compare> - void merge(BidirIt first, BidirIt last, Compare comp) - { this->priv_merge(container_detail::false_type(), first, last, comp); } + template<class InputIt, class Compare> + BOOST_CONTAINER_FORCEINLINE void merge(InputIt first, InputIt last, Compare comp) + { + size_type const s = this->size(); + size_type const c = this->capacity(); + size_type n = 0; + size_type const free_cap = c - s; + //If not input iterator and new elements don't fit in the remaining capacity, merge in new buffer + if(!dtl::is_input_iterator<InputIt>::value && + free_cap < (n = static_cast<size_type>(boost::container::iterator_distance(first, last)))){ + this->priv_merge_in_new_buffer(first, n, comp, alloc_version()); + } + else{ + iterator pos(this->insert(this->cend(), first, last)); + T *const raw_beg = this->priv_raw_begin(); + T *const raw_end = this->priv_raw_end(); + T *const raw_pos = raw_beg + s; + boost::movelib::adaptive_merge(raw_beg, raw_pos, raw_end, comp, raw_end, free_cap - n); + } + } - template<class BidirIt> - void merge_unique(BidirIt first, BidirIt last) - { this->priv_merge(container_detail::true_type(), first, last, value_less()); } + template<class InputIt> + BOOST_CONTAINER_FORCEINLINE void merge_unique(InputIt first, InputIt last) + { this->merge_unique(first, last, value_less_t()); } - template<class BidirIt, class Compare> - void merge_unique(BidirIt first, BidirIt last, Compare comp) - { this->priv_merge(container_detail::true_type(), first, last, comp); } + template<class InputIt, class Compare> + BOOST_CONTAINER_FORCEINLINE void merge_unique(InputIt first, InputIt last, Compare comp) + { + size_type const s = this->size(); + this->priv_set_difference_back(first, last, comp); + T *const raw_beg = this->priv_raw_begin(); + T *const raw_end = this->priv_raw_end(); + T *raw_pos = raw_beg + s; + boost::movelib::adaptive_merge(raw_beg, raw_pos, raw_end, comp, raw_end, this->capacity() - this->size()); + } private: template<class PositionValue> void priv_insert_ordered_at(const size_type element_count, PositionValue position_value) { @@ -2221,125 +2259,66 @@ old_hole_size = new_hole_size; prev_pos = pos; } } - template<class UniqueBool, class BidirIt, class Compare> - void priv_merge(UniqueBool, BidirIt first, BidirIt last, Compare comp) + template<class InputIt, class Compare> + void priv_set_difference_back(InputIt first1, InputIt last1, Compare comp) { - size_type const n = static_cast<size_type>(boost::container::iterator_distance(first, last)); - size_type const s = this->size(); - if(BOOST_LIKELY(s)){ - size_type const c = this->capacity(); - size_type const free_c = (c - s); - //Use a new buffer if current one is too small for new elements, - //or there is no room for position indexes - if(free_c < n){ - size_type const new_size = s + n; - 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); + T * old_first2 = this->priv_raw_begin(); + T * first2 = old_first2; + T * last2 = this->priv_raw_end(); + + while (first1 != last1) { + if (first2 == last2){ + this->insert(this->cend(), first1, last1); + return; } - else if(!UniqueBool::value && free_c >= n){ - typedef container_detail::vector_merge_cursor<T, size_type, BidirIt, Compare> inserter_t; - T* const pbeg = this->priv_raw_begin(); - return this->priv_insert_ordered_at(n, inserter_t(pbeg, pbeg + s, last, comp)); - } - else{ //UniqueBool::value == true and free_c >= n - std::size_t remaining = n; - static const std::size_t PosCount = 64u; - size_type positions[PosCount]; - size_type *indexes = 0; - while(remaining){ - //Query for room to store indexes in the remaining buffer - boost::uintptr_t const szt_align_mask = container_detail::alignment_of<size_type>::value - 1; - boost::uintptr_t const addr = boost::uintptr_t(this->priv_raw_begin() + s + n); - boost::uintptr_t const capaddr = boost::uintptr_t(this->priv_raw_begin() + c); - boost::uintptr_t const aligned_addr = (addr + szt_align_mask) & ~szt_align_mask; - indexes = reinterpret_cast<size_type *>(aligned_addr); - std::size_t index_capacity = (aligned_addr >= capaddr) ? 0u : (capaddr - aligned_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; + if (comp(*first1, *first2)) { + this->emplace_back(*first1); + //Reallocation happened, update range + T * const raw_begin = this->priv_raw_begin(); + if(old_first2 != raw_begin){ + first2 = raw_begin + (first2 - old_first2); + last2 = first2 + (last2 - old_first2); + old_first2 = raw_begin; } + + ++first1; } + else { + if (!comp(*first2, *first1)) { + ++first1; + } + ++first2; + } } - else{ - this->insert(this->cend(), n, first, last); - } } - template <class UniqueBool, class BidirIt, class Compare> - void priv_insert_ordered_range - (UniqueBool, size_type const n, BidirIt first, BidirIt const last, size_type positions[], Compare comp) + template<class FwdIt, class Compare> + BOOST_CONTAINER_FORCEINLINE void priv_merge_in_new_buffer(FwdIt, size_type, Compare, version_0) { - //Linear: at most N + M -1 comparisons - //Log: MlogN - //Average - //Linear: N + M - 2 - //Log: MlogN - //N+M - 2 - //N - //(N+M)/2 < MlogN - //(N/M+1)/2 <= logN - //bool const linear = !s || !n || (s <= n) || ((s+n)/n/2 < logN); - size_type const s = this->size(); - size_type remaining = n; - T* const pbeg = this->priv_raw_begin(); - T* const pend = pbeg + s; - T* pcur = pbeg; - size_type *position = positions; - size_type added_in_middle = 0; - if(first != last && pcur != pend){ - while(1){ - //maintain stability moving external values only if they are strictly less - if(comp(*first, *pcur)) { - *position = static_cast<size_type>(pcur - pbeg); - BOOST_ASSERT((position == positions) || (*(position-1) == size_type(-1)) || (*(position-1) <= *position)); - ++position; - ++added_in_middle; - --remaining; - if(++first == last) break; - } - else if(UniqueBool::value && !comp(*pcur, *first)){ - *position = size_type(-1); - ++position; - --remaining; - if(++first == last) break; - } - else{ - if(++pcur == pend) break; - } - } - } - this->insert_ordered_at(added_in_middle, position, first); - this->insert(this->cend(), remaining, first, last); + throw_bad_alloc(); } - template<class UniqueBool, class FwdIt, class Compare> - void priv_merge_in_new_buffer - (UniqueBool, FwdIt first, size_type n, Compare comp, pointer new_storage, size_type const new_cap) + template<class FwdIt, class Compare, class Version> + void priv_merge_in_new_buffer(FwdIt first, size_type n, Compare comp, Version) { + size_type const new_size = this->size() + n; + size_type new_cap = new_size; + pointer p = pointer(); + pointer const new_storage = this->m_holder.allocation_command(allocate_new, new_size, new_cap, p); + BOOST_ASSERT((new_cap >= this->size() ) && (new_cap - this->size()) >= n); allocator_type &a = this->m_holder.alloc(); typename value_traits::ArrayDeallocator new_buffer_deallocator(new_storage, a, new_cap); typename value_traits::ArrayDestructor new_values_destroyer(new_storage, a, 0u); T* pbeg = this->priv_raw_begin(); size_type const old_size = this->size(); T* const pend = pbeg + old_size; - T* d_first = container_detail::to_raw_pointer(new_storage); + T* d_first = boost::movelib::to_raw_pointer(new_storage); size_type added = n; //Merge in new buffer loop while(1){ if(!n) { ::boost::container::uninitialized_move_alloc(this->m_holder.alloc(), pbeg, pend, d_first); @@ -2349,45 +2328,40 @@ ::boost::container::uninitialized_move_alloc_n(this->m_holder.alloc(), first, n, d_first); break; } //maintain stability moving external values only if they are strictly less else if(comp(*first, *pbeg)) { - allocator_traits_type::construct( this->m_holder.alloc(), d_first, ::boost::move(*first) ); + allocator_traits_type::construct( this->m_holder.alloc(), d_first, *first ); new_values_destroyer.increment_size(1u); ++first; --n; ++d_first; } - else if(UniqueBool::value && !comp(*pbeg, *first)){ - ++first; - --n; - --added; - } else{ - allocator_traits_type::construct( this->m_holder.alloc(), d_first, ::boost::move(*pbeg) ); + allocator_traits_type::construct( this->m_holder.alloc(), d_first, boost::move(*pbeg) ); new_values_destroyer.increment_size(1u); ++pbeg; ++d_first; } } //Nothrow operations pointer const old_p = this->m_holder.start(); size_type const old_cap = this->m_holder.capacity(); - boost::container::destroy_alloc_n(a, container_detail::to_raw_pointer(old_p), old_size); - a.deallocate(old_p, old_cap); + boost::container::destroy_alloc_n(a, boost::movelib::to_raw_pointer(old_p), old_size); + this->m_holder.deallocate(old_p, old_cap); this->m_holder.m_size = old_size + added; this->m_holder.start(new_storage); this->m_holder.capacity(new_cap); new_buffer_deallocator.release(); new_values_destroyer.release(); } - bool room_enough() const + BOOST_CONTAINER_FORCEINLINE bool room_enough() const { return this->m_holder.m_size < this->m_holder.capacity(); } - pointer back_ptr() const + BOOST_CONTAINER_FORCEINLINE pointer back_ptr() const { return this->m_holder.start() + this->m_holder.m_size; } size_type priv_index_of(pointer p) const { BOOST_ASSERT(this->m_holder.start() <= p); @@ -2395,14 +2369,14 @@ return static_cast<size_type>(p - this->m_holder.start()); } template<class OtherAllocator> void priv_move_assign(BOOST_RV_REF_BEG vector<T, OtherAllocator> BOOST_RV_REF_END x - , typename container_detail::enable_if_c - < container_detail::is_version<OtherAllocator, 0>::value >::type * = 0) + , typename dtl::enable_if_c + < dtl::is_version<OtherAllocator, 0>::value >::type * = 0) { - if(!container_detail::is_same<OtherAllocator, allocator_type>::value && + if(!dtl::is_same<OtherAllocator, allocator_type>::value && this->capacity() < x.size()){ throw_bad_alloc(); } T* const this_start = this->priv_raw_begin(); T* const other_start = x.priv_raw_begin(); @@ -2412,14 +2386,14 @@ this->m_holder.m_size = other_sz; } template<class OtherAllocator> void priv_move_assign(BOOST_RV_REF_BEG vector<T, OtherAllocator> BOOST_RV_REF_END x - , typename container_detail::disable_if_or + , typename dtl::disable_if_or < void - , container_detail::is_version<OtherAllocator, 0> - , container_detail::is_different<OtherAllocator, allocator_type> + , dtl::is_version<OtherAllocator, 0> + , dtl::is_different<OtherAllocator, allocator_type> >::type * = 0) { //for move assignment, no aliasing (&x != this) is assummed. BOOST_ASSERT(this != &x); allocator_type &this_alloc = this->m_holder.alloc(); @@ -2437,29 +2411,29 @@ this->clear(); this->m_holder.swap_resources(x.m_holder); } else if(is_propagable_from_x){ this->clear(); - this->m_holder.alloc().deallocate(this->m_holder.m_start, this->m_holder.m_capacity); + this->m_holder.deallocate(this->m_holder.m_start, this->m_holder.m_capacity); this->m_holder.steal_resources(x.m_holder); } //Else do a one by one move else{ - this->assign( boost::make_move_iterator(container_detail::iterator_to_raw_pointer(x.begin())) - , boost::make_move_iterator(container_detail::iterator_to_raw_pointer(x.end() )) + this->assign( boost::make_move_iterator(boost::movelib::iterator_to_raw_pointer(x.begin())) + , boost::make_move_iterator(boost::movelib::iterator_to_raw_pointer(x.end() )) ); } //Move allocator if needed - container_detail::move_alloc(this_alloc, x_alloc, container_detail::bool_<propagate_alloc>()); + dtl::move_alloc(this_alloc, x_alloc, dtl::bool_<propagate_alloc>()); } template<class OtherAllocator> void priv_copy_assign(const vector<T, OtherAllocator> &x - , typename container_detail::enable_if_c - < container_detail::is_version<OtherAllocator, 0>::value >::type * = 0) + , typename dtl::enable_if_c + < dtl::is_version<OtherAllocator, 0>::value >::type * = 0) { - if(!container_detail::is_same<OtherAllocator, allocator_type>::value && + if(!dtl::is_same<OtherAllocator, allocator_type>::value && this->capacity() < x.size()){ throw_bad_alloc(); } T* const this_start = this->priv_raw_begin(); T* const other_start = x.priv_raw_begin(); @@ -2468,35 +2442,35 @@ boost::container::copy_assign_range_alloc_n(this->m_holder.alloc(), other_start, other_sz, this_start, this_sz); this->m_holder.m_size = other_sz; } template<class OtherAllocator> - typename container_detail::disable_if_or + typename dtl::disable_if_or < void - , container_detail::is_version<OtherAllocator, 0> - , container_detail::is_different<OtherAllocator, allocator_type> + , dtl::is_version<OtherAllocator, 0> + , dtl::is_different<OtherAllocator, allocator_type> >::type priv_copy_assign(const vector<T, OtherAllocator> &x) { allocator_type &this_alloc = this->m_holder.alloc(); const allocator_type &x_alloc = x.m_holder.alloc(); - container_detail::bool_<allocator_traits_type:: + dtl::bool_<allocator_traits_type:: propagate_on_container_copy_assignment::value> flag; if(flag && this_alloc != x_alloc){ this->clear(); this->shrink_to_fit(); } - container_detail::assign_alloc(this_alloc, x_alloc, flag); + dtl::assign_alloc(this_alloc, x_alloc, flag); this->assign( x.priv_raw_begin(), x.priv_raw_end() ); } template<class Vector> //Template it to avoid it in explicit instantiations - void priv_swap(Vector &x, container_detail::true_type) //version_0 + void priv_swap(Vector &x, dtl::true_type) //version_0 { this->m_holder.deep_swap(x.m_holder); } template<class Vector> //Template it to avoid it in explicit instantiations - void priv_swap(Vector &x, container_detail::false_type) //version_N + void priv_swap(Vector &x, dtl::false_type) //version_N { const bool propagate_alloc = allocator_traits_type::propagate_on_container_swap::value; if(are_swap_propagable( this->get_stored_allocator(), this->m_holder.start() , x.get_stored_allocator(), x.m_holder.start(), propagate_alloc)){ //Just swap internals @@ -2512,37 +2486,37 @@ for(size_type i = 0; i != common_elements; ++i){ boost::adl_move_swap(sml[i], big[i]); } //... and move-insert the remaining range sml.insert( sml.cend() - , boost::make_move_iterator(container_detail::iterator_to_raw_pointer(big.nth(common_elements))) - , boost::make_move_iterator(container_detail::iterator_to_raw_pointer(big.end())) + , boost::make_move_iterator(boost::movelib::iterator_to_raw_pointer(big.nth(common_elements))) + , boost::make_move_iterator(boost::movelib::iterator_to_raw_pointer(big.end())) ); //Destroy remaining elements big.erase(big.nth(common_elements), big.cend()); } //And now swap the allocator - container_detail::swap_alloc(this->m_holder.alloc(), x.m_holder.alloc(), container_detail::bool_<propagate_alloc>()); + dtl::swap_alloc(this->m_holder.alloc(), x.m_holder.alloc(), dtl::bool_<propagate_alloc>()); } void priv_reserve_no_capacity(size_type, version_0) { throw_bad_alloc(); } - container_detail::insert_range_proxy<Allocator, boost::move_iterator<T*>, T*> priv_dummy_empty_proxy() + dtl::insert_range_proxy<Allocator, boost::move_iterator<T*>, T*> priv_dummy_empty_proxy() { - return container_detail::insert_range_proxy<Allocator, boost::move_iterator<T*>, T*> + return dtl::insert_range_proxy<Allocator, boost::move_iterator<T*>, T*> (::boost::make_move_iterator((T *)0)); } void priv_reserve_no_capacity(size_type new_cap, version_1) { //There is not enough memory, allocate a new buffer //Pass the hint so that allocators can take advantage of this. - pointer const p = allocator_traits_type::allocate(this->m_holder.alloc(), new_cap, this->m_holder.m_start); + pointer const p = this->m_holder.allocate(new_cap); //We will reuse insert code, so create a dummy input iterator this->priv_forward_range_insert_new_allocation - ( container_detail::to_raw_pointer(p), new_cap, this->priv_raw_end(), 0, this->priv_dummy_empty_proxy()); + ( boost::movelib::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) { //There is not enough memory, allocate a new @@ -2559,11 +2533,11 @@ ++this->num_expand_fwd; #endif this->m_holder.capacity(real_cap); } 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 = boost::movelib::to_raw_pointer(ret); T * const ins_pos = this->priv_raw_end(); if(reuse){ //Backwards (and possibly forward) expansion #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS ++this->num_expand_bwd; #endif @@ -2581,11 +2555,12 @@ } void priv_destroy_last(const bool moved = false) BOOST_NOEXCEPT_OR_NOTHROW { (void)moved; - if(!(value_traits::trivial_dctr || (value_traits::trivial_dctr_after_move && 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; } @@ -2618,18 +2593,18 @@ template<class U> iterator priv_insert(const const_iterator &p, BOOST_FWD_REF(U) x) { BOOST_ASSERT(this->priv_in_range_or_end(p)); return this->priv_forward_range_insert - ( vector_iterator_get_ptr(p), 1, container_detail::get_insert_value_proxy<T*, Allocator>(::boost::forward<U>(x))); + ( vector_iterator_get_ptr(p), 1, dtl::get_insert_value_proxy<T*, Allocator>(::boost::forward<U>(x))); } - container_detail::insert_copy_proxy<Allocator, T*> priv_single_insert_proxy(const T &x) - { return container_detail::insert_copy_proxy<Allocator, T*> (x); } + dtl::insert_copy_proxy<Allocator, T*> priv_single_insert_proxy(const T &x) + { return dtl::insert_copy_proxy<Allocator, T*> (x); } - container_detail::insert_move_proxy<Allocator, T*> priv_single_insert_proxy(BOOST_RV_REF(T) x) - { return container_detail::insert_move_proxy<Allocator, T*> (x); } + dtl::insert_move_proxy<Allocator, T*> priv_single_insert_proxy(BOOST_RV_REF(T) x) + { return dtl::insert_move_proxy<Allocator, T*> (x); } template <class U> void priv_push_back(BOOST_FWD_REF(U) u) { if (BOOST_LIKELY(this->room_enough())){ @@ -2643,18 +2618,18 @@ ( this->back_ptr(), 1 , this->priv_single_insert_proxy(::boost::forward<U>(u)), alloc_version()); } } - container_detail::insert_n_copies_proxy<Allocator, T*> priv_resize_proxy(const T &x) - { return container_detail::insert_n_copies_proxy<Allocator, T*>(x); } + BOOST_CONTAINER_FORCEINLINE dtl::insert_n_copies_proxy<Allocator, T*> priv_resize_proxy(const T &x) + { return dtl::insert_n_copies_proxy<Allocator, T*>(x); } - container_detail::insert_default_initialized_n_proxy<Allocator, T*> priv_resize_proxy(default_init_t) - { return container_detail::insert_default_initialized_n_proxy<Allocator, T*>(); } + BOOST_CONTAINER_FORCEINLINE dtl::insert_default_initialized_n_proxy<Allocator, T*> priv_resize_proxy(default_init_t) + { return dtl::insert_default_initialized_n_proxy<Allocator, T*>(); } - container_detail::insert_value_initialized_n_proxy<Allocator, T*> priv_resize_proxy(value_init_t) - { return container_detail::insert_value_initialized_n_proxy<Allocator, T*>(); } + BOOST_CONTAINER_FORCEINLINE dtl::insert_value_initialized_n_proxy<Allocator, T*> priv_resize_proxy(value_init_t) + { return dtl::insert_value_initialized_n_proxy<Allocator, T*>(); } template <class U> void priv_resize(size_type new_size, const U& u) { const size_type sz = this->size(); @@ -2666,34 +2641,34 @@ const size_type n = new_size - this->size(); this->priv_forward_range_insert_at_end(n, this->priv_resize_proxy(u), alloc_version()); } } - void priv_shrink_to_fit(version_0) BOOST_NOEXCEPT_OR_NOTHROW + BOOST_CONTAINER_FORCEINLINE void priv_shrink_to_fit(version_0) BOOST_NOEXCEPT_OR_NOTHROW {} void priv_shrink_to_fit(version_1) { const size_type cp = this->m_holder.capacity(); if(cp){ const size_type sz = this->size(); if(!sz){ - this->m_holder.alloc().deallocate(this->m_holder.m_start, cp); + this->m_holder.deallocate(this->m_holder.m_start, cp); this->m_holder.m_start = pointer(); this->m_holder.m_capacity = 0; } else if(sz < cp){ //Allocate a new buffer. //Pass the hint so that allocators can take advantage of this. - pointer const p = allocator_traits_type::allocate(this->m_holder.alloc(), sz, this->m_holder.m_start); + pointer const p = this->m_holder.allocate(sz); //We will reuse insert code, so create a dummy input iterator #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS ++this->num_alloc; #endif this->priv_forward_range_insert_new_allocation - ( container_detail::to_raw_pointer(p), sz + ( boost::movelib::to_raw_pointer(p), sz , this->priv_raw_begin(), 0, this->priv_dummy_empty_proxy()); } } } @@ -2701,11 +2676,11 @@ { const size_type cp = this->m_holder.capacity(); if(cp){ const size_type sz = this->size(); if(!sz){ - this->m_holder.alloc().deallocate(this->m_holder.m_start, cp); + this->m_holder.deallocate(this->m_holder.m_start, cp); this->m_holder.m_start = pointer(); this->m_holder.m_capacity = 0; } else{ size_type received_size = sz; @@ -2733,16 +2708,15 @@ iterator priv_forward_range_insert_no_capacity (const pointer &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 = pos - this->m_holder.start(); - T *const raw_pos = container_detail::to_raw_pointer(pos); + T *const raw_pos = boost::movelib::to_raw_pointer(pos); - const size_type new_cap = this->m_holder.next_capacity(n); + 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. - 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 = boost::movelib::to_raw_pointer(this->m_holder.allocate(new_cap)); #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS ++this->num_alloc; #endif this->priv_forward_range_insert_new_allocation ( new_buf, new_cap, raw_pos, n, insert_range_proxy); @@ -2752,16 +2726,16 @@ template <class InsertionProxy> iterator priv_forward_range_insert_no_capacity (const pointer &pos, const size_type n, const InsertionProxy insert_range_proxy, version_2) { //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 = boost::movelib::to_raw_pointer(pos); const size_type n_pos = raw_pos - this->priv_raw_begin(); //There is not enough memory, allocate a new //buffer or expand the old one. - size_type real_cap = this->m_holder.next_capacity(n); + size_type real_cap = this->m_holder.template next_capacity<growth_factor_type>(n); pointer reuse(this->m_holder.start()); pointer const ret (this->m_holder.allocation_command (allocate_new | expand_fwd | expand_bwd, this->m_holder.m_size + n, real_cap, reuse)); //Buffer reallocated @@ -2779,20 +2753,20 @@ else{ #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS ++this->num_expand_bwd; #endif this->priv_forward_range_insert_expand_backwards - (container_detail::to_raw_pointer(ret), real_cap, raw_pos, n, insert_range_proxy); + (boost::movelib::to_raw_pointer(ret), real_cap, raw_pos, n, insert_range_proxy); } } //New buffer else{ #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS ++this->num_alloc; #endif this->priv_forward_range_insert_new_allocation - ( container_detail::to_raw_pointer(ret), real_cap, raw_pos, n, insert_range_proxy); + ( boost::movelib::to_raw_pointer(ret), real_cap, raw_pos, n, insert_range_proxy); } return iterator(this->m_holder.start() + n_pos); } @@ -2808,11 +2782,11 @@ if (!same_buffer_start){ return priv_forward_range_insert_no_capacity(pos, n, insert_range_proxy, alloc_version()); } else{ //Expand forward - T *const raw_pos = container_detail::to_raw_pointer(pos); + T *const raw_pos = boost::movelib::to_raw_pointer(pos); const size_type n_pos = raw_pos - this->priv_raw_begin(); this->priv_forward_range_insert_expand_forward(raw_pos, n, insert_range_proxy); return iterator(this->m_holder.start() + n_pos); } } @@ -2831,11 +2805,11 @@ this->priv_forward_range_insert_at_end_expand_forward(n, insert_range_proxy); return this->end(); } template <class InsertionProxy, class AllocVersion> - iterator priv_forward_range_insert_at_end + BOOST_CONTAINER_FORCEINLINE iterator priv_forward_range_insert_at_end (const size_type n, const InsertionProxy insert_range_proxy, AllocVersion) { return this->priv_forward_range_insert(this->back_ptr(), n, insert_range_proxy); } @@ -2924,14 +2898,14 @@ } return hole_size; } private: - T *priv_raw_begin() const - { return container_detail::to_raw_pointer(m_holder.start()); } + BOOST_CONTAINER_FORCEINLINE T *priv_raw_begin() const + { return boost::movelib::to_raw_pointer(m_holder.start()); } - T* priv_raw_end() const + BOOST_CONTAINER_FORCEINLINE T* priv_raw_end() const { return this->priv_raw_begin() + this->m_holder.m_size; } template <class InsertionProxy> void priv_forward_range_insert_at_end_expand_forward(const size_type n, InsertionProxy insert_range_proxy) { @@ -3015,14 +2989,14 @@ (this->m_holder.alloc(), 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); - this->m_holder.alloc().deallocate(this->m_holder.start(), this->m_holder.capacity()); + this->m_holder.deallocate(this->m_holder.start(), this->m_holder.capacity()); } this->m_holder.start(new_start); - this->m_holder.m_size = new_finish - new_start; + this->m_holder.m_size = size_type(new_finish - new_start); this->m_holder.capacity(new_cap); //All construction successful, disable rollbacks new_values_destroyer.release(); new_buffer_deallocator.release(); } @@ -3354,15 +3328,15 @@ if (n >= this->size()){ throw_out_of_range("vector::at out of range"); } } - bool priv_in_range(const_iterator pos) const + BOOST_CONTAINER_FORCEINLINE bool priv_in_range(const_iterator pos) const { return (this->begin() <= pos) && (pos < this->end()); } - bool priv_in_range_or_end(const_iterator pos) const + BOOST_CONTAINER_FORCEINLINE bool priv_in_range_or_end(const_iterator pos) const { return (this->begin() <= pos) && (pos <= this->end()); } #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS