Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-07-05 08:28:51

0001 //////////////////////////////////////////////////////////////////////////////
0002 //
0003 // (C) Copyright Ion Gaztanaga 2005-2015. Distributed under the Boost
0004 // Software License, Version 1.0. (See accompanying file
0005 // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
0006 //
0007 // See http://www.boost.org/libs/container for documentation.
0008 //
0009 //////////////////////////////////////////////////////////////////////////////
0010 
0011 #ifndef BOOST_CONTAINER_CONTAINER_VECTOR_HPP
0012 #define BOOST_CONTAINER_CONTAINER_VECTOR_HPP
0013 
0014 #ifndef BOOST_CONFIG_HPP
0015 #  include <boost/config.hpp>
0016 #endif
0017 
0018 #if defined(BOOST_HAS_PRAGMA_ONCE)
0019 #  pragma once
0020 #endif
0021 
0022 #include <boost/container/detail/config_begin.hpp>
0023 #include <boost/container/detail/workaround.hpp>
0024 
0025 // container
0026 #include <boost/container/container_fwd.hpp>
0027 #include <boost/container/allocator_traits.hpp>
0028 #include <boost/container/new_allocator.hpp> //new_allocator
0029 #include <boost/container/throw_exception.hpp>
0030 #include <boost/container/options.hpp>
0031 // container detail
0032 #include <boost/container/detail/advanced_insert_int.hpp>
0033 #include <boost/container/detail/algorithm.hpp> //equal()
0034 #include <boost/container/detail/alloc_helpers.hpp>
0035 #include <boost/container/detail/allocation_type.hpp>
0036 #include <boost/container/detail/copy_move_algo.hpp>
0037 #include <boost/container/detail/destroyers.hpp>
0038 #include <boost/container/detail/iterator.hpp>
0039 #include <boost/container/detail/iterators.hpp>
0040 #include <boost/move/detail/iterator_to_raw_pointer.hpp>
0041 #include <boost/container/detail/mpl.hpp>
0042 #include <boost/container/detail/next_capacity.hpp>
0043 #include <boost/container/detail/value_functors.hpp>
0044 #include <boost/move/detail/to_raw_pointer.hpp>
0045 #include <boost/container/detail/type_traits.hpp>
0046 #include <boost/container/detail/version_type.hpp>
0047 // intrusive
0048 #include <boost/intrusive/pointer_traits.hpp>
0049 // move
0050 #include <boost/move/adl_move_swap.hpp>
0051 #include <boost/move/iterator.hpp>
0052 #include <boost/move/traits.hpp>
0053 #include <boost/move/utility_core.hpp>
0054 #include <boost/move/detail/launder.hpp>
0055 // move/detail
0056 #if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
0057 #include <boost/move/detail/fwd_macros.hpp>
0058 #endif
0059 #include <boost/move/detail/move_helpers.hpp>
0060 // move/algo
0061 #include <boost/move/algo/adaptive_merge.hpp>
0062 #include <boost/move/algo/unique.hpp>
0063 #include <boost/move/algo/predicate.hpp>
0064 #include <boost/move/algo/detail/set_difference.hpp>
0065 // other
0066 #include <boost/assert.hpp>
0067 #include <boost/cstdint.hpp>
0068 
0069 //std
0070 #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
0071 #include <initializer_list>   //for std::initializer_list
0072 #endif
0073 
0074 namespace boost {
0075 namespace container {
0076 
0077 #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
0078 
0079 
0080 template <class Pointer, bool IsConst>
0081 class vec_iterator
0082 {
0083    public:
0084    typedef std::random_access_iterator_tag                                          iterator_category;
0085    #ifdef BOOST_MOVE_CONTIGUOUS_ITERATOR_TAG
0086    typedef std::contiguous_iterator_tag                                             iterator_concept;
0087    #endif
0088    typedef typename boost::intrusive::pointer_traits<Pointer>::element_type         value_type;
0089 
0090    //Defining element_type to make libstdc++'s std::pointer_traits well-formed leads to ambiguity
0091    //due to LWG3446. So we need to specialize std::pointer_traits. See 
0092    //https://gcc.gnu.org/bugzilla/show_bug.cgi?id=96416 for details. Many thanks to Jonathan Wakely
0093    //for explaining the issue.
0094    #ifndef BOOST_GNU_STDLIB
0095    //Define element_
0096    typedef typename boost::intrusive::pointer_traits<Pointer>::element_type         element_type;
0097    #endif
0098    typedef typename boost::intrusive::pointer_traits<Pointer>::difference_type      difference_type;
0099    typedef typename boost::intrusive::pointer_traits<Pointer>::size_type            size_type;
0100    typedef typename dtl::if_c
0101       < IsConst
0102       , typename boost::intrusive::pointer_traits<Pointer>::template
0103                                  rebind_pointer<const value_type>::type
0104       , Pointer
0105       >::type                                                                       pointer;
0106    typedef typename boost::intrusive::pointer_traits<pointer>                       ptr_traits;
0107    typedef typename ptr_traits::reference                                           reference;
0108 
0109    #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
0110    private:
0111    Pointer m_ptr;
0112 
0113    class nat
0114    {
0115       public:
0116       Pointer get_ptr() const
0117       { return Pointer();  }
0118    };
0119    typedef typename dtl::if_c< IsConst
0120                              , vec_iterator<Pointer, false>
0121                              , nat>::type                                           nonconst_iterator;
0122 
0123    public:
0124    inline
0125       const Pointer &get_ptr() const BOOST_NOEXCEPT_OR_NOTHROW
0126    {  return   m_ptr;  }
0127 
0128    inline
0129       Pointer &get_ptr() BOOST_NOEXCEPT_OR_NOTHROW
0130    {  return   m_ptr;  }
0131 
0132    inline explicit vec_iterator(Pointer ptr) BOOST_NOEXCEPT_OR_NOTHROW
0133       : m_ptr(ptr)
0134    {}
0135    #endif   //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
0136 
0137    public:
0138 
0139    //Constructors
0140    inline vec_iterator() BOOST_NOEXCEPT_OR_NOTHROW
0141       : m_ptr()   //Value initialization to achieve "null iterators" (N3644)
0142    {}
0143 
0144    inline vec_iterator(const vec_iterator& other) BOOST_NOEXCEPT_OR_NOTHROW
0145       :  m_ptr(other.get_ptr())
0146    {}
0147 
0148    inline vec_iterator(const nonconst_iterator &other) BOOST_NOEXCEPT_OR_NOTHROW
0149       :  m_ptr(other.get_ptr())
0150    {}
0151 
0152    inline vec_iterator & operator=(const vec_iterator& other) BOOST_NOEXCEPT_OR_NOTHROW
0153    {  m_ptr = other.get_ptr();   return *this;  }
0154 
0155    //Pointer like operators
0156    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
0157       reference operator*()   const BOOST_NOEXCEPT_OR_NOTHROW
0158    {  BOOST_ASSERT(!!m_ptr);  return *m_ptr;  }
0159 
0160    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
0161       pointer operator->()  const BOOST_NOEXCEPT_OR_NOTHROW
0162    {  return m_ptr;  }
0163 
0164    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
0165       reference operator[](difference_type off) const BOOST_NOEXCEPT_OR_NOTHROW
0166    {  BOOST_ASSERT(!!m_ptr);  return m_ptr[off];  }
0167 
0168    //Increment / Decrement
0169    inline vec_iterator& operator++() BOOST_NOEXCEPT_OR_NOTHROW
0170    {  BOOST_ASSERT(!!m_ptr); ++m_ptr;  return *this; }
0171 
0172    inline vec_iterator operator++(int) BOOST_NOEXCEPT_OR_NOTHROW
0173    {  BOOST_ASSERT(!!m_ptr); return vec_iterator(m_ptr++); }
0174 
0175    inline vec_iterator& operator--() BOOST_NOEXCEPT_OR_NOTHROW
0176    {  BOOST_ASSERT(!!m_ptr); --m_ptr; return *this;  }
0177 
0178    inline vec_iterator operator--(int) BOOST_NOEXCEPT_OR_NOTHROW
0179    {  BOOST_ASSERT(!!m_ptr); return vec_iterator(m_ptr--); }
0180 
0181    //Arithmetic
0182    inline vec_iterator& operator+=(difference_type off) BOOST_NOEXCEPT_OR_NOTHROW
0183    {  BOOST_ASSERT(m_ptr || !off); m_ptr += off; return *this;   }
0184 
0185    inline vec_iterator& operator-=(difference_type off) BOOST_NOEXCEPT_OR_NOTHROW
0186    {  BOOST_ASSERT(m_ptr || !off); m_ptr -= off; return *this;   }
0187 
0188    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
0189       friend vec_iterator operator+(const vec_iterator &x, difference_type off) BOOST_NOEXCEPT_OR_NOTHROW
0190    {  BOOST_ASSERT(x.m_ptr || !off); return vec_iterator(x.m_ptr+off);  }
0191 
0192    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
0193       friend vec_iterator operator+(difference_type off, vec_iterator right) BOOST_NOEXCEPT_OR_NOTHROW
0194    {  BOOST_ASSERT(right.m_ptr || !off); right.m_ptr += off;  return right; }
0195 
0196    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
0197       friend vec_iterator operator-(vec_iterator left, difference_type off) BOOST_NOEXCEPT_OR_NOTHROW
0198    {  BOOST_ASSERT(left.m_ptr || !off); left.m_ptr -= off;  return left; }
0199 
0200    //Difference
0201    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
0202       friend difference_type operator-(const vec_iterator &left, const vec_iterator& right) BOOST_NOEXCEPT_OR_NOTHROW
0203    {  return left.m_ptr - right.m_ptr;   }
0204 
0205    //Comparison operators
0206    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
0207       friend bool operator==   (const vec_iterator& l, const vec_iterator& r) BOOST_NOEXCEPT_OR_NOTHROW
0208    {  return l.m_ptr == r.m_ptr;  }
0209 
0210    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
0211       friend bool operator!=   (const vec_iterator& l, const vec_iterator& r) BOOST_NOEXCEPT_OR_NOTHROW
0212    {  return l.m_ptr != r.m_ptr;  }
0213 
0214    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
0215       friend bool operator<    (const vec_iterator& l, const vec_iterator& r) BOOST_NOEXCEPT_OR_NOTHROW
0216    {  return l.m_ptr < r.m_ptr;  }
0217 
0218    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
0219       friend bool operator<=   (const vec_iterator& l, const vec_iterator& r) BOOST_NOEXCEPT_OR_NOTHROW
0220    {  return l.m_ptr <= r.m_ptr;  }
0221 
0222    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
0223       friend bool operator>    (const vec_iterator& l, const vec_iterator& r) BOOST_NOEXCEPT_OR_NOTHROW
0224    {  return l.m_ptr > r.m_ptr;  }
0225 
0226    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
0227       friend bool operator>=   (const vec_iterator& l, const vec_iterator& r) BOOST_NOEXCEPT_OR_NOTHROW
0228    {  return l.m_ptr >= r.m_ptr;  }
0229 };
0230 
0231 template<class BiDirPosConstIt, class BiDirValueIt>
0232 struct vector_insert_ordered_cursor
0233 {
0234    typedef typename iterator_traits<BiDirPosConstIt>::value_type  size_type;
0235    typedef typename iterator_traits<BiDirValueIt>::reference      reference;
0236 
0237    inline vector_insert_ordered_cursor(BiDirPosConstIt posit, BiDirValueIt valueit)
0238       : last_position_it(posit), last_value_it(valueit)
0239    {}
0240 
0241    void operator --()
0242    {
0243       --last_value_it;
0244       --last_position_it;
0245       while(this->get_pos() == size_type(-1)){
0246          --last_value_it;
0247          --last_position_it;
0248       }
0249    }
0250 
0251    inline size_type get_pos() const
0252    {  return *last_position_it;  }
0253 
0254    inline reference get_val()
0255    {  return *last_value_it;  }
0256 
0257    BiDirPosConstIt last_position_it;
0258    BiDirValueIt last_value_it;
0259 };
0260 
0261 template<class Pointer, bool IsConst>
0262 inline const Pointer &vector_iterator_get_ptr(const vec_iterator<Pointer, IsConst> &it) BOOST_NOEXCEPT_OR_NOTHROW
0263 {  return   it.get_ptr();  }
0264 
0265 template<class Pointer, bool IsConst>
0266 inline Pointer &get_ptr(vec_iterator<Pointer, IsConst> &it) BOOST_NOEXCEPT_OR_NOTHROW
0267 {  return  it.get_ptr();  }
0268 
0269 struct initial_capacity_t {};
0270 
0271 struct vector_uninitialized_size_t {};
0272 BOOST_CONTAINER_CONSTANT_VAR vector_uninitialized_size_t vector_uninitialized_size = vector_uninitialized_size_t();
0273 
0274 struct maybe_initial_capacity_t {};
0275 
0276 template <class T>
0277 struct vector_value_traits_base
0278 {
0279    BOOST_STATIC_CONSTEXPR bool trivial_dctr = dtl::is_trivially_destructible<T>::value;
0280    BOOST_STATIC_CONSTEXPR bool trivial_dctr_after_move = has_trivial_destructor_after_move<T>::value;
0281 };
0282 
0283 template <class Allocator>
0284 struct vector_value_traits
0285    : public vector_value_traits_base<typename Allocator::value_type>
0286 {
0287    typedef vector_value_traits_base<typename Allocator::value_type> base_t;
0288    //This is the anti-exception array destructor
0289    //to deallocate values already constructed
0290    typedef typename dtl::if_c
0291       <base_t::trivial_dctr
0292       ,dtl::null_scoped_destructor_n<Allocator>
0293       ,dtl::scoped_destructor_n<Allocator>
0294       >::type   ArrayDestructor;
0295    //This is the anti-exception array deallocator
0296    typedef dtl::scoped_array_deallocator<Allocator> ArrayDeallocator;
0297 };
0298 
0299 //!This struct deallocates and allocated memory
0300 template < class Allocator
0301          , class StoredSizeType
0302          , class AllocatorVersion = typename dtl::version<Allocator>::type
0303          >
0304 struct vector_alloc_holder
0305    : public Allocator
0306 {
0307    private:
0308    BOOST_MOVABLE_BUT_NOT_COPYABLE(vector_alloc_holder)
0309 
0310    public:
0311    typedef Allocator                                           allocator_type;
0312    typedef StoredSizeType                                      stored_size_type;
0313    typedef boost::container::allocator_traits<allocator_type>  allocator_traits_type;
0314    typedef typename allocator_traits_type::pointer             pointer;
0315    typedef typename allocator_traits_type::size_type           size_type;
0316    typedef typename allocator_traits_type::value_type          value_type;
0317 
0318 
0319    private:
0320 
0321    template<class SizeType>
0322    void do_initial_capacity(SizeType initial_capacity)
0323    {
0324       if (BOOST_UNLIKELY(initial_capacity > size_type(-1))) {
0325          boost::container::throw_length_error("get_next_capacity, allocator's max size reached");
0326       }
0327       else if (initial_capacity) {
0328          pointer reuse = pointer();
0329          size_type final_cap = static_cast<size_type>(initial_capacity);
0330          m_start = this->allocation_command(allocate_new, final_cap, final_cap, reuse);
0331          this->set_stored_capacity(final_cap);
0332       }
0333    }
0334 
0335    template<class SizeType>
0336    void do_maybe_initial_capacity(pointer p, SizeType initial_capacity)
0337    {
0338       if (BOOST_UNLIKELY(initial_capacity > size_type(-1))) {
0339          boost::container::throw_length_error("get_next_capacity, allocator's max size reached");
0340       }
0341       else if (p) {
0342          m_start = p;
0343       }
0344       else {
0345          BOOST_ASSERT(initial_capacity > 0);
0346          pointer reuse = pointer();
0347          size_type final_cap = static_cast<size_type>(initial_capacity);
0348          m_start = this->allocation_command(allocate_new, final_cap, final_cap, reuse);
0349          this->set_stored_capacity(final_cap);
0350       }
0351    }
0352 
0353    public:
0354 
0355    template <bool PropagateAllocator>
0356    inline static bool is_propagable_from(const allocator_type &from_alloc, pointer p, const allocator_type &to_alloc)
0357    {
0358       (void)p; (void)to_alloc; (void)from_alloc;
0359       const bool all_storage_propagable = !allocator_traits_type::is_partially_propagable::value ||
0360                                           !allocator_traits_type::storage_is_unpropagable(from_alloc, p);
0361       return all_storage_propagable &&
0362          (PropagateAllocator || allocator_traits_type::is_always_equal::value || allocator_traits_type::equal(from_alloc, to_alloc));
0363    }
0364 
0365    template <bool PropagateAllocator>
0366    inline static bool are_swap_propagable(const allocator_type &l_a, pointer l_p, const allocator_type &r_a, pointer r_p)
0367    {
0368       (void)l_p; (void)r_p; (void)l_a; (void)r_a;
0369       const bool all_storage_propagable = !allocator_traits_type::is_partially_propagable::value || 
0370               !(allocator_traits_type::storage_is_unpropagable(l_a, l_p) || allocator_traits_type::storage_is_unpropagable(r_a, r_p));
0371       return all_storage_propagable && (PropagateAllocator || allocator_traits_type::is_always_equal::value || allocator_traits_type::equal(l_a, r_a));
0372    }
0373 
0374    //Constructor, does not throw
0375    vector_alloc_holder()
0376       BOOST_NOEXCEPT_IF(dtl::is_nothrow_default_constructible<allocator_type>::value)
0377       : allocator_type(), m_start(), m_size(), m_capacity()
0378    {}
0379 
0380    //Constructor, does not throw
0381    template<class AllocConvertible>
0382    explicit vector_alloc_holder(BOOST_FWD_REF(AllocConvertible) a) BOOST_NOEXCEPT_OR_NOTHROW
0383       : allocator_type(boost::forward<AllocConvertible>(a)), m_start(), m_size(), m_capacity()
0384    {}
0385 
0386 
0387    template<class AllocConvertible, class SizeType>
0388    vector_alloc_holder(vector_uninitialized_size_t, BOOST_FWD_REF(AllocConvertible) a, SizeType initial_size)
0389       : allocator_type(boost::forward<AllocConvertible>(a))
0390       , m_start()
0391       //Size is initialized here so vector should only call uninitialized_xxx after this
0392       , m_size(static_cast<stored_size_type>(initial_size))
0393       , m_capacity()
0394    {  this->do_initial_capacity(initial_size);  }
0395 
0396    template<class SizeType>
0397    vector_alloc_holder(vector_uninitialized_size_t, SizeType initial_size)
0398       : allocator_type()
0399       , m_start()
0400       //Size is initialized here so vector should only call uninitialized_xxx after this
0401       , m_size(static_cast<stored_size_type>(initial_size))
0402       , m_capacity()
0403    {  this->do_initial_capacity(initial_size);  }
0404 
0405    vector_alloc_holder(initial_capacity_t, pointer p, size_type n)
0406       BOOST_NOEXCEPT_IF(dtl::is_nothrow_default_constructible<allocator_type>::value)
0407       : allocator_type()
0408       , m_start(p)
0409       , m_size()
0410       //n is guaranteed to fit into stored_size_type
0411       , m_capacity(static_cast<stored_size_type>(n))
0412    {}
0413 
0414    template<class AllocFwd>
0415    vector_alloc_holder(initial_capacity_t, pointer p, size_type n, BOOST_FWD_REF(AllocFwd) a)
0416       : allocator_type(::boost::forward<AllocFwd>(a))
0417       , m_start(p)
0418       , m_size()
0419       , m_capacity(n)
0420    {}
0421 
0422    template<class AllocConvertible, class SizeType>
0423    vector_alloc_holder(maybe_initial_capacity_t, pointer p, SizeType initial_capacity, BOOST_FWD_REF(AllocConvertible) a)
0424       : allocator_type(boost::forward<AllocConvertible>(a))
0425       //, m_start()
0426       //Size is initialized here so vector should only call uninitialized_xxx after this
0427       , m_size()
0428       , m_capacity(static_cast<stored_size_type>(initial_capacity))
0429    {  this->do_maybe_initial_capacity(p, initial_capacity);  }
0430 
0431    template<class SizeType>
0432    vector_alloc_holder(maybe_initial_capacity_t, pointer p, SizeType initial_capacity)
0433       : allocator_type()
0434       //, m_start()
0435       //Size is initialized here so vector should only call uninitialized_xxx after this
0436       , m_size()
0437       , m_capacity(static_cast<stored_size_type>(initial_capacity))
0438    {  this->do_maybe_initial_capacity(p, initial_capacity);  }
0439 
0440    vector_alloc_holder(BOOST_RV_REF(vector_alloc_holder) holder) BOOST_NOEXCEPT_OR_NOTHROW
0441       : allocator_type(BOOST_MOVE_BASE(allocator_type, holder))
0442       , m_start(holder.m_start)
0443       , m_size(holder.m_size)
0444       , m_capacity(holder.m_capacity)
0445    {
0446       holder.m_start = pointer();
0447       holder.m_size = holder.m_capacity = 0;
0448    }
0449 
0450    inline ~vector_alloc_holder() BOOST_NOEXCEPT_OR_NOTHROW
0451    {
0452       if(this->m_capacity){
0453          this->deallocate(this->m_start, this->m_capacity);
0454       }
0455    }
0456 
0457    inline void set_stored_size(size_type s) BOOST_NOEXCEPT_OR_NOTHROW
0458       {  this->m_size = static_cast<stored_size_type>(s);   }
0459 
0460    inline void dec_stored_size(size_type s) BOOST_NOEXCEPT_OR_NOTHROW
0461       {  this->m_size = static_cast<stored_size_type>(this->m_size - s);   }
0462 
0463    inline void inc_stored_size(size_type s) BOOST_NOEXCEPT_OR_NOTHROW
0464       {  this->m_size = static_cast<stored_size_type>(this->m_size + s);   }
0465 
0466    inline void set_stored_capacity(size_type c) BOOST_NOEXCEPT_OR_NOTHROW
0467       {  this->m_capacity = static_cast<stored_size_type>(c);  }
0468 
0469    inline pointer allocation_command(boost::container::allocation_type command,
0470                                  size_type limit_size, size_type &prefer_in_recvd_out_size, pointer &reuse)
0471    {
0472       typedef typename dtl::version<allocator_type>::type alloc_version;
0473       return this->priv_allocation_command(alloc_version(), command, limit_size, prefer_in_recvd_out_size, reuse);
0474    }
0475 
0476    inline pointer allocate(size_type n)
0477    {
0478       const size_type max_alloc = allocator_traits_type::max_size(this->alloc());
0479       const size_type max = max_alloc <= stored_size_type(-1) ? max_alloc : stored_size_type(-1);
0480       if (BOOST_UNLIKELY(max < n) )
0481          boost::container::throw_length_error("get_next_capacity, allocator's max size reached");
0482 
0483       return allocator_traits_type::allocate(this->alloc(), n);
0484    }
0485 
0486    inline void deallocate(const pointer &p, size_type n)
0487    {
0488       allocator_traits_type::deallocate(this->alloc(), p, n);
0489    }
0490 
0491    bool try_expand_fwd(size_type at_least)
0492    {
0493       //There is not enough memory, try to expand the old one
0494       const size_type new_cap = size_type(this->capacity() + at_least);
0495       size_type real_cap = new_cap;
0496       pointer reuse = this->start();
0497       bool const success = !!this->allocation_command(expand_fwd, new_cap, real_cap, reuse);
0498       //Check for forward expansion
0499       if(success){
0500          #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
0501          ++this->num_expand_fwd;
0502          #endif
0503          this->capacity(real_cap);
0504       }
0505       return success;
0506    }
0507 
0508    template<class GrowthFactorType>
0509    size_type next_capacity(size_type additional_objects) const
0510    {
0511       BOOST_ASSERT(additional_objects > size_type(this->m_capacity - this->m_size));
0512       size_type max = allocator_traits_type::max_size(this->alloc());
0513       (clamp_by_stored_size_type<size_type>)(max, stored_size_type());
0514       const size_type remaining_cap = size_type(max - size_type(this->m_capacity));
0515       const size_type min_additional_cap = size_type(additional_objects - size_type(this->m_capacity - this->m_size));
0516 
0517       if ( remaining_cap < min_additional_cap )
0518          boost::container::throw_length_error("get_next_capacity, allocator's max size reached");
0519 
0520       return GrowthFactorType()( size_type(this->m_capacity), min_additional_cap, max);
0521    }
0522 
0523    pointer           m_start;
0524    stored_size_type  m_size;
0525    stored_size_type  m_capacity;
0526 
0527    void swap_resources(vector_alloc_holder &x) BOOST_NOEXCEPT_OR_NOTHROW
0528    {
0529       boost::adl_move_swap(this->m_start, x.m_start);
0530       boost::adl_move_swap(this->m_size, x.m_size);
0531       boost::adl_move_swap(this->m_capacity, x.m_capacity);
0532    }
0533 
0534    void steal_resources(vector_alloc_holder &x) BOOST_NOEXCEPT_OR_NOTHROW
0535    {
0536       this->m_start     = x.m_start;
0537       this->m_size      = x.m_size;
0538       this->m_capacity  = x.m_capacity;
0539       x.m_start = pointer();
0540       x.m_size = x.m_capacity = 0;
0541    }
0542 
0543    inline allocator_type &alloc() BOOST_NOEXCEPT_OR_NOTHROW
0544    {  return *this;  }
0545 
0546    inline const allocator_type &alloc() const BOOST_NOEXCEPT_OR_NOTHROW
0547    {  return *this;  }
0548 
0549    inline pointer   start() const     BOOST_NOEXCEPT_OR_NOTHROW
0550       {  return m_start;  }
0551    inline       size_type capacity() const     BOOST_NOEXCEPT_OR_NOTHROW
0552       {  return m_capacity;  }
0553    inline void start(const pointer &p)       BOOST_NOEXCEPT_OR_NOTHROW
0554       {  m_start = p;  }
0555    inline void capacity(const size_type &c)  BOOST_NOEXCEPT_OR_NOTHROW
0556       {  BOOST_ASSERT( c <= stored_size_type(-1)); this->set_stored_capacity(c);  }
0557 
0558    static inline void on_capacity_overflow()
0559    { }
0560 
0561    private:
0562    void priv_first_allocation(size_type cap)
0563    {
0564       if(cap){
0565          pointer reuse = pointer();
0566          m_start = this->allocation_command(allocate_new, cap, cap, reuse);
0567          m_capacity = cap;
0568          #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
0569          ++this->num_alloc;
0570          #endif
0571       }
0572    }
0573 
0574    pointer priv_allocation_command(version_1, boost::container::allocation_type command,
0575                          size_type limit_size,
0576                          size_type &prefer_in_recvd_out_size,
0577                          pointer &reuse)
0578    {
0579       (void)command;
0580       BOOST_ASSERT( (command & allocate_new));
0581       BOOST_ASSERT(!(command & nothrow_allocation));
0582       //First detect overflow on smaller stored_size_types
0583       if (BOOST_UNLIKELY(limit_size > stored_size_type(-1))){
0584          boost::container::throw_length_error("get_next_capacity, allocator's max size reached");
0585       }
0586       (clamp_by_stored_size_type<size_type>)(prefer_in_recvd_out_size, stored_size_type());
0587       pointer const p = this->allocate(prefer_in_recvd_out_size);
0588       reuse = pointer();
0589       return p;
0590    }
0591 
0592    pointer priv_allocation_command(version_2, boost::container::allocation_type command,
0593                          size_type limit_size,
0594                          size_type &prefer_in_recvd_out_size,
0595                          pointer &reuse)
0596    {
0597       //First detect overflow on smaller stored_size_types
0598       if (BOOST_UNLIKELY(limit_size > stored_size_type(-1))){
0599          boost::container::throw_length_error("get_next_capacity, allocator's max size reached");
0600       }
0601       (clamp_by_stored_size_type<size_type>)(prefer_in_recvd_out_size, stored_size_type());
0602       //Allocate memory 
0603       pointer p = this->alloc().allocation_command(command, limit_size, prefer_in_recvd_out_size, reuse);
0604       //If after allocation prefer_in_recvd_out_size is not representable by stored_size_type, truncate it.
0605       (clamp_by_stored_size_type<size_type>)(prefer_in_recvd_out_size, stored_size_type());
0606       return p;
0607    }
0608 };
0609 
0610 //!This struct deallocates and allocated memory
0611 template <class Allocator, class StoredSizeType>
0612 struct vector_alloc_holder<Allocator, StoredSizeType, version_0>
0613    : public Allocator
0614 {
0615    private:
0616    BOOST_MOVABLE_BUT_NOT_COPYABLE(vector_alloc_holder)
0617 
0618    public:
0619    typedef Allocator                                     allocator_type;
0620    typedef boost::container::
0621       allocator_traits<allocator_type>                   allocator_traits_type;
0622    typedef typename allocator_traits_type::pointer       pointer;
0623    typedef typename allocator_traits_type::size_type     size_type;
0624    typedef typename allocator_traits_type::value_type    value_type;
0625    typedef StoredSizeType                                stored_size_type;
0626       
0627    template <class OtherAllocator, class OtherStoredSizeType, class OtherAllocatorVersion>
0628    friend struct vector_alloc_holder;
0629 
0630    //Constructor, does not throw
0631    vector_alloc_holder()
0632       BOOST_NOEXCEPT_IF(dtl::is_nothrow_default_constructible<allocator_type>::value)
0633       : allocator_type(), m_size()
0634    {}
0635 
0636    //Constructor, does not throw
0637    template<class AllocConvertible>
0638    explicit vector_alloc_holder(BOOST_FWD_REF(AllocConvertible) a) BOOST_NOEXCEPT_OR_NOTHROW
0639       : allocator_type(boost::forward<AllocConvertible>(a)), m_size()
0640    {}
0641 
0642    //Constructor, does not throw
0643    template<class AllocConvertible>
0644    vector_alloc_holder(vector_uninitialized_size_t, BOOST_FWD_REF(AllocConvertible) a, size_type initial_size)
0645       : allocator_type(boost::forward<AllocConvertible>(a))
0646       , m_size(initial_size)  //Size is initialized here...
0647    {
0648       //... and capacity here, so vector, must call uninitialized_xxx in the derived constructor
0649       this->priv_first_allocation(initial_size);
0650    }
0651 
0652    //Constructor, does not throw
0653    vector_alloc_holder(vector_uninitialized_size_t, size_type initial_size)
0654       : allocator_type()
0655       , m_size(initial_size)  //Size is initialized here...
0656    {
0657       //... and capacity here, so vector, must call uninitialized_xxx in the derived constructor
0658       this->priv_first_allocation(initial_size);
0659    }
0660 
0661    vector_alloc_holder(BOOST_RV_REF(vector_alloc_holder) holder)
0662       : allocator_type(BOOST_MOVE_BASE(allocator_type, holder))
0663       , m_size(holder.m_size) //Size is initialized here so vector should only call uninitialized_xxx after this
0664    {
0665       ::boost::container::uninitialized_move_alloc_n
0666          (this->alloc(), boost::movelib::to_raw_pointer(holder.start()), m_size, boost::movelib::to_raw_pointer(this->start()));
0667       ::boost::container::destroy_alloc_n
0668          (this->alloc(), boost::movelib::to_raw_pointer(holder.start()), m_size);
0669       holder.m_size = 0;
0670    }
0671 
0672    template<class OtherAllocator, class OtherStoredSizeType, class OtherAllocatorVersion>
0673    vector_alloc_holder(BOOST_RV_REF_BEG vector_alloc_holder<OtherAllocator, OtherStoredSizeType, OtherAllocatorVersion> BOOST_RV_REF_END holder)
0674       : allocator_type()
0675       , m_size(holder.m_size) //Initialize it to m_size as first_allocation can only succeed or abort
0676    {
0677       //Different allocator type so we must check we have enough storage
0678       const size_type n = holder.m_size;
0679       this->priv_first_allocation(n);
0680       ::boost::container::uninitialized_move_alloc_n
0681          (this->alloc(), boost::movelib::to_raw_pointer(holder.start()), n, boost::movelib::to_raw_pointer(this->start()));
0682    }
0683 
0684    static inline void on_capacity_overflow()
0685    {  allocator_type::on_capacity_overflow();  }
0686 
0687    inline void set_stored_size(size_type s) BOOST_NOEXCEPT_OR_NOTHROW
0688       {  this->m_size = static_cast<stored_size_type>(s);   }
0689 
0690    inline void dec_stored_size(size_type s) BOOST_NOEXCEPT_OR_NOTHROW
0691       {  this->m_size = static_cast<stored_size_type>(this->m_size - s);   }
0692 
0693    inline void inc_stored_size(size_type s) BOOST_NOEXCEPT_OR_NOTHROW
0694       {  this->m_size = static_cast<stored_size_type>(this->m_size + s);   }
0695 
0696    inline void priv_first_allocation(size_type cap)
0697    {
0698       if(cap > allocator_type::internal_capacity){
0699          on_capacity_overflow();
0700       }
0701    }
0702 
0703    inline void deep_swap(vector_alloc_holder &x)
0704       {  this->priv_deep_swap(x);   }
0705 
0706    template<class OtherAllocator, class OtherStoredSizeType, class OtherAllocatorVersion>
0707    void deep_swap(vector_alloc_holder<OtherAllocator, OtherStoredSizeType, OtherAllocatorVersion> &x)
0708    {
0709       typedef typename real_allocator<value_type, OtherAllocator>::type other_allocator_type;
0710       if(this->m_size > other_allocator_type::internal_capacity || x.m_size > allocator_type::internal_capacity){
0711          on_capacity_overflow();
0712       }
0713       this->priv_deep_swap(x);
0714    }
0715 
0716    inline void swap_resources(vector_alloc_holder &) BOOST_NOEXCEPT_OR_NOTHROW
0717    {  //Containers with version 0 allocators can't be moved without moving elements one by one
0718       on_capacity_overflow();
0719    }
0720 
0721    inline void steal_resources(vector_alloc_holder &)
0722    {  //Containers with version 0 allocators can't be moved without moving elements one by one
0723       on_capacity_overflow();
0724    }
0725 
0726    inline allocator_type &alloc() BOOST_NOEXCEPT_OR_NOTHROW
0727    {  return *this;  }
0728 
0729    inline const allocator_type &alloc() const BOOST_NOEXCEPT_OR_NOTHROW
0730    {  return *this;  }
0731 
0732    inline bool try_expand_fwd(size_type at_least)
0733    {  return !at_least;  }
0734 
0735    inline pointer start() const       BOOST_NOEXCEPT_OR_NOTHROW
0736    {  return allocator_type::internal_storage();  }
0737    
0738    inline size_type capacity() const BOOST_NOEXCEPT_OR_NOTHROW
0739    {  return allocator_type::internal_capacity;  }
0740    
0741    stored_size_type m_size;
0742 
0743    private:
0744 
0745    template<class OtherAllocator, class OtherStoredSizeType, class OtherAllocatorVersion>
0746    void priv_deep_swap(vector_alloc_holder<OtherAllocator, OtherStoredSizeType, OtherAllocatorVersion> &x)
0747    {
0748       const size_type MaxTmpStorage = sizeof(value_type)*allocator_type::internal_capacity;
0749       value_type *const first_this = boost::movelib::to_raw_pointer(this->start());
0750       value_type *const first_x = boost::movelib::to_raw_pointer(x.start());
0751 
0752       if(this->m_size < x.m_size){
0753          boost::container::deep_swap_alloc_n<MaxTmpStorage>(this->alloc(), first_this, this->m_size, first_x, x.m_size);
0754       }
0755       else{
0756          boost::container::deep_swap_alloc_n<MaxTmpStorage>(this->alloc(), first_x, x.m_size, first_this, this->m_size);
0757       }
0758       boost::adl_move_swap(this->m_size, x.m_size);
0759    }
0760 };
0761 
0762 struct growth_factor_60;
0763 struct growth_factor_100;
0764 
0765 template<class Options, class AllocatorSizeType>
0766 struct get_vector_opt
0767 {
0768    typedef vector_opt< typename default_if_void<typename Options::growth_factor_type, growth_factor_60>::type
0769                      , typename default_if_void<typename Options::stored_size_type, AllocatorSizeType>::type
0770                      > type;
0771 };
0772 
0773 template<class AllocatorSizeType>
0774 struct get_vector_opt<void, AllocatorSizeType>
0775 {
0776    typedef vector_opt<growth_factor_60, AllocatorSizeType> type;
0777 };
0778 
0779 #endif   //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
0780 
0781 //! A vector is a sequence that supports random access to elements, constant
0782 //! time insertion and removal of elements at the end, and linear time insertion
0783 //! and removal of elements at the beginning or in the middle. The number of
0784 //! elements in a vector may vary dynamically; memory management is automatic.
0785 //!
0786 //! \tparam T The type of object that is stored in the vector
0787 //! \tparam A The allocator used for all internal memory management, use void
0788 //!   for the default allocator
0789 //! \tparam Options A type produced from \c boost::container::vector_options.
0790 template <class T, class A BOOST_CONTAINER_DOCONLY(= void), class Options BOOST_CONTAINER_DOCONLY(= void) >
0791 class vector
0792 {
0793 public:
0794    //////////////////////////////////////////////
0795    //
0796    //                    types
0797    //
0798    //////////////////////////////////////////////
0799    typedef T                                                                           value_type;
0800    typedef BOOST_CONTAINER_IMPDEF
0801       (typename real_allocator<T BOOST_MOVE_I A>::type)                                allocator_type;
0802    typedef ::boost::container::allocator_traits<allocator_type>                        allocator_traits_t;
0803    typedef typename   allocator_traits<allocator_type>::pointer                        pointer;
0804    typedef typename   allocator_traits<allocator_type>::const_pointer                  const_pointer;
0805    typedef typename   allocator_traits<allocator_type>::reference                      reference;
0806    typedef typename   allocator_traits<allocator_type>::const_reference                const_reference;
0807    typedef typename   allocator_traits<allocator_type>::size_type                      size_type;
0808    typedef typename   allocator_traits<allocator_type>::difference_type                difference_type;
0809    typedef allocator_type                                                              stored_allocator_type;
0810    typedef BOOST_CONTAINER_IMPDEF(vec_iterator<pointer BOOST_MOVE_I false>)            iterator;
0811    typedef BOOST_CONTAINER_IMPDEF(vec_iterator<pointer BOOST_MOVE_I true >)            const_iterator;
0812    typedef BOOST_CONTAINER_IMPDEF(boost::container::reverse_iterator<iterator>)        reverse_iterator;
0813    typedef BOOST_CONTAINER_IMPDEF(boost::container::reverse_iterator<const_iterator>)  const_reverse_iterator;
0814 
0815 private:
0816 
0817    #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
0818    typedef typename boost::container::
0819       allocator_traits<allocator_type>::size_type                             alloc_size_type;
0820    typedef typename get_vector_opt<Options, alloc_size_type>::type            options_type;
0821    typedef typename options_type::growth_factor_type                          growth_factor_type;
0822    typedef typename options_type::stored_size_type                            stored_size_type;
0823    typedef value_less<T>                                                      value_less_t;
0824 
0825    //If provided the stored_size option must specify a type that is equal or a type that is smaller.
0826    BOOST_CONTAINER_STATIC_ASSERT( (sizeof(stored_size_type) < sizeof(alloc_size_type) ||
0827                         dtl::is_same<stored_size_type, alloc_size_type>::value) );
0828 
0829    typedef typename dtl::version<allocator_type>::type alloc_version;
0830    typedef boost::container::vector_alloc_holder
0831       <allocator_type, stored_size_type> alloc_holder_t;
0832 
0833    alloc_holder_t m_holder;
0834 
0835    typedef allocator_traits<allocator_type>                      allocator_traits_type;
0836    template <class U, class UA, class UOptions>
0837    friend class vector;
0838 
0839 
0840    protected:
0841    template <bool PropagateAllocator>
0842    inline static bool is_propagable_from(const allocator_type &from_alloc, pointer p, const allocator_type &to_alloc)
0843    {  return alloc_holder_t::template is_propagable_from<PropagateAllocator>(from_alloc, p, to_alloc);  }
0844 
0845    template <bool PropagateAllocator>
0846    inline static bool are_swap_propagable( const allocator_type &l_a, pointer l_p
0847                                          , const allocator_type &r_a, pointer r_p)
0848    {  return alloc_holder_t::template are_swap_propagable<PropagateAllocator>(l_a, l_p, r_a, r_p);  }
0849 
0850    #endif   //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
0851    #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
0852    private:
0853    BOOST_COPYABLE_AND_MOVABLE(vector)
0854    typedef vector_value_traits<allocator_type> value_traits;
0855    typedef constant_iterator<T>            cvalue_iterator;
0856 
0857    protected:
0858 
0859    inline void steal_resources(vector &x)
0860    {  return this->m_holder.steal_resources(x.m_holder);   }
0861 
0862    inline void protected_set_size(size_type n)
0863    {  this->m_holder.m_size = static_cast<stored_size_type>(n);   }
0864 
0865    template<class AllocFwd>
0866    inline vector(initial_capacity_t, pointer initial_memory, size_type cap, BOOST_FWD_REF(AllocFwd) a)
0867       : m_holder(initial_capacity_t(), initial_memory, cap, ::boost::forward<AllocFwd>(a))
0868    {}
0869 
0870    template<class AllocFwd>
0871    inline vector(initial_capacity_t, pointer initial_memory, size_type cap, BOOST_FWD_REF(AllocFwd) a, vector &x)
0872       : m_holder(initial_capacity_t(), initial_memory, cap, ::boost::forward<AllocFwd>(a))
0873    {
0874       allocator_type &this_al = this->get_stored_allocator();
0875       if (this->template is_propagable_from<true>(x.get_stored_allocator(), x.data(), this_al)) {
0876          this->steal_resources(x);
0877       }
0878       else {
0879          const size_type sz = x.size();
0880          ::boost::container::uninitialized_move_alloc_n_source
0881             ( this_al, x.priv_raw_begin(), sz
0882             //Use launder to stop false positives from -Warray-bounds
0883             , boost::move_detail::launder(this->priv_raw_begin()));
0884          this->protected_set_size(sz);
0885          x.clear();
0886       }
0887    }
0888 
0889    inline vector(initial_capacity_t, pointer initial_memory, size_type cap)
0890       : m_holder(initial_capacity_t(), initial_memory, cap)
0891    {}
0892 
0893    template<class SizeType, class AllocFwd>
0894    inline vector(maybe_initial_capacity_t, pointer p, SizeType initial_capacity, BOOST_FWD_REF(AllocFwd) a)
0895       : m_holder(maybe_initial_capacity_t(), p, initial_capacity, ::boost::forward<AllocFwd>(a))
0896    {
0897       #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
0898       this->num_alloc += size_type(p != pointer());
0899       #endif
0900    }
0901 
0902    template<class SizeType>
0903    inline vector(maybe_initial_capacity_t, pointer p, SizeType initial_capacity)
0904       : m_holder(maybe_initial_capacity_t(), p, initial_capacity)
0905    {
0906       #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
0907       this->num_alloc += size_type(p != pointer());
0908       #endif
0909    }
0910 
0911    template <class U>
0912    void protected_init_n(const size_type new_size, const U& u)
0913    {
0914       BOOST_ASSERT(this->empty());
0915       this->priv_resize_proxy(u).uninitialized_copy_n_and_update(this->m_holder.alloc(), this->priv_raw_begin(), new_size);
0916       this->m_holder.set_stored_size(new_size);
0917    }
0918 
0919    #endif   //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
0920 
0921    public:
0922    //////////////////////////////////////////////
0923    //
0924    //          construct/copy/destroy
0925    //
0926    //////////////////////////////////////////////
0927 
0928    //! <b>Effects</b>: Constructs a vector taking the allocator as parameter.
0929    //!
0930    //! <b>Throws</b>: Nothing.
0931    //!
0932    //! <b>Complexity</b>: Constant.
0933    vector() BOOST_NOEXCEPT_IF(dtl::is_nothrow_default_constructible<allocator_type>::value)
0934       : m_holder()
0935    {}
0936 
0937    //! <b>Effects</b>: Constructs a vector taking the allocator as parameter.
0938    //!
0939    //! <b>Throws</b>: Nothing
0940    //!
0941    //! <b>Complexity</b>: Constant.
0942    explicit vector(const allocator_type& a) BOOST_NOEXCEPT_OR_NOTHROW
0943       : m_holder(a)
0944    {}
0945 
0946    //! <b>Effects</b>: Constructs a vector and inserts n value initialized values.
0947    //!
0948    //! <b>Throws</b>: If allocator_type's allocation
0949    //!   throws or T's value initialization throws.
0950    //!
0951    //! <b>Complexity</b>: Linear to n.
0952    explicit vector(size_type n)
0953       :  m_holder(vector_uninitialized_size, n)
0954    {
0955       #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
0956       this->num_alloc += n != 0;
0957       #endif
0958       boost::container::uninitialized_value_init_alloc_n
0959          (this->m_holder.alloc(), n, this->priv_raw_begin());
0960    }
0961 
0962    //! <b>Effects</b>: Constructs a vector that will use a copy of allocator a
0963    //!   and inserts n value initialized values.
0964    //!
0965    //! <b>Throws</b>: If allocator_type's allocation
0966    //!   throws or T's value initialization throws.
0967    //!
0968    //! <b>Complexity</b>: Linear to n.
0969    explicit vector(size_type n, const allocator_type &a)
0970       :  m_holder(vector_uninitialized_size, a, n)
0971    {
0972       #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
0973       this->num_alloc += n != 0;
0974       #endif
0975       boost::container::uninitialized_value_init_alloc_n
0976          (this->m_holder.alloc(), n, this->priv_raw_begin());
0977    }
0978 
0979    //! <b>Effects</b>: Constructs a vector that will use a copy of allocator a
0980    //!   and inserts n default initialized values.
0981    //!
0982    //! <b>Throws</b>: If allocator_type's allocation
0983    //!   throws or T's default initialization throws.
0984    //!
0985    //! <b>Complexity</b>: Linear to n.
0986    //!
0987    //! <b>Note</b>: Non-standard extension
0988    vector(size_type n, default_init_t)
0989       :  m_holder(vector_uninitialized_size, n)
0990    {
0991       #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
0992       this->num_alloc += n != 0;
0993       #endif
0994       boost::container::uninitialized_default_init_alloc_n
0995          (this->m_holder.alloc(), n, this->priv_raw_begin());
0996    }
0997 
0998    //! <b>Effects</b>: Constructs a vector that will use a copy of allocator a
0999    //!   and inserts n default initialized values.
1000    //!
1001    //! <b>Throws</b>: If allocator_type's allocation
1002    //!   throws or T's default initialization throws.
1003    //!
1004    //! <b>Complexity</b>: Linear to n.
1005    //!
1006    //! <b>Note</b>: Non-standard extension
1007    vector(size_type n, default_init_t, const allocator_type &a)
1008       :  m_holder(vector_uninitialized_size, a, n)
1009    {
1010       #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
1011       this->num_alloc += n != 0;
1012       #endif
1013       boost::container::uninitialized_default_init_alloc_n
1014          (this->m_holder.alloc(), n, this->priv_raw_begin());
1015    }
1016 
1017    //! <b>Effects</b>: Constructs a vector
1018    //!   and inserts n copies of value.
1019    //!
1020    //! <b>Throws</b>: If allocator_type's allocation
1021    //!   throws or T's copy constructor throws.
1022    //!
1023    //! <b>Complexity</b>: Linear to n.
1024    vector(size_type n, const T& value)
1025       :  m_holder(vector_uninitialized_size, n)
1026    {
1027       #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
1028       this->num_alloc += n != 0;
1029       #endif
1030       boost::container::uninitialized_fill_alloc_n
1031          (this->m_holder.alloc(), value, n, this->priv_raw_begin());
1032    }
1033 
1034    //! <b>Effects</b>: Constructs a vector that will use a copy of allocator a
1035    //!   and inserts n copies of value.
1036    //!
1037    //! <b>Throws</b>: If allocation
1038    //!   throws or T's copy constructor throws.
1039    //!
1040    //! <b>Complexity</b>: Linear to n.
1041    vector(size_type n, const T& value, const allocator_type& a)
1042       :  m_holder(vector_uninitialized_size, a, n)
1043    {
1044       #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
1045       this->num_alloc += n != 0;
1046       #endif
1047       boost::container::uninitialized_fill_alloc_n
1048          (this->m_holder.alloc(), value, n, this->priv_raw_begin());
1049    }
1050 
1051    //! <b>Effects</b>: Constructs a vector
1052    //!   and inserts a copy of the range [first, last) in the vector.
1053    //!
1054    //! <b>Throws</b>: If allocator_type's allocation
1055    //!   throws or T's constructor taking a dereferenced InIt throws.
1056    //!
1057    //! <b>Complexity</b>: Linear to the range [first, last).
1058 //    template <class InIt>
1059 //    vector(InIt first, InIt last
1060 //           BOOST_CONTAINER_DOCIGN(BOOST_MOVE_I typename dtl::disable_if_c
1061 //                                  < dtl::is_convertible<InIt BOOST_MOVE_I size_type>::value
1062 //                                  BOOST_MOVE_I dtl::nat >::type * = 0)
1063 //           ) -> vector<typename iterator_traits<InIt>::value_type, new_allocator<typename iterator_traits<InIt>::value_type>>;
1064    template <class InIt>
1065    vector(InIt first, InIt last
1066       BOOST_CONTAINER_DOCIGN(BOOST_MOVE_I typename dtl::disable_if_c
1067          < dtl::is_convertible<InIt BOOST_MOVE_I size_type>::value
1068          BOOST_MOVE_I dtl::nat >::type * = 0)
1069       )
1070       :  m_holder()
1071    {  this->assign(first, last); }
1072 
1073    //! <b>Effects</b>: Constructs a vector that will use a copy of allocator a
1074    //!   and inserts a copy of the range [first, last) in the vector.
1075    //!
1076    //! <b>Throws</b>: If allocator_type's allocation
1077    //!   throws or T's constructor taking a dereferenced InIt throws.
1078    //!
1079    //! <b>Complexity</b>: Linear to the range [first, last).
1080    template <class InIt>
1081    vector(InIt first, InIt last, const allocator_type& a
1082       BOOST_CONTAINER_DOCIGN(BOOST_MOVE_I typename dtl::disable_if_c
1083          < dtl::is_convertible<InIt BOOST_MOVE_I size_type>::value
1084          BOOST_MOVE_I dtl::nat >::type * = 0)
1085       )
1086       :  m_holder(a)
1087    {  this->assign(first, last); }
1088 
1089    //! <b>Effects</b>: Copy constructs a vector.
1090    //!
1091    //! <b>Postcondition</b>: x == *this.
1092    //!
1093    //! <b>Throws</b>: If allocator_type's allocation
1094    //!   throws or T's copy constructor throws.
1095    //!
1096    //! <b>Complexity</b>: Linear to the elements x contains.
1097    vector(const vector &x)
1098       :  m_holder( vector_uninitialized_size
1099                  , allocator_traits_type::select_on_container_copy_construction(x.m_holder.alloc())
1100                  , x.size())
1101    {
1102       #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
1103       this->num_alloc += x.size() != 0;
1104       #endif
1105       ::boost::container::uninitialized_copy_alloc_n
1106          ( this->m_holder.alloc(), x.priv_raw_begin()
1107          , x.size(), this->priv_raw_begin());
1108    }
1109 
1110    //! <b>Effects</b>: Move constructor. Moves x's resources to *this.
1111    //!
1112    //! <b>Throws</b>: Nothing
1113    //!
1114    //! <b>Complexity</b>: Constant.
1115    vector(BOOST_RV_REF(vector) x) BOOST_NOEXCEPT_OR_NOTHROW
1116       :  m_holder(boost::move(x.m_holder))
1117    {  BOOST_CONTAINER_STATIC_ASSERT((!allocator_traits_type::is_partially_propagable::value));  }
1118 
1119    #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
1120    //! <b>Effects</b>: Constructs a vector that will use a copy of allocator a
1121    //!  and inserts a copy of the range [il.begin(), il.last()) in the vector
1122    //!
1123    //! <b>Throws</b>: If T's constructor taking a dereferenced initializer_list iterator throws.
1124    //!
1125    //! <b>Complexity</b>: Linear to the range [il.begin(), il.end()).
1126    vector(std::initializer_list<value_type> il, const allocator_type& a = allocator_type())
1127       :  m_holder(vector_uninitialized_size, a, il.size())
1128    {
1129       #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
1130       this->num_alloc += il.size() != 0;
1131       #endif
1132       ::boost::container::uninitialized_copy_alloc_n_source
1133          ( this->m_holder.alloc(), il.begin()
1134          , static_cast<size_type>(il.size()), this->priv_raw_begin());
1135    }
1136    #endif
1137 
1138    #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
1139 
1140    //! <b>Effects</b>: Move constructor. Moves x's resources to *this.
1141    //!
1142    //! <b>Throws</b>: If T's move constructor or allocation throws
1143    //!
1144    //! <b>Complexity</b>: Linear.
1145    //!
1146    //! <b>Note</b>: Non-standard extension to support static_vector
1147    template<class OtherA>
1148    vector(BOOST_RV_REF_BEG vector<T, OtherA, Options> BOOST_RV_REF_END x
1149          , typename dtl::enable_if_c
1150             < dtl::is_version<typename real_allocator<T, OtherA>::type, 0>::value>::type * = 0
1151          )
1152       :  m_holder(boost::move(x.m_holder))
1153    {}
1154 
1155    #endif   // defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
1156 
1157    //! <b>Effects</b>: Copy constructs a vector using the specified allocator.
1158    //!
1159    //! <b>Postcondition</b>: x == *this.
1160    //!
1161    //! <b>Throws</b>: If allocation
1162    //!   throws or T's copy constructor throws.
1163    //!
1164    //! <b>Complexity</b>: Linear to the elements x contains.
1165    vector(const vector &x, const allocator_type &a)
1166       :  m_holder(vector_uninitialized_size, a, x.size())
1167    {
1168       #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
1169       this->num_alloc += x.size() != 0;
1170       #endif
1171       ::boost::container::uninitialized_copy_alloc_n_source
1172          ( this->m_holder.alloc(), x.priv_raw_begin()
1173          , x.size(), this->priv_raw_begin());
1174    }
1175 
1176    //! <b>Effects</b>: Move constructor using the specified allocator.
1177    //!                 Moves x's resources to *this if a == allocator_type().
1178    //!                 Otherwise copies values from x to *this.
1179    //!
1180    //! <b>Throws</b>: If allocation or T's copy constructor throws.
1181    //!
1182    //! <b>Complexity</b>: Constant if a == x.get_allocator(), linear otherwise.
1183    vector(BOOST_RV_REF(vector) x, const allocator_type &a)
1184       :  m_holder( vector_uninitialized_size, a
1185                  //In this allocator move constructor the allocator won't be propagated --v
1186                  , is_propagable_from<false>(x.get_stored_allocator(), x.m_holder.start(), a) ? 0 : x.size()
1187                  )
1188    {
1189       //In this allocator move constructor the allocator won't be propagated ---v
1190       if(is_propagable_from<false>(x.get_stored_allocator(), x.m_holder.start(), a)){
1191          this->m_holder.steal_resources(x.m_holder);
1192       }
1193       else{
1194          const size_type n = x.size();
1195          #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
1196          this->num_alloc += n != 0;
1197          #endif
1198          ::boost::container::uninitialized_move_alloc_n_source
1199             ( this->m_holder.alloc(), x.priv_raw_begin()
1200             , n, this->priv_raw_begin());
1201       }
1202    }
1203 
1204    //! <b>Effects</b>: Destroys the vector. All stored values are destroyed
1205    //!   and used memory is deallocated.
1206    //!
1207    //! <b>Throws</b>: Nothing.
1208    //!
1209    //! <b>Complexity</b>: Linear to the number of elements.
1210    ~vector() BOOST_NOEXCEPT_OR_NOTHROW
1211    {
1212       boost::container::destroy_alloc_n
1213          (this->get_stored_allocator(), this->priv_raw_begin(), this->m_holder.m_size);
1214       //vector_alloc_holder deallocates the data
1215    }
1216 
1217    //! <b>Effects</b>: Makes *this contain the same elements as x.
1218    //!
1219    //! <b>Postcondition</b>: this->size() == x.size(). *this contains a copy
1220    //! of each of x's elements.
1221    //!
1222    //! <b>Throws</b>: If memory allocation throws or T's copy/move constructor/assignment throws.
1223    //!
1224    //! <b>Complexity</b>: Linear to the number of elements in x.
1225    inline vector& operator=(BOOST_COPY_ASSIGN_REF(vector) x)
1226    {
1227       if (BOOST_LIKELY(&x != this)){
1228          this->priv_copy_assign(x);
1229       }
1230       return *this;
1231    }
1232 
1233    #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
1234    //! <b>Effects</b>: Make *this container contains elements from il.
1235    //!
1236    //! <b>Complexity</b>: Linear to the range [il.begin(), il.end()).
1237    inline vector& operator=(std::initializer_list<value_type> il)
1238    {
1239       this->assign(il.begin(), il.end());
1240       return *this;
1241    }
1242    #endif
1243 
1244    //! <b>Effects</b>: Move assignment. All x's values are transferred to *this.
1245    //!
1246    //! <b>Postcondition</b>: x.empty(). *this contains a the elements x had
1247    //!   before the function.
1248    //!
1249    //! <b>Throws</b>: If allocator_traits_type::propagate_on_container_move_assignment
1250    //!   is false and (allocation throws or value_type's move constructor throws)
1251    //!
1252    //! <b>Complexity</b>: Constant if allocator_traits_type::
1253    //!   propagate_on_container_move_assignment is true or
1254    //!   this->get>allocator() == x.get_allocator(). Linear otherwise.
1255    inline vector& operator=(BOOST_RV_REF(vector) x)
1256       BOOST_NOEXCEPT_IF(allocator_traits_type::propagate_on_container_move_assignment::value
1257                         || allocator_traits_type::is_always_equal::value)
1258    {
1259       if (BOOST_LIKELY(&x != this)){
1260          this->priv_move_assign(boost::move(x));
1261       }
1262       return *this;
1263    }
1264 
1265    #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
1266 
1267    //! <b>Effects</b>: Move assignment. All x's values are transferred to *this.
1268    //!
1269    //! <b>Postcondition</b>: x.empty(). *this contains a the elements x had
1270    //!   before the function.
1271    //!
1272    //! <b>Throws</b>: If move constructor/assignment of T throws or allocation throws
1273    //!
1274    //! <b>Complexity</b>: Linear.
1275    //!
1276    //! <b>Note</b>: Non-standard extension to support static_vector
1277    template<class OtherA>
1278    inline typename dtl::enable_if_and
1279                            < vector&
1280                            , dtl::is_version<typename real_allocator<T, OtherA>::type, 0>
1281                            , dtl::is_different<typename real_allocator<T, OtherA>::type, allocator_type>
1282                            >::type
1283       operator=(BOOST_RV_REF_BEG vector<value_type, OtherA, Options> BOOST_RV_REF_END x)
1284    {
1285       this->priv_move_assign(boost::move(x));
1286       return *this;
1287    }
1288 
1289    //! <b>Effects</b>: Copy assignment. All x's values are copied to *this.
1290    //!
1291    //! <b>Postcondition</b>: x.empty(). *this contains a the elements x had
1292    //!   before the function.
1293    //!
1294    //! <b>Throws</b>: If move constructor/assignment of T throws or allocation throws
1295    //!
1296    //! <b>Complexity</b>: Linear.
1297    //!
1298    //! <b>Note</b>: Non-standard extension to support static_vector
1299    template<class OtherA>
1300    inline typename dtl::enable_if_and
1301                            < vector&
1302                            , dtl::is_version<typename real_allocator<T, OtherA>::type, 0>
1303                            , dtl::is_different<typename real_allocator<T, OtherA>::type, allocator_type>
1304                            >::type
1305       operator=(const vector<value_type, OtherA, Options> &x)
1306    {
1307       this->priv_copy_assign(x);
1308       return *this;
1309    }
1310 
1311    #endif
1312 
1313    //! <b>Effects</b>: Assigns the the range [first, last) to *this.
1314    //!
1315    //! <b>Throws</b>: If memory allocation throws or T's copy/move constructor/assignment or
1316    //!   T's constructor/assignment from dereferencing InpIt throws.
1317    //!
1318    //! <b>Complexity</b>: Linear to n.
1319    template <class InIt>
1320    void assign(InIt first, InIt last
1321       //Input iterators or version 0 allocator
1322       BOOST_CONTAINER_DOCIGN(BOOST_MOVE_I typename dtl::disable_if_or
1323          < void
1324          BOOST_MOVE_I dtl::is_convertible<InIt BOOST_MOVE_I size_type>
1325          BOOST_MOVE_I dtl::and_
1326             < dtl::is_different<alloc_version BOOST_MOVE_I version_0>
1327             BOOST_MOVE_I dtl::is_not_input_iterator<InIt>
1328             >
1329          >::type * = 0)
1330       )
1331    {
1332       //Overwrite all elements we can from [first, last)
1333       iterator cur = this->begin();
1334       const iterator end_it = this->end();
1335       for ( ; first != last && cur != end_it; ++cur, ++first){
1336          *cur = *first;
1337       }
1338 
1339       if (first == last){
1340          //There are no more elements in the sequence, erase remaining
1341          T* const end_pos = this->priv_raw_end();
1342          const size_type n = static_cast<size_type>(end_pos - boost::movelib::iterator_to_raw_pointer(cur));
1343          this->priv_destroy_last_n(n);
1344       }
1345       else{
1346          //There are more elements in the range, insert the remaining ones
1347          this->insert(this->cend(), first, last);
1348       }
1349    }
1350 
1351    #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
1352    //! <b>Effects</b>: Assigns the the range [il.begin(), il.end()) to *this.
1353    //!
1354    //! <b>Throws</b>: If memory allocation throws or
1355    //!   T's constructor from dereferencing iniializer_list iterator throws.
1356    //!
1357    inline void assign(std::initializer_list<T> il)
1358    {
1359       this->assign(il.begin(), il.end());
1360    }
1361    #endif
1362 
1363    //! <b>Effects</b>: Assigns the the range [first, last) to *this.
1364    //!
1365    //! <b>Throws</b>: If memory allocation throws or T's copy/move constructor/assignment or
1366    //!   T's constructor/assignment from dereferencing InpIt throws.
1367    //!
1368    //! <b>Complexity</b>: Linear to n.
1369    template <class FwdIt>
1370    void assign(FwdIt first, FwdIt last
1371       //Forward iterators and version > 0 allocator
1372       BOOST_CONTAINER_DOCIGN(BOOST_MOVE_I typename dtl::disable_if_or
1373          < void
1374          BOOST_MOVE_I dtl::is_same<alloc_version BOOST_MOVE_I version_0>
1375          BOOST_MOVE_I dtl::is_convertible<FwdIt BOOST_MOVE_I size_type>
1376          BOOST_MOVE_I dtl::is_input_iterator<FwdIt>
1377          >::type * = 0)
1378       )
1379    {
1380       typedef typename iter_size<FwdIt>::type it_size_type;
1381       //For Fwd iterators the standard only requires EmplaceConstructible and assignable from *first
1382       //so we can't do any backwards allocation
1383       const it_size_type sz = boost::container::iterator_udistance(first, last);
1384       if (BOOST_UNLIKELY(sz > size_type(-1))){
1385          boost::container::throw_length_error("vector::assign, FwdIt's max length reached");
1386       }
1387 
1388       const size_type input_sz = static_cast<size_type>(sz);
1389       const size_type old_capacity = this->capacity();
1390       if(input_sz > old_capacity){  //If input range is too big, we need to reallocate
1391          size_type real_cap = 0;
1392          pointer reuse(this->m_holder.start());
1393          pointer const ret(this->m_holder.allocation_command(allocate_new|expand_fwd, input_sz, real_cap = input_sz, reuse));
1394          if(!reuse){  //New allocation, just emplace new values
1395             #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
1396             ++this->num_alloc;
1397             #endif
1398             pointer const old_p = this->m_holder.start();
1399             if(old_p){
1400                this->priv_destroy_all();
1401                this->m_holder.deallocate(old_p, old_capacity);
1402             }
1403             this->m_holder.start(ret);
1404             this->m_holder.capacity(real_cap);
1405             this->m_holder.m_size = 0;
1406             this->priv_uninitialized_construct_at_end(first, last);
1407             return;
1408          }
1409          else{
1410             #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
1411             ++this->num_expand_fwd;
1412             #endif
1413             this->m_holder.capacity(real_cap);
1414             //Forward expansion, use assignment + back deletion/construction that comes later
1415          }
1416       }
1417 
1418       boost::container::copy_assign_range_alloc_n(this->m_holder.alloc(), first, input_sz, this->priv_raw_begin(), this->size());
1419       m_holder.set_stored_size(input_sz);
1420    }
1421 
1422    //! <b>Effects</b>: Assigns the n copies of val to *this.
1423    //!
1424    //! <b>Throws</b>: If memory allocation throws or
1425    //!   T's copy/move constructor/assignment throws.
1426    //!
1427    //! <b>Complexity</b>: Linear to n.
1428    inline void assign(size_type n, const value_type& val)
1429    {  this->assign(cvalue_iterator(val, n), cvalue_iterator());   }
1430 
1431    //! <b>Effects</b>: Returns a copy of the internal allocator.
1432    //!
1433    //! <b>Throws</b>: If allocator's copy constructor throws.
1434    //!
1435    //! <b>Complexity</b>: Constant.
1436    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline allocator_type get_allocator() const BOOST_NOEXCEPT_OR_NOTHROW
1437    { return this->m_holder.alloc();  }
1438 
1439    //! <b>Effects</b>: Returns a reference to the internal allocator.
1440    //!
1441    //! <b>Throws</b>: Nothing
1442    //!
1443    //! <b>Complexity</b>: Constant.
1444    //!
1445    //! <b>Note</b>: Non-standard extension.
1446    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline 
1447       stored_allocator_type &get_stored_allocator() BOOST_NOEXCEPT_OR_NOTHROW
1448    {  return this->m_holder.alloc(); }
1449 
1450    //! <b>Effects</b>: Returns a reference to the internal allocator.
1451    //!
1452    //! <b>Throws</b>: Nothing
1453    //!
1454    //! <b>Complexity</b>: Constant.
1455    //!
1456    //! <b>Note</b>: Non-standard extension.
1457    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
1458       const stored_allocator_type &get_stored_allocator() const BOOST_NOEXCEPT_OR_NOTHROW
1459    {  return this->m_holder.alloc(); }
1460 
1461    //////////////////////////////////////////////
1462    //
1463    //                iterators
1464    //
1465    //////////////////////////////////////////////
1466 
1467    //! <b>Effects</b>: Returns an iterator to the first element contained in the vector.
1468    //!
1469    //! <b>Throws</b>: Nothing.
1470    //!
1471    //! <b>Complexity</b>: Constant.
1472    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline iterator begin() BOOST_NOEXCEPT_OR_NOTHROW
1473    { return iterator(this->m_holder.start()); }
1474 
1475    //! <b>Effects</b>: Returns a const_iterator to the first element contained in the vector.
1476    //!
1477    //! <b>Throws</b>: Nothing.
1478    //!
1479    //! <b>Complexity</b>: Constant.
1480    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline const_iterator begin() const BOOST_NOEXCEPT_OR_NOTHROW
1481    { return const_iterator(this->m_holder.start()); }
1482 
1483    //! <b>Effects</b>: Returns an iterator to the end of the vector.
1484    //!
1485    //! <b>Throws</b>: Nothing.
1486    //!
1487    //! <b>Complexity</b>: Constant.
1488    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline iterator end() BOOST_NOEXCEPT_OR_NOTHROW
1489    {
1490       iterator it (this->m_holder.start());
1491       it += difference_type(this->m_holder.m_size);
1492       return it;  //Adding zero to null pointer is allowed (non-UB)
1493    }
1494 
1495    //! <b>Effects</b>: Returns a const_iterator to the end of the vector.
1496    //!
1497    //! <b>Throws</b>: Nothing.
1498    //!
1499    //! <b>Complexity</b>: Constant.
1500    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline const_iterator end() const BOOST_NOEXCEPT_OR_NOTHROW
1501    { return this->cend(); }
1502 
1503    //! <b>Effects</b>: Returns a reverse_iterator pointing to the beginning
1504    //! of the reversed vector.
1505    //!
1506    //! <b>Throws</b>: Nothing.
1507    //!
1508    //! <b>Complexity</b>: Constant.
1509    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline reverse_iterator rbegin() BOOST_NOEXCEPT_OR_NOTHROW
1510    { return reverse_iterator(this->end());      }
1511 
1512    //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the beginning
1513    //! of the reversed vector.
1514    //!
1515    //! <b>Throws</b>: Nothing.
1516    //!
1517    //! <b>Complexity</b>: Constant.
1518    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline const_reverse_iterator rbegin() const BOOST_NOEXCEPT_OR_NOTHROW
1519    { return this->crbegin(); }
1520 
1521    //! <b>Effects</b>: Returns a reverse_iterator pointing to the end
1522    //! of the reversed vector.
1523    //!
1524    //! <b>Throws</b>: Nothing.
1525    //!
1526    //! <b>Complexity</b>: Constant.
1527    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline reverse_iterator rend() BOOST_NOEXCEPT_OR_NOTHROW
1528    { return reverse_iterator(this->begin());       }
1529 
1530    //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the end
1531    //! of the reversed vector.
1532    //!
1533    //! <b>Throws</b>: Nothing.
1534    //!
1535    //! <b>Complexity</b>: Constant.
1536    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline const_reverse_iterator rend() const BOOST_NOEXCEPT_OR_NOTHROW
1537    { return this->crend(); }
1538 
1539    //! <b>Effects</b>: Returns a const_iterator to the first element contained in the vector.
1540    //!
1541    //! <b>Throws</b>: Nothing.
1542    //!
1543    //! <b>Complexity</b>: Constant.
1544    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline const_iterator cbegin() const BOOST_NOEXCEPT_OR_NOTHROW
1545    { return const_iterator(this->m_holder.start()); }
1546 
1547    //! <b>Effects</b>: Returns a const_iterator to the end of the vector.
1548    //!
1549    //! <b>Throws</b>: Nothing.
1550    //!
1551    //! <b>Complexity</b>: Constant.
1552    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline const_iterator cend() const BOOST_NOEXCEPT_OR_NOTHROW
1553    {
1554       const_iterator it (this->m_holder.start());
1555       it += difference_type(this->m_holder.m_size);
1556       return it;  //Adding zero to null pointer is allowed (non-UB)
1557    }
1558 
1559    //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the beginning
1560    //! of the reversed vector.
1561    //!
1562    //! <b>Throws</b>: Nothing.
1563    //!
1564    //! <b>Complexity</b>: Constant.
1565    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline const_reverse_iterator crbegin() const BOOST_NOEXCEPT_OR_NOTHROW
1566    { return const_reverse_iterator(this->end());}
1567 
1568    //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the end
1569    //! of the reversed vector.
1570    //!
1571    //! <b>Throws</b>: Nothing.
1572    //!
1573    //! <b>Complexity</b>: Constant.
1574    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline const_reverse_iterator crend() const BOOST_NOEXCEPT_OR_NOTHROW
1575    { return const_reverse_iterator(this->begin()); }
1576 
1577    //////////////////////////////////////////////
1578    //
1579    //                capacity
1580    //
1581    //////////////////////////////////////////////
1582 
1583    //! <b>Effects</b>: Returns true if the vector contains no elements.
1584    //!
1585    //! <b>Throws</b>: Nothing.
1586    //!
1587    //! <b>Complexity</b>: Constant.
1588    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline bool empty() const BOOST_NOEXCEPT_OR_NOTHROW
1589    { return !this->m_holder.m_size; }
1590 
1591    //! <b>Effects</b>: Returns the number of the elements contained in the vector.
1592    //!
1593    //! <b>Throws</b>: Nothing.
1594    //!
1595    //! <b>Complexity</b>: Constant.
1596    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline size_type size() const BOOST_NOEXCEPT_OR_NOTHROW
1597    { return this->m_holder.m_size; }
1598 
1599    //! <b>Effects</b>: Returns the largest possible size of the vector.
1600    //!
1601    //! <b>Throws</b>: Nothing.
1602    //!
1603    //! <b>Complexity</b>: Constant.
1604    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline size_type max_size() const BOOST_NOEXCEPT_OR_NOTHROW
1605    { return allocator_traits_type::max_size(this->m_holder.alloc()); }
1606 
1607    //! <b>Effects</b>: Inserts or erases elements at the end such that
1608    //!   the size becomes n. New elements are value initialized.
1609    //!
1610    //! <b>Throws</b>: If memory allocation throws, or T's copy/move or value initialization throws.
1611    //!
1612    //! <b>Complexity</b>: Linear to the difference between size() and new_size.
1613    inline void resize(size_type new_size)
1614    {  this->priv_resize(new_size, value_init, alloc_version());  }
1615 
1616    //! <b>Effects</b>: Inserts or erases elements at the end such that
1617    //!   the size becomes n. New elements are default initialized.
1618    //!
1619    //! <b>Throws</b>: If memory allocation throws, or T's copy/move or default initialization throws.
1620    //!
1621    //! <b>Complexity</b>: Linear to the difference between size() and new_size.
1622    //!
1623    //! <b>Note</b>: Non-standard extension
1624    inline void resize(size_type new_size, default_init_t)
1625    {  this->priv_resize(new_size, default_init, alloc_version());  }
1626 
1627    //! <b>Effects</b>: Inserts or erases elements at the end such that
1628    //!   the size becomes n. New elements are copy constructed from x.
1629    //!
1630    //! <b>Throws</b>: If memory allocation throws, or T's copy/move constructor throws.
1631    //!
1632    //! <b>Complexity</b>: Linear to the difference between size() and new_size.
1633    inline void resize(size_type new_size, const T& x)
1634    {  this->priv_resize(new_size, x, alloc_version());  }
1635 
1636    //! <b>Effects</b>: Number of elements for which memory has been allocated.
1637    //!   capacity() is always greater than or equal to size().
1638    //!
1639    //! <b>Throws</b>: Nothing.
1640    //!
1641    //! <b>Complexity</b>: Constant.
1642    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline size_type capacity() const BOOST_NOEXCEPT_OR_NOTHROW
1643    { return this->m_holder.capacity(); }
1644 
1645    //! <b>Effects</b>: If n is less than or equal to capacity(), this call has no
1646    //!   effect. Otherwise, it is a request for allocation of additional memory.
1647    //!   If the request is successful, then capacity() is greater than or equal to
1648    //!   n; otherwise, capacity() is unchanged. In either case, size() is unchanged.
1649    //!
1650    //! <b>Throws</b>: If memory allocation allocation throws or T's copy/move constructor throws.
1651    inline void reserve(size_type new_cap)
1652    {
1653       if (this->capacity() < new_cap){
1654          this->priv_move_to_new_buffer(new_cap, alloc_version());
1655       }
1656    }
1657 
1658    //! <b>Effects</b>: Tries to deallocate the excess of memory created
1659    //!   with previous allocations. The size of the vector is unchanged
1660    //!
1661    //! <b>Throws</b>: If memory allocation throws, or T's copy/move constructor throws.
1662    //!
1663    //! <b>Complexity</b>: Linear to size().
1664    inline void shrink_to_fit()
1665    {  this->priv_shrink_to_fit(alloc_version());   }
1666 
1667    //////////////////////////////////////////////
1668    //
1669    //               element access
1670    //
1671    //////////////////////////////////////////////
1672 
1673    //! <b>Requires</b>: !empty()
1674    //!
1675    //! <b>Effects</b>: Returns a reference to the first
1676    //!   element of the container.
1677    //!
1678    //! <b>Throws</b>: Nothing.
1679    //!
1680    //! <b>Complexity</b>: Constant.
1681    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline reference front() BOOST_NOEXCEPT_OR_NOTHROW
1682    {
1683       BOOST_ASSERT(!this->empty());
1684       return *this->m_holder.start();
1685    }
1686 
1687    //! <b>Requires</b>: !empty()
1688    //!
1689    //! <b>Effects</b>: Returns a const reference to the first
1690    //!   element of the container.
1691    //!
1692    //! <b>Throws</b>: Nothing.
1693    //!
1694    //! <b>Complexity</b>: Constant.
1695    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline const_reference front() const BOOST_NOEXCEPT_OR_NOTHROW
1696    {
1697       BOOST_ASSERT(!this->empty());
1698       return *this->m_holder.start();
1699    }
1700 
1701    //! <b>Requires</b>: !empty()
1702    //!
1703    //! <b>Effects</b>: Returns a reference to the last
1704    //!   element of the container.
1705    //!
1706    //! <b>Throws</b>: Nothing.
1707    //!
1708    //! <b>Complexity</b>: Constant.
1709    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline reference back() BOOST_NOEXCEPT_OR_NOTHROW
1710    {
1711       BOOST_ASSERT(!this->empty());
1712       return this->m_holder.start()[difference_type(this->m_holder.m_size - 1u)];
1713    }
1714 
1715    //! <b>Requires</b>: !empty()
1716    //!
1717    //! <b>Effects</b>: Returns a const reference to the last
1718    //!   element of the container.
1719    //!
1720    //! <b>Throws</b>: Nothing.
1721    //!
1722    //! <b>Complexity</b>: Constant.
1723    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline const_reference back()  const BOOST_NOEXCEPT_OR_NOTHROW
1724    {
1725       BOOST_ASSERT(!this->empty());
1726       return this->m_holder.start()[this->m_holder.m_size - 1];
1727    }
1728 
1729    //! <b>Requires</b>: size() > n.
1730    //!
1731    //! <b>Effects</b>: Returns a reference to the nth element
1732    //!   from the beginning of the container.
1733    //!
1734    //! <b>Throws</b>: Nothing.
1735    //!
1736    //! <b>Complexity</b>: Constant.
1737    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline reference operator[](size_type n) BOOST_NOEXCEPT_OR_NOTHROW
1738    {
1739       BOOST_ASSERT(this->m_holder.m_size > n);
1740       return this->m_holder.start()[difference_type(n)];
1741    }
1742 
1743    //! <b>Requires</b>: size() > n.
1744    //!
1745    //! <b>Effects</b>: Returns a const reference to the nth element
1746    //!   from the beginning of the container.
1747    //!
1748    //! <b>Throws</b>: Nothing.
1749    //!
1750    //! <b>Complexity</b>: Constant.
1751    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
1752       const_reference operator[](size_type n) const BOOST_NOEXCEPT_OR_NOTHROW
1753    {
1754       BOOST_ASSERT(this->m_holder.m_size > n);
1755       return this->m_holder.start()[n];
1756    }
1757 
1758    //! <b>Requires</b>: size() >= n.
1759    //!
1760    //! <b>Effects</b>: Returns an iterator to the nth element
1761    //!   from the beginning of the container. Returns end()
1762    //!   if n == size().
1763    //!
1764    //! <b>Throws</b>: Nothing.
1765    //!
1766    //! <b>Complexity</b>: Constant.
1767    //!
1768    //! <b>Note</b>: Non-standard extension
1769    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
1770       iterator nth(size_type n) BOOST_NOEXCEPT_OR_NOTHROW
1771    {
1772       BOOST_ASSERT(this->m_holder.m_size >= n);
1773       return iterator(this->m_holder.start()+difference_type(n));
1774    }
1775 
1776    //! <b>Requires</b>: size() >= n.
1777    //!
1778    //! <b>Effects</b>: Returns a const_iterator to the nth element
1779    //!   from the beginning of the container. Returns end()
1780    //!   if n == size().
1781    //!
1782    //! <b>Throws</b>: Nothing.
1783    //!
1784    //! <b>Complexity</b>: Constant.
1785    //!
1786    //! <b>Note</b>: Non-standard extension
1787    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
1788       const_iterator nth(size_type n) const BOOST_NOEXCEPT_OR_NOTHROW
1789    {
1790       BOOST_ASSERT(this->m_holder.m_size >= n);
1791       return const_iterator(this->m_holder.start()+difference_type(n));
1792    }
1793 
1794    //! <b>Requires</b>: begin() <= p <= end().
1795    //!
1796    //! <b>Effects</b>: Returns the index of the element pointed by p
1797    //!   and size() if p == end().
1798    //!
1799    //! <b>Throws</b>: Nothing.
1800    //!
1801    //! <b>Complexity</b>: Constant.
1802    //!
1803    //! <b>Note</b>: Non-standard extension
1804    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
1805       size_type index_of(iterator p) BOOST_NOEXCEPT_OR_NOTHROW
1806    {
1807       //Range check assert done in priv_index_of
1808       return this->priv_index_of(vector_iterator_get_ptr(p));
1809    }
1810 
1811    //! <b>Requires</b>: begin() <= p <= end().
1812    //!
1813    //! <b>Effects</b>: Returns the index of the element pointed by p
1814    //!   and size() if p == end().
1815    //!
1816    //! <b>Throws</b>: Nothing.
1817    //!
1818    //! <b>Complexity</b>: Constant.
1819    //!
1820    //! <b>Note</b>: Non-standard extension
1821    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
1822       size_type index_of(const_iterator p) const BOOST_NOEXCEPT_OR_NOTHROW
1823    {
1824       //Range check assert done in priv_index_of
1825       return this->priv_index_of(vector_iterator_get_ptr(p));
1826    }
1827 
1828    //! <b>Requires</b>: size() > n.
1829    //!
1830    //! <b>Effects</b>: Returns a reference to the nth element
1831    //!   from the beginning of the container.
1832    //!
1833    //! <b>Throws</b>: range_error if n >= size()
1834    //!
1835    //! <b>Complexity</b>: Constant.
1836    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline reference at(size_type n)
1837    {
1838       this->priv_throw_if_out_of_range(n);
1839       return this->m_holder.start()[difference_type(n)];
1840    }
1841 
1842    //! <b>Requires</b>: size() > n.
1843    //!
1844    //! <b>Effects</b>: Returns a const reference to the nth element
1845    //!   from the beginning of the container.
1846    //!
1847    //! <b>Throws</b>: range_error if n >= size()
1848    //!
1849    //! <b>Complexity</b>: Constant.
1850    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline const_reference at(size_type n) const
1851    {
1852       this->priv_throw_if_out_of_range(n);
1853       return this->m_holder.start()[n];
1854    }
1855 
1856    //////////////////////////////////////////////
1857    //
1858    //                 data access
1859    //
1860    //////////////////////////////////////////////
1861 
1862    //! <b>Returns</b>: A pointer such that [data(),data() + size()) is a valid range.
1863    //!   For a non-empty vector, data() == &front().
1864    //!
1865    //! <b>Throws</b>: Nothing.
1866    //!
1867    //! <b>Complexity</b>: Constant.
1868    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline T* data() BOOST_NOEXCEPT_OR_NOTHROW
1869    { return this->priv_raw_begin(); }
1870 
1871    //! <b>Returns</b>: A pointer such that [data(),data() + size()) is a valid range.
1872    //!   For a non-empty vector, data() == &front().
1873    //!
1874    //! <b>Throws</b>: Nothing.
1875    //!
1876    //! <b>Complexity</b>: Constant.
1877    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline const T * data()  const BOOST_NOEXCEPT_OR_NOTHROW
1878    { return this->priv_raw_begin(); }
1879 
1880    //////////////////////////////////////////////
1881    //
1882    //                modifiers
1883    //
1884    //////////////////////////////////////////////
1885 
1886    #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
1887    //! <b>Effects</b>: Inserts an object of type T constructed with
1888    //!   std::forward<Args>(args)... in the end of the vector.
1889    //!
1890    //! <b>Returns</b>: A reference to the created object.
1891    //!
1892    //! <b>Throws</b>: If memory allocation throws or the in-place constructor throws or
1893    //!   T's copy/move constructor throws.
1894    //!
1895    //! <b>Complexity</b>: Amortized constant time.
1896    template<class ...Args>
1897    inline reference emplace_back(BOOST_FWD_REF(Args)...args)
1898    {
1899       T* const p = this->priv_raw_end();
1900       if (BOOST_LIKELY(this->room_enough())){
1901          //There is more memory, just construct a new object at the end
1902          allocator_traits_type::construct(this->m_holder.alloc(), p, ::boost::forward<Args>(args)...);
1903          ++this->m_holder.m_size;
1904          return *p;
1905       }
1906       else{
1907          typedef dtl::insert_emplace_proxy<allocator_type, Args...> proxy_t;
1908          return *this->priv_insert_forward_range_no_capacity
1909             (p, 1, proxy_t(::boost::forward<Args>(args)...), alloc_version());
1910       }
1911    }
1912 
1913    //! <b>Effects</b>: Inserts an object of type T constructed with
1914    //!   std::forward<Args>(args)... in the end of the vector.
1915    //!
1916    //! <b>Throws</b>: If the in-place constructor throws.
1917    //!
1918    //! <b>Complexity</b>: Constant time.
1919    //!
1920    //! <b>Note</b>: Non-standard extension.
1921    template<class ...Args>
1922    inline bool stable_emplace_back(BOOST_FWD_REF(Args)...args)
1923    {
1924       const bool is_room_enough = this->room_enough() || (alloc_version::value == 2 && this->m_holder.try_expand_fwd(1u));
1925       if (BOOST_LIKELY(is_room_enough)){
1926          //There is more memory, just construct a new object at the end
1927          allocator_traits_type::construct(this->m_holder.alloc(), this->priv_raw_end(), ::boost::forward<Args>(args)...);
1928          ++this->m_holder.m_size;
1929       }
1930       return is_room_enough;
1931    }
1932 
1933    //! <b>Requires</b>: position must be a valid iterator of *this.
1934    //!
1935    //! <b>Effects</b>: Inserts an object of type T constructed with
1936    //!   std::forward<Args>(args)... before position
1937    //!
1938    //! <b>Throws</b>: If memory allocation throws or the in-place constructor throws or
1939    //!   T's copy/move constructor/assignment throws.
1940    //!
1941    //! <b>Complexity</b>: If position is end(), amortized constant time
1942    //!   Linear time otherwise.
1943    template<class ...Args>
1944    inline iterator emplace(const_iterator position, BOOST_FWD_REF(Args) ...args)
1945    {
1946       BOOST_ASSERT(this->priv_in_range_or_end(position));
1947       //Just call more general insert(pos, size, value) and return iterator
1948       typedef dtl::insert_emplace_proxy<allocator_type, Args...> proxy_t;
1949       return this->priv_insert_forward_range( vector_iterator_get_ptr(position), 1
1950                                             , proxy_t(::boost::forward<Args>(args)...));
1951    }
1952 
1953    #else // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
1954 
1955    #define BOOST_CONTAINER_VECTOR_EMPLACE_CODE(N) \
1956    BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
1957    inline reference emplace_back(BOOST_MOVE_UREF##N)\
1958    {\
1959       T* const p = this->priv_raw_end();\
1960       if (BOOST_LIKELY(this->room_enough())){\
1961          allocator_traits_type::construct (this->m_holder.alloc()\
1962             , this->priv_raw_end() BOOST_MOVE_I##N BOOST_MOVE_FWD##N);\
1963          ++this->m_holder.m_size;\
1964          return *p;\
1965       }\
1966       else{\
1967          typedef dtl::insert_emplace_proxy_arg##N<allocator_type BOOST_MOVE_I##N BOOST_MOVE_TARG##N> proxy_t;\
1968          return *this->priv_insert_forward_range_no_capacity\
1969             ( p, 1, proxy_t(BOOST_MOVE_FWD##N), alloc_version());\
1970       }\
1971    }\
1972    \
1973    BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
1974    inline bool stable_emplace_back(BOOST_MOVE_UREF##N)\
1975    {\
1976       const bool is_room_enough = this->room_enough() || (alloc_version::value == 2 && this->m_holder.try_expand_fwd(1u));\
1977       if (BOOST_LIKELY(is_room_enough)){\
1978          allocator_traits_type::construct (this->m_holder.alloc()\
1979             , this->priv_raw_end() BOOST_MOVE_I##N BOOST_MOVE_FWD##N);\
1980          ++this->m_holder.m_size;\
1981       }\
1982       return is_room_enough;\
1983    }\
1984    \
1985    BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
1986    inline iterator emplace(const_iterator pos BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\
1987    {\
1988       BOOST_ASSERT(this->priv_in_range_or_end(pos));\
1989       typedef dtl::insert_emplace_proxy_arg##N<allocator_type BOOST_MOVE_I##N BOOST_MOVE_TARG##N> proxy_t;\
1990       return this->priv_insert_forward_range(vector_iterator_get_ptr(pos), 1, proxy_t(BOOST_MOVE_FWD##N));\
1991    }\
1992    //
1993    BOOST_MOVE_ITERATE_0TO9(BOOST_CONTAINER_VECTOR_EMPLACE_CODE)
1994    #undef BOOST_CONTAINER_VECTOR_EMPLACE_CODE
1995 
1996    #endif
1997 
1998    #if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
1999    //! <b>Effects</b>: Inserts a copy of x at the end of the vector.
2000    //!
2001    //! <b>Throws</b>: If memory allocation throws or
2002    //!   T's copy/move constructor throws.
2003    //!
2004    //! <b>Complexity</b>: Amortized constant time.
2005    void push_back(const T &x);
2006 
2007    //! <b>Effects</b>: Constructs a new element in the end of the vector
2008    //!   and moves the resources of x to this new element.
2009    //!
2010    //! <b>Throws</b>: If memory allocation throws or
2011    //!   T's copy/move constructor throws.
2012    //!
2013    //! <b>Complexity</b>: Amortized constant time.
2014    void push_back(T &&x);
2015    #else
2016    BOOST_MOVE_CONVERSION_AWARE_CATCH(push_back, T, void, priv_push_back)
2017    #endif
2018 
2019    #if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
2020    //! <b>Requires</b>: position must be a valid iterator of *this.
2021    //!
2022    //! <b>Effects</b>: Insert a copy of x before position.
2023    //!
2024    //! <b>Throws</b>: If memory allocation throws or T's copy/move constructor/assignment throws.
2025    //!
2026    //! <b>Complexity</b>: If position is end(), amortized constant time
2027    //!   Linear time otherwise.
2028    iterator insert(const_iterator position, const T &x);
2029 
2030    //! <b>Requires</b>: position must be a valid iterator of *this.
2031    //!
2032    //! <b>Effects</b>: Insert a new element before position with x's resources.
2033    //!
2034    //! <b>Throws</b>: If memory allocation throws.
2035    //!
2036    //! <b>Complexity</b>: If position is end(), amortized constant time
2037    //!   Linear time otherwise.
2038    iterator insert(const_iterator position, T &&x);
2039    #else
2040    BOOST_MOVE_CONVERSION_AWARE_CATCH_1ARG(insert, T, iterator, priv_insert, const_iterator, const_iterator)
2041    #endif
2042 
2043    //! <b>Requires</b>: p must be a valid iterator of *this.
2044    //!
2045    //! <b>Effects</b>: Insert n copies of x before pos.
2046    //!
2047    //! <b>Returns</b>: an iterator to the first inserted element or p if n is 0.
2048    //!
2049    //! <b>Throws</b>: If memory allocation throws or T's copy/move constructor throws.
2050    //!
2051    //! <b>Complexity</b>: Linear to n.
2052    inline iterator insert(const_iterator p, size_type n, const T& x)
2053    {
2054       BOOST_ASSERT(this->priv_in_range_or_end(p));
2055       dtl::insert_n_copies_proxy<allocator_type> proxy(x);
2056       return this->priv_insert_forward_range(vector_iterator_get_ptr(p), n, proxy);
2057    }
2058 
2059    //! <b>Requires</b>: p must be a valid iterator of *this.
2060    //!
2061    //! <b>Effects</b>: Insert a copy of the [first, last) range before pos.
2062    //!
2063    //! <b>Returns</b>: an iterator to the first inserted element or pos if first == last.
2064    //!
2065    //! <b>Throws</b>: If memory allocation throws, T's constructor from a
2066    //!   dereferenced InpIt throws or T's copy/move constructor/assignment throws.
2067    //!
2068    //! <b>Complexity</b>: Linear to boost::container::iterator_distance [first, last).
2069    template <class InIt>
2070    iterator insert(const_iterator pos, InIt first, InIt last
2071       #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
2072       , typename dtl::disable_if_or
2073          < void
2074          , dtl::is_convertible<InIt, size_type>
2075          , dtl::is_not_input_iterator<InIt>
2076          >::type * = 0
2077       #endif
2078       )
2079    {
2080       BOOST_ASSERT(this->priv_in_range_or_end(pos));
2081       const size_type n_pos = size_type(pos - this->cbegin());
2082       iterator it(vector_iterator_get_ptr(pos));
2083       for(;first != last; ++first){
2084          it = this->emplace(it, *first);
2085          ++it;
2086       }
2087       return iterator(this->m_holder.start() + difference_type(n_pos));
2088    }
2089 
2090    #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
2091    template <class FwdIt>
2092    inline iterator insert(const_iterator pos, FwdIt first, FwdIt last
2093       , typename dtl::disable_if_or
2094          < void
2095          , dtl::is_convertible<FwdIt, size_type>
2096          , dtl::is_input_iterator<FwdIt>
2097          >::type * = 0
2098       )
2099    {
2100       typedef typename iter_size<FwdIt>::type it_size_type;
2101       BOOST_ASSERT(this->priv_in_range_or_end(pos));
2102       const it_size_type sz = boost::container::iterator_udistance(first, last);
2103       if (BOOST_UNLIKELY(sz > size_type(-1))){
2104          boost::container::throw_length_error("vector::insert, FwdIt's max length reached");
2105       }
2106 
2107       dtl::insert_range_proxy<allocator_type, FwdIt> proxy(first);
2108       return this->priv_insert_forward_range(vector_iterator_get_ptr(pos), static_cast<size_type>(sz), proxy);
2109    }
2110    #endif
2111 
2112    //! <b>Requires</b>: p must be a valid iterator of *this. num, must
2113    //!   be equal to boost::container::iterator_distance(first, last)
2114    //!
2115    //! <b>Effects</b>: Insert a copy of the [first, last) range before pos.
2116    //!
2117    //! <b>Returns</b>: an iterator to the first inserted element or pos if first == last.
2118    //!
2119    //! <b>Throws</b>: If memory allocation throws, T's constructor from a
2120    //!   dereferenced InpIt throws or T's copy/move constructor/assignment throws.
2121    //!
2122    //! <b>Complexity</b>: Linear to boost::container::iterator_distance [first, last).
2123    //!
2124    //! <b>Note</b>: This function avoids a linear operation to calculate boost::container::iterator_distance[first, last)
2125    //!   for forward and bidirectional iterators, and a one by one insertion for input iterators. This is a
2126    //!   a non-standard extension.
2127    #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
2128    template <class InIt>
2129    inline iterator insert(const_iterator pos, size_type num, InIt first, InIt last)
2130    {
2131       BOOST_ASSERT(this->priv_in_range_or_end(pos));
2132       BOOST_ASSERT(dtl::is_input_iterator<InIt>::value ||
2133                    num == boost::container::iterator_udistance(first, last));
2134       (void)last;
2135       dtl::insert_range_proxy<allocator_type, InIt> proxy(first);
2136       return this->priv_insert_forward_range(vector_iterator_get_ptr(pos), num, proxy);
2137    }
2138    #endif
2139 
2140    #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
2141    //! <b>Requires</b>: position must be a valid iterator of *this.
2142    //!
2143    //! <b>Effects</b>: Insert a copy of the [il.begin(), il.end()) range before position.
2144    //!
2145    //! <b>Returns</b>: an iterator to the first inserted element or position if first == last.
2146    //!
2147    //! <b>Complexity</b>: Linear to the range [il.begin(), il.end()).
2148    inline iterator insert(const_iterator position, std::initializer_list<value_type> il)
2149    {
2150       //Assertion done in insert()
2151       return this->insert(position, il.begin(), il.end());
2152    }
2153    #endif
2154 
2155    //! <b>Effects</b>: Removes the last element from the container.
2156    //!
2157    //! <b>Throws</b>: Nothing.
2158    //!
2159    //! <b>Complexity</b>: Constant time.
2160    inline void pop_back() BOOST_NOEXCEPT_OR_NOTHROW
2161    {
2162       BOOST_ASSERT(!this->empty());
2163       //Destroy last element
2164       allocator_traits_type::destroy(this->get_stored_allocator(), this->priv_raw_end() - 1);
2165       --this->m_holder.m_size;
2166    }
2167 
2168    //! <b>Effects</b>: Erases the element at position pos.
2169    //!
2170    //! <b>Throws</b>: Nothing.
2171    //!
2172    //! <b>Complexity</b>: Linear to the elements between pos and the
2173    //!   last element. Constant if pos is the last element.
2174    iterator erase(const_iterator position)
2175    {
2176       BOOST_ASSERT(this->priv_in_range(position));
2177       const pointer p = vector_iterator_get_ptr(position);
2178       T *const pos_ptr = boost::movelib::to_raw_pointer(p);
2179       T *const end_ptr = this->priv_raw_end();
2180 
2181       //Move elements forward and destroy last
2182       (void)::boost::container::move(pos_ptr + 1, end_ptr, pos_ptr);
2183 
2184       T *const last_ptr = end_ptr-1;
2185       if(!value_traits::trivial_dctr_after_move || pos_ptr == last_ptr){
2186          allocator_traits_type::destroy(this->get_stored_allocator(), last_ptr);
2187       }
2188       --this->m_holder.m_size;
2189       return iterator(p);
2190    }
2191 
2192    //! <b>Effects</b>: Erases the elements pointed by [first, last).
2193    //!
2194    //! <b>Throws</b>: Nothing.
2195    //!
2196    //! <b>Complexity</b>: Linear to the distance between first and last
2197    //!   plus linear to the elements between pos and the last element.
2198    iterator erase(const_iterator first, const_iterator last)
2199    {
2200       BOOST_ASSERT(this->priv_in_range_or_end(first));
2201       BOOST_ASSERT(this->priv_in_range_or_end(last));
2202       BOOST_ASSERT(first <= last);
2203       if(first != last){
2204          T* const old_end_ptr = this->priv_raw_end();
2205          T* const first_ptr = boost::movelib::to_raw_pointer(vector_iterator_get_ptr(first));
2206          T* const last_ptr  = boost::movelib::to_raw_pointer(vector_iterator_get_ptr(last));
2207          T* const new_last_ptr = boost::movelib::to_raw_pointer(boost::container::move(last_ptr, old_end_ptr, first_ptr));
2208          const size_type n = static_cast<size_type>(old_end_ptr - new_last_ptr);
2209          if(!value_traits::trivial_dctr_after_move || old_end_ptr == last_ptr){
2210             boost::container::destroy_alloc_n(this->get_stored_allocator(), new_last_ptr, n);
2211          }
2212          this->m_holder.dec_stored_size(n);
2213       }
2214       return iterator(vector_iterator_get_ptr(first));
2215    }
2216 
2217    //! <b>Effects</b>: Swaps the contents of *this and x.
2218    //!
2219    //! <b>Throws</b>: Nothing.
2220    //!
2221    //! <b>Complexity</b>: Constant.
2222    inline void swap(vector& x)
2223       BOOST_NOEXCEPT_IF( ((allocator_traits_type::propagate_on_container_swap::value
2224                                     || allocator_traits_type::is_always_equal::value) &&
2225                                     !dtl::is_version<allocator_type, 0>::value))
2226    {
2227       this->priv_swap(x, dtl::bool_<dtl::is_version<allocator_type, 0>::value>());
2228    }
2229 
2230    #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
2231 
2232    //! <b>Effects</b>: Swaps the contents of *this and x.
2233    //!
2234    //! <b>Throws</b>: Nothing.
2235    //!
2236    //! <b>Complexity</b>: Linear
2237    //!
2238    //! <b>Note</b>: Non-standard extension to support static_vector
2239    template<class OtherA>
2240    inline void swap(vector<T, OtherA, Options> & x
2241             , typename dtl::enable_if_and
2242                      < void
2243                      , dtl::is_version<typename real_allocator<T, OtherA>::type, 0>
2244                      , dtl::is_different<typename real_allocator<T, OtherA>::type, allocator_type>
2245                      >::type * = 0
2246             )
2247    {  this->m_holder.deep_swap(x.m_holder); }
2248 
2249    #endif   //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
2250 
2251    //! <b>Effects</b>: Erases all the elements of the vector. Leaves the capacity() of the vector unchanged.
2252    //!
2253    //! <b>Throws</b>: Nothing.
2254    //!
2255    //! <b>Complexity</b>: Linear to the number of elements in the container.
2256    inline void clear() BOOST_NOEXCEPT_OR_NOTHROW
2257    {  this->priv_destroy_all();  }
2258 
2259    //! <b>Effects</b>: Returns true if x and y are equal
2260    //!
2261    //! <b>Complexity</b>: Linear to the number of elements in the container.
2262    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline friend bool operator==(const vector& x, const vector& y)
2263    {  return x.size() == y.size() && ::boost::container::algo_equal(x.begin(), x.end(), y.begin());  }
2264 
2265    //! <b>Effects</b>: Returns true if x and y are unequal
2266    //!
2267    //! <b>Complexity</b>: Linear to the number of elements in the container.
2268    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline friend bool operator!=(const vector& x, const vector& y)
2269    {  return !(x == y); }
2270 
2271    //! <b>Effects</b>: Returns true if x is less than y
2272    //!
2273    //! <b>Complexity</b>: Linear to the number of elements in the container.
2274    BOOST_CONTAINER_ATTRIBUTE_NODISCARD friend bool operator<(const vector& x, const vector& y)
2275    {  return boost::container::algo_lexicographical_compare(x.begin(), x.end(), y.begin(), y.end());  }
2276 
2277    //! <b>Effects</b>: Returns true if x is greater than y
2278    //!
2279    //! <b>Complexity</b>: Linear to the number of elements in the container.
2280    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline friend bool operator>(const vector& x, const vector& y)
2281    {  return y < x;  }
2282 
2283    //! <b>Effects</b>: Returns true if x is equal or less than y
2284    //!
2285    //! <b>Complexity</b>: Linear to the number of elements in the container.
2286    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline friend bool operator<=(const vector& x, const vector& y)
2287    {  return !(y < x);  }
2288 
2289    //! <b>Effects</b>: Returns true if x is equal or greater than y
2290    //!
2291    //! <b>Complexity</b>: Linear to the number of elements in the container.
2292    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline friend bool operator>=(const vector& x, const vector& y)
2293    {  return !(x < y);  }
2294 
2295    //! <b>Effects</b>: x.swap(y)
2296    //!
2297    //! <b>Complexity</b>: Constant.
2298    inline friend void swap(vector& x, vector& y)
2299        BOOST_NOEXCEPT_IF(BOOST_NOEXCEPT(x.swap(y)))
2300    {  x.swap(y);  }
2301 
2302    #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
2303    //! <b>Effects</b>: If n is less than or equal to capacity(), this call has no
2304    //!   effect. Otherwise, it is a request for allocation of additional memory
2305    //!   (memory expansion) that will not invalidate iterators.
2306    //!   If the request is successful, then capacity() is greater than or equal to
2307    //!   n; otherwise, capacity() is unchanged. In either case, size() is unchanged.
2308    //!
2309    //! <b>Throws</b>: If memory allocation allocation throws or T's copy/move constructor throws.
2310    //!
2311    //! <b>Note</b>: Non-standard extension.
2312    bool stable_reserve(size_type new_cap)
2313    {
2314       const size_type cp = this->capacity();
2315       return cp >= new_cap || (alloc_version::value == 2 && this->m_holder.try_expand_fwd(size_type(new_cap - cp)));
2316    }
2317 
2318    //Absolutely experimental. This function might change, disappear or simply crash!
2319    template<class BiDirPosConstIt, class BiDirValueIt>
2320    inline void insert_ordered_at(const size_type element_count, BiDirPosConstIt last_position_it, BiDirValueIt last_value_it)
2321    {
2322       typedef vector_insert_ordered_cursor<BiDirPosConstIt, BiDirValueIt> inserter_t;
2323       return this->priv_insert_ordered_at(element_count, inserter_t(last_position_it, last_value_it));
2324    }
2325 
2326    template<class InputIt>
2327    inline void merge(InputIt first, InputIt last)
2328    {  this->merge(first, last, value_less_t());  }
2329 
2330    template<class InputIt, class Compare>
2331    inline void merge(InputIt first, InputIt last, Compare comp)
2332    {
2333       size_type const s = this->size();
2334       size_type const c = this->capacity();
2335       size_type n = 0;
2336       size_type const free_cap = c - s;
2337       //If not input iterator and new elements don't fit in the remaining capacity, merge in new buffer
2338       if(!dtl::is_input_iterator<InputIt>::value &&
2339          free_cap < (n = boost::container::iterator_udistance(first, last))){
2340          this->priv_merge_in_new_buffer(first, n, comp, alloc_version());
2341       }
2342       else{
2343          this->insert(this->cend(), first, last);
2344          T *const raw_beg = this->priv_raw_begin();
2345          T *const raw_end = this->priv_raw_end();
2346          T *const raw_pos = raw_beg + s;
2347          boost::movelib::adaptive_merge(raw_beg, raw_pos, raw_end, comp, raw_end, free_cap - n);
2348       }
2349    }
2350 
2351    template<class InputIt>
2352    inline void merge_unique(InputIt first, InputIt last)
2353    {  this->merge_unique(first, last, value_less_t());  }
2354 
2355    template<class InputIt, class Compare>
2356    inline void merge_unique(InputIt first, InputIt last, Compare comp)
2357    {
2358       size_type const old_size = this->size();
2359       this->priv_set_difference_back(first, last, comp);
2360       T *const raw_beg = this->priv_raw_begin();
2361       T *const raw_end = this->priv_raw_end();
2362       T *raw_pos = raw_beg + old_size;
2363       boost::movelib::adaptive_merge(raw_beg, raw_pos, raw_end, comp, raw_end, this->capacity() - this->size());
2364    }
2365 
2366    private:
2367    template<class PositionValue>
2368    void priv_insert_ordered_at(const size_type element_count, PositionValue position_value)
2369    {
2370       const size_type old_size_pos = this->size();
2371       this->reserve(old_size_pos + element_count);
2372       T* const begin_ptr = this->priv_raw_begin();
2373       size_type insertions_left = element_count;
2374       size_type prev_pos = old_size_pos;
2375       size_type old_hole_size = element_count;
2376 
2377       //Exception rollback. If any copy throws before the hole is filled, values
2378       //already inserted/copied at the end of the buffer will be destroyed.
2379       typename value_traits::ArrayDestructor past_hole_values_destroyer
2380          (begin_ptr + old_size_pos + element_count, this->m_holder.alloc(), size_type(0u));
2381       //Loop for each insertion backwards, first moving the elements after the insertion point,
2382       //then inserting the element.
2383       while(insertions_left){
2384          --position_value;
2385          size_type const pos = position_value.get_pos();
2386          BOOST_ASSERT(pos != size_type(-1) && pos <= old_size_pos && pos <= prev_pos);
2387          //If needed shift the range after the insertion point and the previous insertion point.
2388          //Function will take care if the shift crosses the size() boundary, using copy/move
2389          //or uninitialized copy/move if necessary.
2390          size_type new_hole_size = (pos != prev_pos)
2391             ? priv_insert_ordered_at_shift_range(pos, prev_pos, this->size(), insertions_left)
2392             : old_hole_size
2393             ;
2394          if(new_hole_size){
2395             //The hole was reduced by priv_insert_ordered_at_shift_range so expand exception rollback range backwards
2396             past_hole_values_destroyer.increment_size_backwards(prev_pos - pos);
2397             //Insert the new value in the hole
2398             allocator_traits_type::construct(this->m_holder.alloc(), begin_ptr + pos + insertions_left - 1, position_value.get_val());
2399             if(--new_hole_size){
2400                //The hole was reduced by the new insertion by one
2401                past_hole_values_destroyer.increment_size_backwards(size_type(1u));
2402             }
2403             else{
2404                //Hole was just filled, disable exception rollback and change vector size
2405                past_hole_values_destroyer.release();
2406                this->m_holder.inc_stored_size(element_count);
2407             }
2408          }
2409          else{
2410             if(old_hole_size){
2411                //Hole was just filled by priv_insert_ordered_at_shift_range, disable exception rollback and change vector size
2412                past_hole_values_destroyer.release();
2413                this->m_holder.inc_stored_size(element_count);
2414             }
2415             //Insert the new value in the already constructed range
2416             begin_ptr[pos + insertions_left - 1] = position_value.get_val();
2417          }
2418          --insertions_left;
2419          old_hole_size = new_hole_size;
2420          prev_pos = pos;
2421       }
2422    }
2423 
2424    template<class InputIt, class Compare>
2425    void priv_set_difference_back(InputIt first1, InputIt last1, Compare comp)
2426    {
2427       T * old_first2 = this->priv_raw_begin();
2428       T * first2 = old_first2;
2429       T * last2  = this->priv_raw_end();
2430 
2431       while (first1 != last1) {
2432          if (first2 == last2){
2433             this->insert(this->cend(), first1, last1);
2434             return;
2435          }
2436 
2437          if (comp(*first1, *first2)) {
2438             this->emplace_back(*first1);
2439             T * const raw_begin = this->priv_raw_begin();
2440             if(old_first2 != raw_begin)
2441             {
2442                //Reallocation happened, update range
2443                first2 = raw_begin + (first2 - old_first2);
2444                last2  = raw_begin + (last2 - old_first2);
2445                old_first2 = raw_begin;
2446             }
2447             ++first1;
2448          }
2449          else {
2450             if (!comp(*first2, *first1)) {
2451                ++first1;
2452             }
2453             ++first2;
2454          }
2455       }
2456    }
2457 
2458    template<class FwdIt, class Compare>
2459    inline void priv_merge_in_new_buffer(FwdIt, size_type, Compare, version_0)
2460    {
2461       alloc_holder_t::on_capacity_overflow();
2462    }
2463 
2464    template<class FwdIt, class Compare, class Version>
2465    void priv_merge_in_new_buffer(FwdIt first, size_type n, Compare comp, Version)
2466    {
2467       size_type const new_size = this->size() + n;
2468       size_type new_cap = new_size;
2469       pointer p = pointer();
2470       pointer const new_storage = this->m_holder.allocation_command(allocate_new, new_size, new_cap, p);
2471 
2472       BOOST_ASSERT((new_cap >= this->size() ) && (new_cap - this->size()) >= n);
2473       allocator_type &a = this->m_holder.alloc();
2474       typename value_traits::ArrayDeallocator new_buffer_deallocator(new_storage, a, new_cap);
2475       typename value_traits::ArrayDestructor  new_values_destroyer(new_storage, a, 0u);
2476       T* pbeg  = this->priv_raw_begin();
2477       size_type const old_size = this->size();
2478       T* const pend = pbeg + old_size;
2479       T* d_first = boost::movelib::to_raw_pointer(new_storage);
2480       size_type added = n;
2481       //Merge in new buffer loop
2482       while(1){
2483          if(!n) {
2484             ::boost::container::uninitialized_move_alloc(this->m_holder.alloc(), pbeg, pend, d_first);
2485             break;
2486          } 
2487          else if(pbeg == pend) {
2488             ::boost::container::uninitialized_move_alloc_n(this->m_holder.alloc(), first, n, d_first);
2489             break;
2490          }
2491          //maintain stability moving external values only if they are strictly less
2492          else if(comp(*first, *pbeg)) {
2493             allocator_traits_type::construct( this->m_holder.alloc(), d_first, *first );
2494             new_values_destroyer.increment_size(1u);
2495             ++first;
2496             --n;
2497             ++d_first;
2498          }
2499          else{
2500             allocator_traits_type::construct( this->m_holder.alloc(), d_first, boost::move(*pbeg) );
2501             new_values_destroyer.increment_size(1u);
2502             ++pbeg;
2503             ++d_first;
2504          }
2505       }
2506 
2507       //Nothrow operations
2508       pointer const old_p     = this->m_holder.start();
2509       size_type const old_cap = this->m_holder.capacity();
2510       boost::container::destroy_alloc_n(a, boost::movelib::to_raw_pointer(old_p), old_size);
2511       if (old_cap > 0) {
2512          this->m_holder.deallocate(old_p, old_cap);
2513       }
2514       m_holder.set_stored_size(old_size + added);
2515       this->m_holder.start(new_storage);
2516       this->m_holder.capacity(new_cap);
2517       new_buffer_deallocator.release();
2518       new_values_destroyer.release();
2519    }
2520 
2521    inline bool room_enough() const
2522    {  return this->m_holder.m_size != this->m_holder.capacity();   }
2523 
2524    inline pointer back_ptr() const
2525    {  return this->m_holder.start() + difference_type(this->m_holder.m_size);  }
2526 
2527    inline size_type priv_index_of(pointer p) const
2528    {
2529       BOOST_ASSERT(this->m_holder.start() <= p);
2530       BOOST_ASSERT(p <= (this->m_holder.start()+difference_type(this->size())));
2531       return static_cast<size_type>(p - this->m_holder.start());
2532    }
2533 
2534    template<class OtherA>
2535    void priv_move_assign(BOOST_RV_REF_BEG vector<T, OtherA, Options> BOOST_RV_REF_END x
2536       , typename dtl::enable_if_c
2537          < dtl::is_version<typename real_allocator<T, OtherA>::type, 0>::value >::type * = 0)
2538    {
2539       if(!dtl::is_same<typename real_allocator<T, OtherA>::type, allocator_type>::value &&
2540           this->capacity() < x.size()){
2541          alloc_holder_t::on_capacity_overflow();
2542       }
2543       T* const this_start  = this->priv_raw_begin();
2544       T* const other_start = x.priv_raw_begin();
2545       const size_type this_sz  = m_holder.m_size;
2546       const size_type other_sz = static_cast<size_type>(x.m_holder.m_size);
2547       boost::container::move_assign_range_alloc_n(this->m_holder.alloc(), other_start, other_sz, this_start, this_sz);
2548       m_holder.set_stored_size(other_sz);
2549       //Not emptying the source container seems to be confusing for users as drop-in
2550       //replacement for non-static vectors, so clear it.
2551       x.clear();
2552    }
2553 
2554    template<class OtherA>
2555    void priv_move_assign_steal_or_assign(BOOST_RV_REF_BEG vector<T, OtherA, Options> BOOST_RV_REF_END x, dtl::true_type /*data_can_be_always_stolen*/)
2556    {
2557       this->clear();
2558       if (BOOST_LIKELY(!!this->m_holder.m_start))
2559          this->m_holder.deallocate(this->m_holder.m_start, this->m_holder.m_capacity);
2560       this->m_holder.steal_resources(x.m_holder);
2561    }
2562 
2563    template<class OtherA>
2564    void priv_move_assign_steal_or_assign(BOOST_RV_REF_BEG vector<T, OtherA, Options> BOOST_RV_REF_END x, dtl::false_type /*data_can_be_always_stolen*/)
2565    {
2566       const bool propagate_alloc = allocator_traits_type::propagate_on_container_move_assignment::value;
2567       allocator_type& this_alloc = this->m_holder.alloc();
2568       allocator_type& x_alloc = x.m_holder.alloc();
2569 
2570       //In this allocator move constructor the allocator might will be propagated, but to support small_vector-like
2571       //types, we need to check the currently owned buffers to know if they are propagable.
2572       const bool is_buffer_propagable_from_x = is_propagable_from<propagate_alloc>(x_alloc, x.m_holder.start(), this_alloc);
2573 
2574       if (is_buffer_propagable_from_x) {
2575          this->priv_move_assign_steal_or_assign(boost::move(x), dtl::true_type());
2576       }
2577       //Else do a one by one move. Also, clear the source as users find confusing
2578       //elements are still alive in the source container.
2579       else {
2580          this->assign( boost::make_move_iterator(boost::movelib::iterator_to_raw_pointer(x.begin()))
2581                      , boost::make_move_iterator(boost::movelib::iterator_to_raw_pointer(x.end()))   );
2582          x.clear();
2583       }
2584    }
2585 
2586    template<class OtherA>
2587    void priv_move_assign(BOOST_RV_REF_BEG vector<T, OtherA, Options> BOOST_RV_REF_END x
2588       , typename dtl::disable_if_or
2589          < void
2590          , dtl::is_version<typename real_allocator<T, OtherA>::type, 0>
2591          , dtl::is_different<typename real_allocator<T, OtherA>::type, allocator_type>
2592          >::type * = 0)
2593    {
2594       //for move assignment, no aliasing (&x != this) is assumed.
2595       //x.size() == 0 is allowed for buggy std libraries.
2596       BOOST_ASSERT(this != &x || x.size() == 0);
2597       const bool alloc_is_always_equal = allocator_traits_type::is_always_equal::value;
2598       const bool propagate_alloc = allocator_traits_type::propagate_on_container_move_assignment::value;
2599       const bool partially_propagable_alloc = allocator_traits_type::is_partially_propagable::value;
2600       const bool data_can_be_always_be_stolen = alloc_is_always_equal || (propagate_alloc && !partially_propagable_alloc);
2601 
2602       this->priv_move_assign_steal_or_assign(boost::move(x), dtl::bool_<data_can_be_always_be_stolen>());
2603 
2604       //Move allocator if needed
2605       allocator_type& this_alloc = this->m_holder.alloc();
2606       allocator_type& x_alloc    = x.m_holder.alloc();
2607       dtl::move_alloc(this_alloc, x_alloc, dtl::bool_<propagate_alloc>());
2608    }
2609 
2610    template<class OtherA>
2611    void priv_copy_assign(const vector<T, OtherA, Options> &x
2612       , typename dtl::enable_if_c
2613          < dtl::is_version<typename real_allocator<T, OtherA>::type, 0>::value >::type * = 0)
2614    {
2615       if(!dtl::is_same<typename real_allocator<T, OtherA>::type, allocator_type>::value &&
2616          this->capacity() < x.size()){
2617          alloc_holder_t::on_capacity_overflow();
2618       }
2619       T* const this_start  = this->priv_raw_begin();
2620       T* const other_start = x.priv_raw_begin();
2621       const size_type this_sz  = m_holder.m_size;
2622       const size_type other_sz = static_cast<size_type>(x.m_holder.m_size);
2623       boost::container::copy_assign_range_alloc_n(this->m_holder.alloc(), other_start, other_sz, this_start, this_sz);
2624       m_holder.set_stored_size(other_sz);
2625    }
2626 
2627    template<class OtherA>
2628    typename dtl::disable_if_or
2629       < void
2630       , dtl::is_version<typename real_allocator<T, OtherA>::type, 0>
2631       , dtl::is_different<typename real_allocator<T, OtherA>::type, allocator_type>
2632       >::type
2633       priv_copy_assign(const vector<T, OtherA, Options> &x)
2634    {
2635       allocator_type &this_alloc     = this->m_holder.alloc();
2636       const allocator_type &x_alloc  = x.m_holder.alloc();
2637       dtl::bool_<allocator_traits_type::
2638          propagate_on_container_copy_assignment::value> flag;
2639       if(flag && this_alloc != x_alloc){
2640          this->clear();
2641          this->shrink_to_fit();
2642       }
2643       dtl::assign_alloc(this_alloc, x_alloc, flag);
2644       this->assign( x.priv_raw_begin(), x.priv_raw_end() );
2645    }
2646 
2647    template<class Vector>  //Template it to avoid it in explicit instantiations
2648    inline void priv_swap(Vector &x, dtl::true_type)   //version_0
2649    {  this->m_holder.deep_swap(x.m_holder);  }
2650 
2651    template<class Vector>  //Template it to avoid it in explicit instantiations
2652    void priv_swap(Vector &x, dtl::false_type)  //version_N
2653    {
2654       BOOST_ASSERT(allocator_traits_type::propagate_on_container_swap::value ||
2655                    allocator_traits_type::is_always_equal::value ||
2656                    this->get_stored_allocator() == x.get_stored_allocator());
2657 
2658       if (BOOST_UNLIKELY(&x == this)) {
2659          return;
2660       }
2661 
2662       //Just swap internals
2663       this->m_holder.swap_resources(x.m_holder);
2664       //And now swap the allocator
2665       dtl::bool_<allocator_traits_type::propagate_on_container_swap::value> flag;
2666       dtl::swap_alloc(this->m_holder.alloc(), x.m_holder.alloc(), flag);
2667    }
2668 
2669    protected:
2670    template<class Vector>  //Template it to avoid it in explicit instantiations
2671    void prot_swap_small(Vector &x, std::size_t internal_capacity)  //version_N
2672    {
2673       if (BOOST_UNLIKELY(&x == this)){
2674          return;
2675       }
2676 
2677       const bool propagate_alloc = allocator_traits_type::propagate_on_container_swap::value;
2678       if(are_swap_propagable<propagate_alloc>
2679          ( this->get_stored_allocator(), this->m_holder.start(), x.get_stored_allocator(), x.m_holder.start())){
2680          this->priv_swap(x, dtl::false_());
2681          return;
2682       }
2683 
2684       allocator_type &th_al = this->get_stored_allocator();
2685       allocator_type &ot_al = x.get_stored_allocator();
2686 
2687       const bool is_this_data_propagable = is_propagable_from<propagate_alloc>(th_al, this->data(), ot_al);
2688       const bool is_that_data_propagable = is_propagable_from<propagate_alloc>(ot_al, x.data(), th_al);
2689 
2690       if(internal_capacity && (is_this_data_propagable || is_that_data_propagable)) {
2691          //steal memory from src to dst, but move elements from dst to src
2692          vector& extmem = is_this_data_propagable ? *this : x;
2693          vector& intmem = is_this_data_propagable ? x : *this;
2694 
2695          //Reset extmem to the internal storage and backup data
2696          pointer const orig_extdata = extmem.data();
2697          const size_type orig_extmem_size = extmem.size();
2698          const size_type orig_extmem_cap = extmem.capacity();
2699 
2700          //New safe state for extmem -> empty, internal storage
2701          extmem.m_holder.m_start = extmem.get_stored_allocator().internal_storage();
2702          extmem.m_holder.set_stored_size(0u);
2703          extmem.m_holder.set_stored_capacity(internal_capacity);
2704 
2705          {
2706             //Deallocate on exception
2707             typename value_traits::ArrayDeallocator new_buffer_deallocator(orig_extdata, extmem.get_stored_allocator(), orig_extmem_cap);
2708             typename value_traits::ArrayDestructor  new_values_destroyer(orig_extdata, extmem.get_stored_allocator(), orig_extmem_size);
2709 
2710             //Move internal memory data to the internal memory data of the target, this can throw
2711             BOOST_ASSERT(extmem.capacity() >= intmem.size());
2712             ::boost::container::uninitialized_move_alloc_n
2713                (intmem.get_stored_allocator(), this->priv_raw_begin(), intmem.size(), extmem.priv_raw_begin());
2714 
2715             //Exception not thrown, commit new state
2716             extmem.m_holder.set_stored_size(intmem.size());
2717             //Throwing part passed, disable rollback
2718             new_buffer_deallocator.release();
2719             new_values_destroyer.release();
2720          }
2721 
2722          //Destroy moved elements from intmem
2723          boost::container::destroy_alloc_n
2724             ( intmem.get_stored_allocator(), this->priv_raw_begin()
2725             , intmem.size());
2726 
2727          //Adopt dynamic buffer
2728          intmem.m_holder.m_start = orig_extdata;
2729          intmem.m_holder.set_stored_size(orig_extmem_size);
2730          intmem.m_holder.set_stored_capacity(orig_extmem_cap);
2731 
2732          //And now swap the allocator
2733          dtl::swap_alloc(this->m_holder.alloc(), x.m_holder.alloc(), dtl::bool_<propagate_alloc>());
2734       }
2735       else {   //swap element by element and insert rest
2736          bool const t_smaller = this->size() < x.size();
2737          vector &sml = t_smaller ? *this : x;
2738          vector &big = t_smaller ? x : *this;
2739 
2740          //swap element by element until common size
2741          size_type const common_elements = sml.size();
2742          for(size_type i = 0; i != common_elements; ++i){
2743             boost::adl_move_swap(sml[i], big[i]);
2744          }
2745 
2746          //And now swap the allocator to be able to construct new elements in sml with the proper allocator
2747          dtl::swap_alloc(this->m_holder.alloc(), x.m_holder.alloc(), dtl::bool_<propagate_alloc>());
2748 
2749          //move-insert the remaining range
2750          T *const raw_big_nth = boost::movelib::iterator_to_raw_pointer(big.nth(common_elements));
2751          sml.insert(sml.cend()
2752             , boost::make_move_iterator(raw_big_nth)
2753             , boost::make_move_iterator(boost::movelib::iterator_to_raw_pointer(big.end())));
2754 
2755          //Destroy remaining, moved, elements with their original allocator
2756          boost::container::destroy_alloc_n
2757             ( sml.get_stored_allocator(), raw_big_nth
2758             , std::size_t(big.m_holder.m_size - common_elements));
2759          big.m_holder.set_stored_size(common_elements);
2760       }
2761    }
2762    private:
2763    inline void priv_move_to_new_buffer(size_type, version_0)
2764    {  alloc_holder_t::on_capacity_overflow();  }
2765 
2766    inline dtl::insert_range_proxy<allocator_type, boost::move_iterator<T*> > priv_dummy_empty_proxy()
2767    {
2768       return dtl::insert_range_proxy<allocator_type, boost::move_iterator<T*> >
2769          (::boost::make_move_iterator((T *)0));
2770    }
2771 
2772    inline void priv_move_to_new_buffer(size_type new_cap, version_1)
2773    {
2774       //There is not enough memory, allocate a new buffer
2775       //Pass the hint so that allocators can take advantage of this.
2776       pointer const p = this->m_holder.allocate(new_cap);
2777       #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
2778       ++this->num_alloc;
2779       #endif
2780       //We will reuse insert code, so create a dummy input iterator
2781       this->priv_insert_forward_range_new_allocation
2782          ( boost::movelib::to_raw_pointer(p), new_cap, this->priv_raw_end(), 0, this->priv_dummy_empty_proxy());
2783    }
2784 
2785    void priv_move_to_new_buffer(size_type new_cap, version_2)
2786    {
2787       //There is not enough memory, allocate a new
2788       //buffer or expand the old one.
2789       bool same_buffer_start;
2790       size_type real_cap = 0;
2791       pointer reuse(this->m_holder.start());
2792       pointer const ret(this->m_holder.allocation_command(allocate_new | expand_fwd | expand_bwd, new_cap, real_cap = new_cap, reuse));
2793 
2794       //Check for forward expansion
2795       same_buffer_start = reuse && this->m_holder.start() == ret;
2796       if(same_buffer_start){
2797          #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
2798          ++this->num_expand_fwd;
2799          #endif
2800          this->m_holder.capacity(real_cap);
2801       }
2802       else{ //If there is no forward expansion, move objects, we will reuse insertion code
2803          T * const new_mem = boost::movelib::to_raw_pointer(ret);
2804          T * const ins_pos = this->priv_raw_end();
2805          if(reuse){   //Backwards (and possibly forward) expansion
2806             #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
2807             ++this->num_expand_bwd;
2808             #endif
2809             this->priv_insert_forward_range_expand_backwards
2810                ( new_mem, real_cap, ins_pos, 0, this->priv_dummy_empty_proxy());
2811          }
2812          else{ //New buffer
2813             #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
2814             ++this->num_alloc;
2815             #endif
2816             this->priv_insert_forward_range_new_allocation
2817                ( new_mem, real_cap, ins_pos, 0, this->priv_dummy_empty_proxy());
2818          }
2819       }
2820    }
2821 
2822    void priv_destroy_last_n(const size_type n) BOOST_NOEXCEPT_OR_NOTHROW
2823    {
2824       BOOST_ASSERT(n <= this->m_holder.m_size);
2825       boost::container::destroy_alloc_n(this->get_stored_allocator(), this->priv_raw_end() - n, n);
2826       this->m_holder.dec_stored_size(n);
2827    }
2828 
2829    template<class InpIt>
2830    void priv_uninitialized_construct_at_end(InpIt first, InpIt last)
2831    {
2832       T* const old_end_pos = this->priv_raw_end();
2833       T* const new_end_pos = boost::container::uninitialized_copy_alloc(this->m_holder.alloc(), first, last, old_end_pos);
2834       this->m_holder.inc_stored_size(static_cast<size_type>(new_end_pos - old_end_pos));
2835    }
2836 
2837    void priv_destroy_all() BOOST_NOEXCEPT_OR_NOTHROW
2838    {
2839       boost::container::destroy_alloc_n
2840          (this->get_stored_allocator(), this->priv_raw_begin(), this->m_holder.m_size);
2841       this->m_holder.m_size = 0;
2842    }
2843 
2844    template<class U>
2845    inline iterator priv_insert(const const_iterator &p, BOOST_FWD_REF(U) u)
2846    {
2847       return this->emplace(p, ::boost::forward<U>(u));
2848    }
2849 
2850    template <class U>
2851    inline void priv_push_back(BOOST_FWD_REF(U) u)
2852    {
2853       this->emplace_back(::boost::forward<U>(u));
2854    }
2855 
2856    //Overload to support compiler errors that instantiate too much
2857    inline void priv_push_back(::boost::move_detail::nat)
2858    {}
2859 
2860    inline iterator priv_insert(const_iterator, ::boost::move_detail::nat)
2861    {  return iterator();  }
2862 
2863    inline dtl::insert_n_copies_proxy<allocator_type> priv_resize_proxy(const T &x)
2864    {  return dtl::insert_n_copies_proxy<allocator_type>(x);   }
2865 
2866    inline dtl::insert_default_initialized_n_proxy<allocator_type> priv_resize_proxy(default_init_t)
2867    {  return dtl::insert_default_initialized_n_proxy<allocator_type>();  }
2868 
2869    inline dtl::insert_value_initialized_n_proxy<allocator_type> priv_resize_proxy(value_init_t)
2870    {  return dtl::insert_value_initialized_n_proxy<allocator_type>(); }
2871 
2872    protected:
2873    void prot_shrink_to_fit_small(pointer const small_buffer, const size_type small_capacity)
2874    {
2875       const size_type cp = this->m_holder.capacity();
2876       if (cp && this->m_holder.m_start != small_buffer) {   //Do something only if a dynamic buffer is used
2877          const size_type sz = this->size();
2878          if (!sz) {
2879             if (BOOST_LIKELY(!!this->m_holder.m_start))
2880                this->m_holder.deallocate(this->m_holder.m_start, cp);
2881             this->m_holder.m_start = small_buffer;
2882             this->m_holder.set_stored_capacity(small_capacity);
2883          }
2884          else if(sz <= small_capacity) {
2885             T *const oldbuf = boost::movelib::to_raw_pointer(this->m_holder.m_start);
2886             ::boost::container::uninitialized_move_alloc_n
2887                ( this->get_stored_allocator()
2888                , oldbuf
2889                , sz
2890                , boost::movelib::to_raw_pointer(small_buffer)
2891                );
2892             boost::container::destroy_alloc_n(this->get_stored_allocator(), oldbuf, sz);
2893 
2894             if (BOOST_LIKELY(!!this->m_holder.m_start))
2895                this->m_holder.deallocate(this->m_holder.m_start, cp);
2896 
2897             this->m_holder.m_start = small_buffer;
2898             this->m_holder.set_stored_capacity(small_capacity);
2899          }
2900          else if (sz < cp) {
2901             this->priv_move_to_new_buffer(sz, alloc_version());
2902          }
2903       }
2904    }
2905 
2906    private:
2907    inline void priv_shrink_to_fit(version_0) BOOST_NOEXCEPT_OR_NOTHROW
2908    {}
2909 
2910    void priv_shrink_to_fit(version_1)
2911    {
2912       const size_type cp = this->m_holder.capacity();
2913       if(cp){
2914          const size_type sz = this->size();
2915          if(!sz){
2916             if(BOOST_LIKELY(!!this->m_holder.m_start))
2917                this->m_holder.deallocate(this->m_holder.m_start, cp);
2918             this->m_holder.m_start     = pointer();
2919             this->m_holder.m_capacity  = 0;
2920          }
2921          else if(sz < cp){
2922             this->priv_move_to_new_buffer(sz, alloc_version());
2923          }
2924       }
2925    }
2926 
2927    void priv_shrink_to_fit(version_2) BOOST_NOEXCEPT_OR_NOTHROW
2928    {
2929       const size_type cp = this->m_holder.capacity();
2930       if(cp){
2931          const size_type sz = this->size();
2932          if(!sz){
2933             if(BOOST_LIKELY(!!this->m_holder.m_start))
2934                this->m_holder.deallocate(this->m_holder.m_start, cp);
2935             this->m_holder.m_start     = pointer();
2936             this->m_holder.m_capacity  = 0;
2937          }
2938          else{
2939             size_type received_size = sz;
2940             pointer reuse(this->m_holder.start());
2941             if(this->m_holder.allocation_command
2942                (shrink_in_place | nothrow_allocation, cp, received_size, reuse)){
2943                this->m_holder.capacity(received_size);
2944                #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
2945                ++this->num_shrink;
2946                #endif
2947             }
2948          }
2949       }
2950    }
2951 
2952    #ifdef _MSC_VER
2953    #pragma warning (push)
2954    #pragma warning(disable: 4702)   //Disable unreachable code warning
2955    #endif
2956    template <class InsertionProxy>
2957    inline iterator priv_insert_forward_range_no_capacity
2958       (T * const, const size_type, const InsertionProxy , version_0)
2959    {
2960       return alloc_holder_t::on_capacity_overflow(), iterator();
2961    }
2962    #ifdef _MSC_VER
2963    #pragma warning (pop)
2964    #endif
2965 
2966    template <class InsertionProxy>
2967    BOOST_CONTAINER_NOINLINE iterator priv_insert_forward_range_no_capacity
2968       (T *const raw_pos, const size_type n, const InsertionProxy insert_range_proxy, version_1)
2969    {
2970       //Check if we have enough memory or try to expand current memory
2971       const size_type n_pos = static_cast<size_type>(raw_pos - this->priv_raw_begin());
2972 
2973       const size_type new_cap = this->m_holder.template next_capacity<growth_factor_type>(n);
2974       //Pass the hint so that allocators can take advantage of this.
2975       T * const new_buf = boost::movelib::to_raw_pointer(this->m_holder.allocate(new_cap));
2976       #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
2977       ++this->num_alloc;
2978       #endif
2979       this->priv_insert_forward_range_new_allocation(new_buf, new_cap, raw_pos, n, insert_range_proxy);
2980       return iterator(this->m_holder.start() + difference_type(n_pos));
2981    }
2982 
2983    template <class InsertionProxy>
2984    BOOST_CONTAINER_NOINLINE iterator priv_insert_forward_range_no_capacity
2985       (T *const raw_pos, const size_type n, const InsertionProxy insert_range_proxy, version_2)
2986    {
2987       //Check if we have enough memory or try to expand current memory
2988       const size_type n_pos = size_type(raw_pos - this->priv_raw_begin());
2989 
2990       //There is not enough memory, allocate a new
2991       //buffer or expand the old one.
2992       size_type real_cap = this->m_holder.template next_capacity<growth_factor_type>(n);
2993       pointer reuse(this->m_holder.start());
2994       pointer const ret (this->m_holder.allocation_command
2995          (allocate_new | expand_fwd | expand_bwd, size_type(this->m_holder.m_size + n), real_cap, reuse));
2996 
2997       //Buffer reallocated
2998       if(reuse){
2999          //Forward expansion, delay insertion
3000          if(this->m_holder.start() == ret){
3001             #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
3002             ++this->num_expand_fwd;
3003             #endif
3004             this->m_holder.capacity(real_cap);
3005             //Expand forward
3006             this->priv_insert_forward_range_expand_forward
3007                (raw_pos, n, insert_range_proxy, dtl::bool_<dtl::is_single_value_proxy<InsertionProxy>::value>());
3008          }
3009          //Backwards (and possibly forward) expansion
3010          else{
3011             #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
3012             ++this->num_expand_bwd;
3013             #endif
3014             this->priv_insert_forward_range_expand_backwards
3015                (boost::movelib::to_raw_pointer(ret), real_cap, raw_pos, n, insert_range_proxy);
3016          }
3017       }
3018       //New buffer
3019       else{
3020          #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
3021          ++this->num_alloc;
3022          #endif
3023          this->priv_insert_forward_range_new_allocation
3024             ( boost::movelib::to_raw_pointer(ret), real_cap, raw_pos, n, insert_range_proxy);
3025       }
3026 
3027       return iterator(this->m_holder.start() + (difference_type)(n_pos));
3028    }
3029 
3030    template <class InsertionProxy>
3031    inline iterator priv_insert_forward_range
3032       (const pointer &pos, const size_type n, const InsertionProxy insert_range_proxy)
3033    {
3034       BOOST_ASSERT(this->m_holder.capacity() >= this->m_holder.m_size);
3035       T *const p = boost::movelib::to_raw_pointer(pos);
3036       //Check if we have enough memory or try to expand current memory
3037       if (BOOST_LIKELY(n <= (this->m_holder.capacity() - this->m_holder.m_size))){
3038          //Expand forward
3039          this->priv_insert_forward_range_expand_forward
3040             (p, n, insert_range_proxy, dtl::bool_<dtl::is_single_value_proxy<InsertionProxy>::value>());
3041          return iterator(pos);
3042       }
3043       else{
3044          return this->priv_insert_forward_range_no_capacity(p, n, insert_range_proxy, alloc_version());
3045       }
3046    }
3047 
3048    template <class U>
3049    void priv_resize(const size_type new_size, const U &u, version_0)
3050    {
3051       const size_type sz = this->m_holder.m_size;
3052       if (new_size > this->capacity()){
3053          //This will trigger an error
3054          alloc_holder_t::on_capacity_overflow();
3055       }
3056       else if (new_size < sz){
3057          //Destroy last elements
3058          this->priv_destroy_last_n(sz - new_size);
3059       }
3060       else{
3061          T* const old_finish = this->priv_raw_end();
3062          this->priv_resize_proxy(u).uninitialized_copy_n_and_update(this->m_holder.alloc(), old_finish, new_size - sz);
3063          this->m_holder.set_stored_size(new_size);
3064       }
3065    }
3066 
3067    template <class U, class AllocVersion>
3068    void priv_resize(const size_type new_size, const U &u, AllocVersion)
3069    {
3070       const size_type sz = this->m_holder.m_size;
3071       if (new_size < sz){
3072          //Destroy last elements
3073          this->priv_destroy_last_n(size_type(sz - new_size));
3074       }
3075       else {
3076          this->priv_insert_forward_range(this->back_ptr(), size_type(new_size - sz), this->priv_resize_proxy(u));
3077       }
3078    }
3079 
3080    //Takes the range pointed by [first_pos, last_pos) and shifts it to the right
3081    //by 'shift_count'. 'limit_pos' marks the end of constructed elements.
3082    //
3083    //Precondition: first_pos <= last_pos <= limit_pos
3084    //
3085    //The shift operation might cross limit_pos so elements to moved beyond limit_pos
3086    //are uninitialized_moved with an allocator. Other elements are moved.
3087    //
3088    //The shift operation might left uninitialized elements after limit_pos
3089    //and the number of uninitialized elements is returned by the function.
3090    //
3091    //Old situation:
3092    //       first_pos   last_pos         old_limit
3093    //             |       |                  |
3094    // ____________V_______V__________________V_____________
3095    //|   prefix   | range |     suffix       |raw_mem      ~
3096    //|____________|_______|__________________|_____________~
3097    //
3098    //New situation in Case A (hole_size == 0):
3099    // range is moved through move assignments
3100    //
3101    //       first_pos   last_pos         limit_pos
3102    //             |       |                  |
3103    // ____________V_______V__________________V_____________
3104    //|   prefix'  |       |  | range |suffix'|raw_mem      ~
3105    //|________________+______|___^___|_______|_____________~
3106    //                 |          |
3107    //                 |_>_>_>_>_>^
3108    //
3109    //
3110    //New situation in Case B (hole_size >= 0):
3111    // range is moved through uninitialized moves
3112    //
3113    //       first_pos   last_pos         limit_pos
3114    //             |       |                  |
3115    // ____________V_______V__________________V________________
3116    //|    prefix' |       |                  | [hole] | range |
3117    //|_______________________________________|________|___^___|
3118    //                 |                                   |
3119    //                 |_>_>_>_>_>_>_>_>_>_>_>_>_>_>_>_>_>_^
3120    //
3121    //New situation in Case C (hole_size == 0):
3122    // range is moved through move assignments and uninitialized moves
3123    //
3124    //       first_pos   last_pos         limit_pos
3125    //             |       |                  |
3126    // ____________V_______V__________________V___
3127    //|   prefix'  |       |              | range |
3128    //|___________________________________|___^___|
3129    //                 |                      |
3130    //                 |_>_>_>_>_>_>_>_>_>_>_>^
3131    size_type priv_insert_ordered_at_shift_range
3132       (size_type first_pos, size_type last_pos, size_type limit_pos, size_type shift_count)
3133    {
3134       BOOST_ASSERT(first_pos <= last_pos);
3135       BOOST_ASSERT(last_pos <= limit_pos);
3136       //
3137       T* const begin_ptr = this->priv_raw_begin();
3138       T* const first_ptr = begin_ptr + first_pos;
3139       T* const last_ptr  = begin_ptr + last_pos;
3140 
3141       size_type hole_size = 0;
3142       //Case A:
3143       if((last_pos + shift_count) <= limit_pos){
3144          //All move assigned
3145          boost::container::move_backward(first_ptr, last_ptr, last_ptr + shift_count);
3146       }
3147       //Case B:
3148       else if((first_pos + shift_count) >= limit_pos){
3149          //All uninitialized_moved
3150          ::boost::container::uninitialized_move_alloc
3151             (this->m_holder.alloc(), first_ptr, last_ptr, first_ptr + shift_count);
3152          //Cast in case size_type is narrower than int, promotions are applied
3153          //and Wconversion is in place
3154          hole_size = static_cast<size_type>(first_pos + shift_count - limit_pos);
3155       }
3156       //Case C:
3157       else{
3158          //Some uninitialized_moved
3159          T* const limit_ptr    = begin_ptr + limit_pos;
3160          T* const boundary_ptr = limit_ptr - shift_count;
3161          ::boost::container::uninitialized_move_alloc(this->m_holder.alloc(), boundary_ptr, last_ptr, limit_ptr);
3162          //The rest is move assigned
3163          boost::container::move_backward(first_ptr, boundary_ptr, limit_ptr);
3164       }
3165       return hole_size;
3166    }
3167 
3168    private:
3169    inline T *priv_raw_begin() const
3170    {  return boost::movelib::to_raw_pointer(m_holder.start());  }
3171 
3172    inline T* priv_raw_end() const
3173    {  return this->priv_raw_begin() + this->m_holder.m_size;  }
3174 
3175    template <class InsertionProxy>  //inline single-element version as it is significantly smaller
3176    inline void priv_insert_forward_range_expand_forward
3177       (T* const raw_pos, const size_type, InsertionProxy insert_range_proxy, dtl::true_type)
3178    {
3179       BOOST_ASSERT(this->room_enough());
3180       //There is enough memory
3181       T* const old_finish = this->priv_raw_end();
3182       allocator_type & a = this->m_holder.alloc();
3183 
3184       if (old_finish == raw_pos){
3185          insert_range_proxy.uninitialized_copy_n_and_update(a, old_finish, 1);
3186          ++this->m_holder.m_size;
3187       }
3188       else{
3189          //New elements can be just copied.
3190          //Move to uninitialized memory last objects
3191          T * const before_old_finish = old_finish-1;
3192 
3193          allocator_traits_type::construct(a, old_finish, ::boost::move(*before_old_finish));
3194          ++this->m_holder.m_size;
3195          //Copy previous to last objects to the initialized end
3196          boost::container::move_backward(raw_pos, before_old_finish, old_finish);
3197          //Insert new objects in the raw_pos
3198          insert_range_proxy.copy_n_and_update(a, raw_pos, 1);
3199       }
3200    }
3201 
3202    template <class InsertionProxy>
3203    inline void priv_insert_forward_range_expand_forward
3204       (T* const raw_pos, const size_type n, InsertionProxy insert_range_proxy, dtl::false_type)
3205    {
3206       //There is enough memory
3207       boost::container::expand_forward_and_insert_alloc
3208          ( this->m_holder.alloc(), raw_pos, this->priv_raw_end(), n, insert_range_proxy);
3209       this->m_holder.inc_stored_size(n);
3210    }
3211 
3212    template <class InsertionProxy>
3213    void priv_insert_forward_range_new_allocation
3214       (T* const new_start, size_type new_cap, T* const pos, const size_type n, InsertionProxy insert_range_proxy)
3215    {
3216       //n can be zero, if we want to reallocate!
3217       allocator_type &a =  this->m_holder.alloc();
3218       T * const raw_old_buffer = this->priv_raw_begin();
3219 
3220       typename value_traits::ArrayDeallocator new_buffer_deallocator(new_start, a, new_cap);
3221       boost::container::uninitialized_move_and_insert_alloc
3222          (a, raw_old_buffer, pos, this->priv_raw_end(), new_start, n, insert_range_proxy);
3223       new_buffer_deallocator.release();
3224 
3225       //Destroy and deallocate old elements
3226       if(raw_old_buffer){
3227          BOOST_IF_CONSTEXPR(!has_trivial_destructor_after_move<value_type>::value)
3228             boost::container::destroy_alloc_n(a, raw_old_buffer, this->m_holder.m_size);
3229          this->m_holder.deallocate(this->m_holder.start(), this->m_holder.capacity());
3230       }
3231 
3232       this->m_holder.start(new_start);
3233       this->m_holder.inc_stored_size(n);
3234       this->m_holder.capacity(new_cap);
3235    }
3236 
3237    template <class InsertionProxy>
3238    void priv_insert_forward_range_expand_backwards
3239          (T* const new_start, const size_type new_capacity,
3240           T* const pos, const size_type n, InsertionProxy insert_range_proxy)
3241    {
3242       T* const old_start = this->priv_raw_begin();
3243       const size_type old_size = this->m_holder.m_size;
3244       allocator_type& a = this->m_holder.alloc();
3245 
3246       //Update the vector buffer information to a safe state
3247       this->m_holder.start(new_start);
3248       this->m_holder.capacity(new_capacity);
3249       this->m_holder.m_size = 0;
3250 
3251       expand_backward_forward_and_insert_alloc(old_start, old_size, new_start, pos, n, insert_range_proxy, a);
3252 
3253       //Update the vector buffer information to a safe state
3254       this->m_holder.m_size = stored_size_type(old_size + n);
3255    }
3256 
3257    void priv_throw_if_out_of_range(size_type n) const
3258    {
3259       //If n is out of range, throw an out_of_range exception
3260       if (n >= this->size()){
3261          throw_out_of_range("vector::at out of range");
3262       }
3263    }
3264 
3265    inline bool priv_in_range(const_iterator pos) const
3266    {
3267       return (this->begin() <= pos) && (pos < this->end());
3268    }
3269 
3270    inline bool priv_in_range_or_end(const_iterator pos) const
3271    {
3272       return (this->begin() <= pos) && (pos <= this->end());
3273    }
3274 
3275    #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
3276    public:
3277    unsigned int num_expand_fwd;
3278    unsigned int num_expand_bwd;
3279    unsigned int num_shrink;
3280    unsigned int num_alloc;
3281    void reset_alloc_stats()
3282    {  num_expand_fwd = num_expand_bwd = num_alloc = 0, num_shrink = 0;   }
3283    #endif
3284    #endif   //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
3285 };
3286 
3287 #ifndef BOOST_CONTAINER_NO_CXX17_CTAD
3288 
3289 template <typename InputIterator>
3290 vector(InputIterator, InputIterator) ->
3291    vector<typename iter_value<InputIterator>::type>;
3292 
3293 template <typename InputIterator, typename Allocator>
3294 vector(InputIterator, InputIterator, Allocator const&) ->
3295    vector<typename iter_value<InputIterator>::type, Allocator>;
3296 
3297 #endif
3298 
3299 
3300 }} //namespace boost::container
3301 
3302 #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
3303 
3304 namespace boost {
3305 
3306 //!has_trivial_destructor_after_move<> == true_type
3307 //!specialization for optimizations
3308 template <class T, class Allocator, class Options>
3309 struct has_trivial_destructor_after_move<boost::container::vector<T, Allocator, Options> >
3310 {
3311    typedef typename boost::container::vector<T, Allocator, Options>::allocator_type allocator_type;
3312    typedef typename ::boost::container::allocator_traits<allocator_type>::pointer pointer;
3313    BOOST_STATIC_CONSTEXPR bool value = ::boost::has_trivial_destructor_after_move<allocator_type>::value &&
3314                                                 ::boost::has_trivial_destructor_after_move<pointer>::value;
3315 };
3316 
3317 }
3318 
3319 //See comments on vec_iterator::element_type to know why is this needed
3320 #ifdef BOOST_GNU_STDLIB
3321 
3322 BOOST_MOVE_STD_NS_BEG
3323 
3324 template <class Pointer, bool IsConst>
3325 struct pointer_traits< boost::container::vec_iterator<Pointer, IsConst> >
3326    : public boost::intrusive::pointer_traits< boost::container::vec_iterator<Pointer, IsConst> >
3327 {};
3328 
3329 BOOST_MOVE_STD_NS_END
3330 
3331 #endif   //BOOST_GNU_STDLIB
3332 
3333 #endif   //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
3334 
3335 #include <boost/container/detail/config_end.hpp>
3336 
3337 #endif //   #ifndef  BOOST_CONTAINER_CONTAINER_VECTOR_HPP