Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-10-14 08:22:27

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(static_cast<stored_size_type>(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(static_cast<stored_size_type>(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    #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
0817    //`allocator_type::value_type` must match container's `value type`. If this
0818    //assertion fails, please review your allocator definition. 
0819    BOOST_CONTAINER_STATIC_ASSERT((dtl::is_same<value_type, typename allocator_traits_t::value_type>::value));
0820 
0821    typedef typename boost::container::
0822       allocator_traits<allocator_type>::size_type                             alloc_size_type;
0823    typedef typename get_vector_opt<Options, alloc_size_type>::type            options_type;
0824    typedef typename options_type::growth_factor_type                          growth_factor_type;
0825    typedef typename options_type::stored_size_type                            stored_size_type;
0826    typedef value_less<T>                                                      value_less_t;
0827 
0828    //If provided the stored_size option must specify a type that is equal or a type that is smaller.
0829    BOOST_CONTAINER_STATIC_ASSERT( (sizeof(stored_size_type) < sizeof(alloc_size_type) ||
0830                         dtl::is_same<stored_size_type, alloc_size_type>::value) );
0831 
0832    typedef typename dtl::version<allocator_type>::type alloc_version;
0833    typedef boost::container::vector_alloc_holder
0834       <allocator_type, stored_size_type> alloc_holder_t;
0835 
0836    alloc_holder_t m_holder;
0837 
0838    typedef allocator_traits<allocator_type>                      allocator_traits_type;
0839    template <class U, class UA, class UOptions>
0840    friend class vector;
0841 
0842 
0843    protected:
0844    template <bool PropagateAllocator>
0845    inline static bool is_propagable_from(const allocator_type &from_alloc, pointer p, const allocator_type &to_alloc)
0846    {  return alloc_holder_t::template is_propagable_from<PropagateAllocator>(from_alloc, p, to_alloc);  }
0847 
0848    template <bool PropagateAllocator>
0849    inline static bool are_swap_propagable( const allocator_type &l_a, pointer l_p
0850                                          , const allocator_type &r_a, pointer r_p)
0851    {  return alloc_holder_t::template are_swap_propagable<PropagateAllocator>(l_a, l_p, r_a, r_p);  }
0852 
0853    #endif   //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
0854    #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
0855    private:
0856    BOOST_COPYABLE_AND_MOVABLE(vector)
0857    typedef vector_value_traits<allocator_type> value_traits;
0858    typedef constant_iterator<T>            cvalue_iterator;
0859 
0860    protected:
0861 
0862    inline void steal_resources(vector &x)
0863    {  return this->m_holder.steal_resources(x.m_holder);   }
0864 
0865    inline void protected_set_size(size_type n)
0866    {  this->m_holder.m_size = static_cast<stored_size_type>(n);   }
0867 
0868    template<class AllocFwd>
0869    inline vector(initial_capacity_t, pointer initial_memory, size_type cap, BOOST_FWD_REF(AllocFwd) a)
0870       : m_holder(initial_capacity_t(), initial_memory, cap, ::boost::forward<AllocFwd>(a))
0871    {}
0872 
0873    template<class AllocFwd>
0874    inline vector(initial_capacity_t, pointer initial_memory, size_type cap, BOOST_FWD_REF(AllocFwd) a, vector &x)
0875       : m_holder(initial_capacity_t(), initial_memory, cap, ::boost::forward<AllocFwd>(a))
0876    {
0877       allocator_type &this_al = this->get_stored_allocator();
0878       if (this->template is_propagable_from<true>(x.get_stored_allocator(), x.data(), this_al)) {
0879          this->steal_resources(x);
0880       }
0881       else {
0882          const size_type sz = x.size();
0883          ::boost::container::uninitialized_move_alloc_n_source
0884             ( this_al, x.priv_raw_begin(), sz
0885             //Use launder to stop false positives from -Warray-bounds
0886             , boost::move_detail::launder(this->priv_raw_begin()));
0887          this->protected_set_size(sz);
0888          x.clear();
0889       }
0890    }
0891 
0892    inline vector(initial_capacity_t, pointer initial_memory, size_type cap)
0893       : m_holder(initial_capacity_t(), initial_memory, cap)
0894    {}
0895 
0896    template<class SizeType, class AllocFwd>
0897    inline vector(maybe_initial_capacity_t, pointer p, SizeType initial_capacity, BOOST_FWD_REF(AllocFwd) a)
0898       : m_holder(maybe_initial_capacity_t(), p, initial_capacity, ::boost::forward<AllocFwd>(a))
0899    {
0900       #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
0901       this->num_alloc += size_type(p != pointer());
0902       #endif
0903    }
0904 
0905    template<class SizeType>
0906    inline vector(maybe_initial_capacity_t, pointer p, SizeType initial_capacity)
0907       : m_holder(maybe_initial_capacity_t(), p, initial_capacity)
0908    {
0909       #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
0910       this->num_alloc += size_type(p != pointer());
0911       #endif
0912    }
0913 
0914    template <class U>
0915    void protected_init_n(const size_type new_size, const U& u)
0916    {
0917       BOOST_ASSERT(this->empty());
0918       this->priv_resize_proxy(u).uninitialized_copy_n_and_update(this->m_holder.alloc(), this->priv_raw_begin(), new_size);
0919       this->m_holder.set_stored_size(new_size);
0920    }
0921 
0922    #endif   //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
0923 
0924    public:
0925    //////////////////////////////////////////////
0926    //
0927    //          construct/copy/destroy
0928    //
0929    //////////////////////////////////////////////
0930 
0931    //! <b>Effects</b>: Constructs a vector taking the allocator as parameter.
0932    //!
0933    //! <b>Throws</b>: Nothing.
0934    //!
0935    //! <b>Complexity</b>: Constant.
0936    vector() BOOST_NOEXCEPT_IF(dtl::is_nothrow_default_constructible<allocator_type>::value)
0937       : m_holder()
0938    {}
0939 
0940    //! <b>Effects</b>: Constructs a vector taking the allocator as parameter.
0941    //!
0942    //! <b>Throws</b>: Nothing
0943    //!
0944    //! <b>Complexity</b>: Constant.
0945    explicit vector(const allocator_type& a) BOOST_NOEXCEPT_OR_NOTHROW
0946       : m_holder(a)
0947    {}
0948 
0949    //! <b>Effects</b>: Constructs a vector and inserts n value initialized values.
0950    //!
0951    //! <b>Throws</b>: If allocator_type's allocation
0952    //!   throws or T's value initialization throws.
0953    //!
0954    //! <b>Complexity</b>: Linear to n.
0955    explicit vector(size_type n)
0956       :  m_holder(vector_uninitialized_size, n)
0957    {
0958       #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
0959       this->num_alloc += n != 0;
0960       #endif
0961       boost::container::uninitialized_value_init_alloc_n
0962          (this->m_holder.alloc(), n, this->priv_raw_begin());
0963    }
0964 
0965    //! <b>Effects</b>: Constructs a vector that will use a copy of allocator a
0966    //!   and inserts n value initialized values.
0967    //!
0968    //! <b>Throws</b>: If allocator_type's allocation
0969    //!   throws or T's value initialization throws.
0970    //!
0971    //! <b>Complexity</b>: Linear to n.
0972    explicit vector(size_type n, const allocator_type &a)
0973       :  m_holder(vector_uninitialized_size, a, n)
0974    {
0975       #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
0976       this->num_alloc += n != 0;
0977       #endif
0978       boost::container::uninitialized_value_init_alloc_n
0979          (this->m_holder.alloc(), n, this->priv_raw_begin());
0980    }
0981 
0982    //! <b>Effects</b>: Constructs a vector that will use a copy of allocator a
0983    //!   and inserts n default initialized values.
0984    //!
0985    //! <b>Throws</b>: If allocator_type's allocation
0986    //!   throws or T's default initialization throws.
0987    //!
0988    //! <b>Complexity</b>: Linear to n.
0989    //!
0990    //! <b>Note</b>: Non-standard extension
0991    vector(size_type n, default_init_t)
0992       :  m_holder(vector_uninitialized_size, n)
0993    {
0994       #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
0995       this->num_alloc += n != 0;
0996       #endif
0997       boost::container::uninitialized_default_init_alloc_n
0998          (this->m_holder.alloc(), n, this->priv_raw_begin());
0999    }
1000 
1001    //! <b>Effects</b>: Constructs a vector that will use a copy of allocator a
1002    //!   and inserts n default initialized values.
1003    //!
1004    //! <b>Throws</b>: If allocator_type's allocation
1005    //!   throws or T's default initialization throws.
1006    //!
1007    //! <b>Complexity</b>: Linear to n.
1008    //!
1009    //! <b>Note</b>: Non-standard extension
1010    vector(size_type n, default_init_t, const allocator_type &a)
1011       :  m_holder(vector_uninitialized_size, a, n)
1012    {
1013       #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
1014       this->num_alloc += n != 0;
1015       #endif
1016       boost::container::uninitialized_default_init_alloc_n
1017          (this->m_holder.alloc(), n, this->priv_raw_begin());
1018    }
1019 
1020    //! <b>Effects</b>: Constructs a vector
1021    //!   and inserts n copies of value.
1022    //!
1023    //! <b>Throws</b>: If allocator_type's allocation
1024    //!   throws or T's copy constructor throws.
1025    //!
1026    //! <b>Complexity</b>: Linear to n.
1027    vector(size_type n, const T& value)
1028       :  m_holder(vector_uninitialized_size, n)
1029    {
1030       #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
1031       this->num_alloc += n != 0;
1032       #endif
1033       boost::container::uninitialized_fill_alloc_n
1034          (this->m_holder.alloc(), value, n, this->priv_raw_begin());
1035    }
1036 
1037    //! <b>Effects</b>: Constructs a vector that will use a copy of allocator a
1038    //!   and inserts n copies of value.
1039    //!
1040    //! <b>Throws</b>: If allocation
1041    //!   throws or T's copy constructor throws.
1042    //!
1043    //! <b>Complexity</b>: Linear to n.
1044    vector(size_type n, const T& value, const allocator_type& a)
1045       :  m_holder(vector_uninitialized_size, a, n)
1046    {
1047       #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
1048       this->num_alloc += n != 0;
1049       #endif
1050       boost::container::uninitialized_fill_alloc_n
1051          (this->m_holder.alloc(), value, n, this->priv_raw_begin());
1052    }
1053 
1054    //! <b>Effects</b>: Constructs a vector
1055    //!   and inserts a copy of the range [first, last) in the vector.
1056    //!
1057    //! <b>Throws</b>: If allocator_type's allocation
1058    //!   throws or T's constructor taking a dereferenced InIt throws.
1059    //!
1060    //! <b>Complexity</b>: Linear to the range [first, last).
1061 //    template <class InIt>
1062 //    vector(InIt first, InIt last
1063 //           BOOST_CONTAINER_DOCIGN(BOOST_MOVE_I typename dtl::disable_if_c
1064 //                                  < dtl::is_convertible<InIt BOOST_MOVE_I size_type>::value
1065 //                                  BOOST_MOVE_I dtl::nat >::type * = 0)
1066 //           ) -> vector<typename iterator_traits<InIt>::value_type, new_allocator<typename iterator_traits<InIt>::value_type>>;
1067    template <class InIt>
1068    vector(InIt first, InIt last
1069       BOOST_CONTAINER_DOCIGN(BOOST_MOVE_I typename dtl::disable_if_c
1070          < dtl::is_convertible<InIt BOOST_MOVE_I size_type>::value
1071          BOOST_MOVE_I dtl::nat >::type * = 0)
1072       )
1073       :  m_holder()
1074    {  this->assign(first, last); }
1075 
1076    //! <b>Effects</b>: Constructs a vector that will use a copy of allocator a
1077    //!   and inserts a copy of the range [first, last) in the vector.
1078    //!
1079    //! <b>Throws</b>: If allocator_type's allocation
1080    //!   throws or T's constructor taking a dereferenced InIt throws.
1081    //!
1082    //! <b>Complexity</b>: Linear to the range [first, last).
1083    template <class InIt>
1084    vector(InIt first, InIt last, const allocator_type& a
1085       BOOST_CONTAINER_DOCIGN(BOOST_MOVE_I typename dtl::disable_if_c
1086          < dtl::is_convertible<InIt BOOST_MOVE_I size_type>::value
1087          BOOST_MOVE_I dtl::nat >::type * = 0)
1088       )
1089       :  m_holder(a)
1090    {  this->assign(first, last); }
1091 
1092    //! <b>Effects</b>: Copy constructs a vector.
1093    //!
1094    //! <b>Postcondition</b>: x == *this.
1095    //!
1096    //! <b>Throws</b>: If allocator_type's allocation
1097    //!   throws or T's copy constructor throws.
1098    //!
1099    //! <b>Complexity</b>: Linear to the elements x contains.
1100    vector(const vector &x)
1101       :  m_holder( vector_uninitialized_size
1102                  , allocator_traits_type::select_on_container_copy_construction(x.m_holder.alloc())
1103                  , x.size())
1104    {
1105       #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
1106       this->num_alloc += x.size() != 0;
1107       #endif
1108       ::boost::container::uninitialized_copy_alloc_n
1109          ( this->m_holder.alloc(), x.priv_raw_begin()
1110          , x.size(), this->priv_raw_begin());
1111    }
1112 
1113    //! <b>Effects</b>: Move constructor. Moves x's resources to *this.
1114    //!
1115    //! <b>Throws</b>: Nothing
1116    //!
1117    //! <b>Complexity</b>: Constant.
1118    vector(BOOST_RV_REF(vector) x) BOOST_NOEXCEPT_OR_NOTHROW
1119       :  m_holder(boost::move(x.m_holder))
1120    {  BOOST_CONTAINER_STATIC_ASSERT((!allocator_traits_type::is_partially_propagable::value));  }
1121 
1122    #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
1123    //! <b>Effects</b>: Constructs a vector that will use a copy of allocator a
1124    //!  and inserts a copy of the range [il.begin(), il.last()) in the vector
1125    //!
1126    //! <b>Throws</b>: If T's constructor taking a dereferenced initializer_list iterator throws.
1127    //!
1128    //! <b>Complexity</b>: Linear to the range [il.begin(), il.end()).
1129    vector(std::initializer_list<value_type> il, const allocator_type& a = allocator_type())
1130       :  m_holder(vector_uninitialized_size, a, il.size())
1131    {
1132       #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
1133       this->num_alloc += il.size() != 0;
1134       #endif
1135       ::boost::container::uninitialized_copy_alloc_n_source
1136          ( this->m_holder.alloc(), il.begin()
1137          , static_cast<size_type>(il.size()), this->priv_raw_begin());
1138    }
1139    #endif
1140 
1141    #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
1142 
1143    //! <b>Effects</b>: Move constructor. Moves x's resources to *this.
1144    //!
1145    //! <b>Throws</b>: If T's move constructor or allocation throws
1146    //!
1147    //! <b>Complexity</b>: Linear.
1148    //!
1149    //! <b>Note</b>: Non-standard extension to support static_vector
1150    template<class OtherA>
1151    vector(BOOST_RV_REF_BEG vector<T, OtherA, Options> BOOST_RV_REF_END x
1152          , typename dtl::enable_if_c
1153             < dtl::is_version<typename real_allocator<T, OtherA>::type, 0>::value>::type * = 0
1154          )
1155       :  m_holder(boost::move(x.m_holder))
1156    {}
1157 
1158    #endif   // defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
1159 
1160    //! <b>Effects</b>: Copy constructs a vector using the specified allocator.
1161    //!
1162    //! <b>Postcondition</b>: x == *this.
1163    //!
1164    //! <b>Throws</b>: If allocation
1165    //!   throws or T's copy constructor throws.
1166    //!
1167    //! <b>Complexity</b>: Linear to the elements x contains.
1168    vector(const vector &x, const allocator_type &a)
1169       :  m_holder(vector_uninitialized_size, a, x.size())
1170    {
1171       #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
1172       this->num_alloc += x.size() != 0;
1173       #endif
1174       ::boost::container::uninitialized_copy_alloc_n_source
1175          ( this->m_holder.alloc(), x.priv_raw_begin()
1176          , x.size(), this->priv_raw_begin());
1177    }
1178 
1179    //! <b>Effects</b>: Move constructor using the specified allocator.
1180    //!                 Moves x's resources to *this if a == allocator_type().
1181    //!                 Otherwise copies values from x to *this.
1182    //!
1183    //! <b>Throws</b>: If allocation or T's copy constructor throws.
1184    //!
1185    //! <b>Complexity</b>: Constant if a == x.get_allocator(), linear otherwise.
1186    vector(BOOST_RV_REF(vector) x, const allocator_type &a)
1187       :  m_holder( vector_uninitialized_size, a
1188                  //In this allocator move constructor the allocator won't be propagated --v
1189                  , is_propagable_from<false>(x.get_stored_allocator(), x.m_holder.start(), a) ? 0 : x.size()
1190                  )
1191    {
1192       //In this allocator move constructor the allocator won't be propagated ---v
1193       if(is_propagable_from<false>(x.get_stored_allocator(), x.m_holder.start(), a)){
1194          this->m_holder.steal_resources(x.m_holder);
1195       }
1196       else{
1197          const size_type n = x.size();
1198          #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
1199          this->num_alloc += n != 0;
1200          #endif
1201          ::boost::container::uninitialized_move_alloc_n_source
1202             ( this->m_holder.alloc(), x.priv_raw_begin()
1203             , n, this->priv_raw_begin());
1204       }
1205    }
1206 
1207    //! <b>Effects</b>: Destroys the vector. All stored values are destroyed
1208    //!   and used memory is deallocated.
1209    //!
1210    //! <b>Throws</b>: Nothing.
1211    //!
1212    //! <b>Complexity</b>: Linear to the number of elements.
1213    ~vector() BOOST_NOEXCEPT_OR_NOTHROW
1214    {
1215       boost::container::destroy_alloc_n
1216          (this->get_stored_allocator(), this->priv_raw_begin(), this->m_holder.m_size);
1217       //vector_alloc_holder deallocates the data
1218    }
1219 
1220    //! <b>Effects</b>: Makes *this contain the same elements as x.
1221    //!
1222    //! <b>Postcondition</b>: this->size() == x.size(). *this contains a copy
1223    //! of each of x's elements.
1224    //!
1225    //! <b>Throws</b>: If memory allocation throws or T's copy/move constructor/assignment throws.
1226    //!
1227    //! <b>Complexity</b>: Linear to the number of elements in x.
1228    inline vector& operator=(BOOST_COPY_ASSIGN_REF(vector) x)
1229    {
1230       if (BOOST_LIKELY(&x != this)){
1231          this->priv_copy_assign(x);
1232       }
1233       return *this;
1234    }
1235 
1236    #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
1237    //! <b>Effects</b>: Make *this container contains elements from il.
1238    //!
1239    //! <b>Complexity</b>: Linear to the range [il.begin(), il.end()).
1240    inline vector& operator=(std::initializer_list<value_type> il)
1241    {
1242       this->assign(il.begin(), il.end());
1243       return *this;
1244    }
1245    #endif
1246 
1247    //! <b>Effects</b>: Move assignment. All x's values are transferred to *this.
1248    //!
1249    //! <b>Postcondition</b>: x.empty(). *this contains a the elements x had
1250    //!   before the function.
1251    //!
1252    //! <b>Throws</b>: If allocator_traits_type::propagate_on_container_move_assignment
1253    //!   is false and (allocation throws or value_type's move constructor throws)
1254    //!
1255    //! <b>Complexity</b>: Constant if allocator_traits_type::
1256    //!   propagate_on_container_move_assignment is true or
1257    //!   this->get>allocator() == x.get_allocator(). Linear otherwise.
1258    inline vector& operator=(BOOST_RV_REF(vector) x)
1259       BOOST_NOEXCEPT_IF(allocator_traits_type::propagate_on_container_move_assignment::value
1260                         || allocator_traits_type::is_always_equal::value)
1261    {
1262       if (BOOST_LIKELY(&x != this)){
1263          this->priv_move_assign(boost::move(x));
1264       }
1265       return *this;
1266    }
1267 
1268    #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
1269 
1270    //! <b>Effects</b>: Move assignment. All x's values are transferred to *this.
1271    //!
1272    //! <b>Postcondition</b>: x.empty(). *this contains a the elements x had
1273    //!   before the function.
1274    //!
1275    //! <b>Throws</b>: If move constructor/assignment of T throws or allocation throws
1276    //!
1277    //! <b>Complexity</b>: Linear.
1278    //!
1279    //! <b>Note</b>: Non-standard extension to support static_vector
1280    template<class OtherA>
1281    inline typename dtl::enable_if_and
1282                            < vector&
1283                            , dtl::is_version<typename real_allocator<T, OtherA>::type, 0>
1284                            , dtl::is_different<typename real_allocator<T, OtherA>::type, allocator_type>
1285                            >::type
1286       operator=(BOOST_RV_REF_BEG vector<value_type, OtherA, Options> BOOST_RV_REF_END x)
1287    {
1288       this->priv_move_assign(boost::move(x));
1289       return *this;
1290    }
1291 
1292    //! <b>Effects</b>: Copy assignment. All x's values are copied to *this.
1293    //!
1294    //! <b>Postcondition</b>: x.empty(). *this contains a the elements x had
1295    //!   before the function.
1296    //!
1297    //! <b>Throws</b>: If move constructor/assignment of T throws or allocation throws
1298    //!
1299    //! <b>Complexity</b>: Linear.
1300    //!
1301    //! <b>Note</b>: Non-standard extension to support static_vector
1302    template<class OtherA>
1303    inline typename dtl::enable_if_and
1304                            < vector&
1305                            , dtl::is_version<typename real_allocator<T, OtherA>::type, 0>
1306                            , dtl::is_different<typename real_allocator<T, OtherA>::type, allocator_type>
1307                            >::type
1308       operator=(const vector<value_type, OtherA, Options> &x)
1309    {
1310       this->priv_copy_assign(x);
1311       return *this;
1312    }
1313 
1314    #endif
1315 
1316    //! <b>Effects</b>: Assigns the the range [first, last) to *this.
1317    //!
1318    //! <b>Throws</b>: If memory allocation throws or T's copy/move constructor/assignment or
1319    //!   T's constructor/assignment from dereferencing InpIt throws.
1320    //!
1321    //! <b>Complexity</b>: Linear to n.
1322    template <class InIt>
1323    void assign(InIt first, InIt last
1324       //Input iterators or version 0 allocator
1325       BOOST_CONTAINER_DOCIGN(BOOST_MOVE_I typename dtl::disable_if_or
1326          < void
1327          BOOST_MOVE_I dtl::is_convertible<InIt BOOST_MOVE_I size_type>
1328          BOOST_MOVE_I dtl::and_
1329             < dtl::is_different<alloc_version BOOST_MOVE_I version_0>
1330             BOOST_MOVE_I dtl::is_not_input_iterator<InIt>
1331             >
1332          >::type * = 0)
1333       )
1334    {
1335       //Overwrite all elements we can from [first, last)
1336       iterator cur = this->begin();
1337       const iterator end_it = this->end();
1338       for ( ; first != last && cur != end_it; ++cur, ++first){
1339          *cur = *first;
1340       }
1341 
1342       if (first == last){
1343          //There are no more elements in the sequence, erase remaining
1344          T* const end_pos = this->priv_raw_end();
1345          const size_type n = static_cast<size_type>(end_pos - boost::movelib::iterator_to_raw_pointer(cur));
1346          this->priv_destroy_last_n(n);
1347       }
1348       else{
1349          //There are more elements in the range, insert the remaining ones
1350          this->insert(this->cend(), first, last);
1351       }
1352    }
1353 
1354    #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
1355    //! <b>Effects</b>: Assigns the the range [il.begin(), il.end()) to *this.
1356    //!
1357    //! <b>Throws</b>: If memory allocation throws or
1358    //!   T's constructor from dereferencing iniializer_list iterator throws.
1359    //!
1360    inline void assign(std::initializer_list<T> il)
1361    {
1362       this->assign(il.begin(), il.end());
1363    }
1364    #endif
1365 
1366    //! <b>Effects</b>: Assigns the the range [first, last) to *this.
1367    //!
1368    //! <b>Throws</b>: If memory allocation throws or T's copy/move constructor/assignment or
1369    //!   T's constructor/assignment from dereferencing InpIt throws.
1370    //!
1371    //! <b>Complexity</b>: Linear to n.
1372    template <class FwdIt>
1373    void assign(FwdIt first, FwdIt last
1374       //Forward iterators and version > 0 allocator
1375       BOOST_CONTAINER_DOCIGN(BOOST_MOVE_I typename dtl::disable_if_or
1376          < void
1377          BOOST_MOVE_I dtl::is_same<alloc_version BOOST_MOVE_I version_0>
1378          BOOST_MOVE_I dtl::is_convertible<FwdIt BOOST_MOVE_I size_type>
1379          BOOST_MOVE_I dtl::is_input_iterator<FwdIt>
1380          >::type * = 0)
1381       )
1382    {
1383       typedef typename iter_size<FwdIt>::type it_size_type;
1384       //For Fwd iterators the standard only requires EmplaceConstructible and assignable from *first
1385       //so we can't do any backwards allocation
1386       const it_size_type sz = boost::container::iterator_udistance(first, last);
1387       if (BOOST_UNLIKELY(sz > size_type(-1))){
1388          boost::container::throw_length_error("vector::assign, FwdIt's max length reached");
1389       }
1390 
1391       const size_type input_sz = static_cast<size_type>(sz);
1392       const size_type old_capacity = this->capacity();
1393       if(input_sz > old_capacity){  //If input range is too big, we need to reallocate
1394          size_type real_cap = 0;
1395          pointer reuse(this->m_holder.start());
1396          pointer const ret(this->m_holder.allocation_command(allocate_new|expand_fwd, input_sz, real_cap = input_sz, reuse));
1397          if(!reuse){  //New allocation, just emplace new values
1398             #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
1399             ++this->num_alloc;
1400             #endif
1401             pointer const old_p = this->m_holder.start();
1402             if(old_p){
1403                this->priv_destroy_all();
1404                this->m_holder.deallocate(old_p, old_capacity);
1405             }
1406             this->m_holder.start(ret);
1407             this->m_holder.capacity(real_cap);
1408             this->m_holder.m_size = 0;
1409             this->priv_uninitialized_construct_at_end(first, last);
1410             return;
1411          }
1412          else{
1413             #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
1414             ++this->num_expand_fwd;
1415             #endif
1416             this->m_holder.capacity(real_cap);
1417             //Forward expansion, use assignment + back deletion/construction that comes later
1418          }
1419       }
1420 
1421       boost::container::copy_assign_range_alloc_n(this->m_holder.alloc(), first, input_sz, this->priv_raw_begin(), this->size());
1422       m_holder.set_stored_size(input_sz);
1423    }
1424 
1425    //! <b>Effects</b>: Assigns the n copies of val to *this.
1426    //!
1427    //! <b>Throws</b>: If memory allocation throws or
1428    //!   T's copy/move constructor/assignment throws.
1429    //!
1430    //! <b>Complexity</b>: Linear to n.
1431    inline void assign(size_type n, const value_type& val)
1432    {  this->assign(cvalue_iterator(val, n), cvalue_iterator());   }
1433 
1434    //! <b>Effects</b>: Returns a copy of the internal allocator.
1435    //!
1436    //! <b>Throws</b>: If allocator's copy constructor throws.
1437    //!
1438    //! <b>Complexity</b>: Constant.
1439    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline allocator_type get_allocator() const BOOST_NOEXCEPT_OR_NOTHROW
1440    { return this->m_holder.alloc();  }
1441 
1442    //! <b>Effects</b>: Returns a reference to the internal allocator.
1443    //!
1444    //! <b>Throws</b>: Nothing
1445    //!
1446    //! <b>Complexity</b>: Constant.
1447    //!
1448    //! <b>Note</b>: Non-standard extension.
1449    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline 
1450       stored_allocator_type &get_stored_allocator() BOOST_NOEXCEPT_OR_NOTHROW
1451    {  return this->m_holder.alloc(); }
1452 
1453    //! <b>Effects</b>: Returns a reference to the internal allocator.
1454    //!
1455    //! <b>Throws</b>: Nothing
1456    //!
1457    //! <b>Complexity</b>: Constant.
1458    //!
1459    //! <b>Note</b>: Non-standard extension.
1460    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
1461       const stored_allocator_type &get_stored_allocator() const BOOST_NOEXCEPT_OR_NOTHROW
1462    {  return this->m_holder.alloc(); }
1463 
1464    //////////////////////////////////////////////
1465    //
1466    //                iterators
1467    //
1468    //////////////////////////////////////////////
1469 
1470    //! <b>Effects</b>: Returns an iterator to the first element contained in the vector.
1471    //!
1472    //! <b>Throws</b>: Nothing.
1473    //!
1474    //! <b>Complexity</b>: Constant.
1475    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline iterator begin() BOOST_NOEXCEPT_OR_NOTHROW
1476    { return iterator(this->m_holder.start()); }
1477 
1478    //! <b>Effects</b>: Returns a const_iterator to the first element contained in the vector.
1479    //!
1480    //! <b>Throws</b>: Nothing.
1481    //!
1482    //! <b>Complexity</b>: Constant.
1483    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline const_iterator begin() const BOOST_NOEXCEPT_OR_NOTHROW
1484    { return const_iterator(this->m_holder.start()); }
1485 
1486    //! <b>Effects</b>: Returns an iterator to the end of the vector.
1487    //!
1488    //! <b>Throws</b>: Nothing.
1489    //!
1490    //! <b>Complexity</b>: Constant.
1491    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline iterator end() BOOST_NOEXCEPT_OR_NOTHROW
1492    {
1493       iterator it (this->m_holder.start());
1494       it += difference_type(this->m_holder.m_size);
1495       return it;  //Adding zero to null pointer is allowed (non-UB)
1496    }
1497 
1498    //! <b>Effects</b>: Returns a const_iterator to the end of the vector.
1499    //!
1500    //! <b>Throws</b>: Nothing.
1501    //!
1502    //! <b>Complexity</b>: Constant.
1503    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline const_iterator end() const BOOST_NOEXCEPT_OR_NOTHROW
1504    { return this->cend(); }
1505 
1506    //! <b>Effects</b>: Returns a reverse_iterator pointing to the beginning
1507    //! of the reversed vector.
1508    //!
1509    //! <b>Throws</b>: Nothing.
1510    //!
1511    //! <b>Complexity</b>: Constant.
1512    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline reverse_iterator rbegin() BOOST_NOEXCEPT_OR_NOTHROW
1513    { return reverse_iterator(this->end());      }
1514 
1515    //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the beginning
1516    //! of the reversed vector.
1517    //!
1518    //! <b>Throws</b>: Nothing.
1519    //!
1520    //! <b>Complexity</b>: Constant.
1521    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline const_reverse_iterator rbegin() const BOOST_NOEXCEPT_OR_NOTHROW
1522    { return this->crbegin(); }
1523 
1524    //! <b>Effects</b>: Returns a reverse_iterator pointing to the end
1525    //! of the reversed vector.
1526    //!
1527    //! <b>Throws</b>: Nothing.
1528    //!
1529    //! <b>Complexity</b>: Constant.
1530    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline reverse_iterator rend() BOOST_NOEXCEPT_OR_NOTHROW
1531    { return reverse_iterator(this->begin());       }
1532 
1533    //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the end
1534    //! of the reversed vector.
1535    //!
1536    //! <b>Throws</b>: Nothing.
1537    //!
1538    //! <b>Complexity</b>: Constant.
1539    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline const_reverse_iterator rend() const BOOST_NOEXCEPT_OR_NOTHROW
1540    { return this->crend(); }
1541 
1542    //! <b>Effects</b>: Returns a const_iterator to the first element contained in the vector.
1543    //!
1544    //! <b>Throws</b>: Nothing.
1545    //!
1546    //! <b>Complexity</b>: Constant.
1547    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline const_iterator cbegin() const BOOST_NOEXCEPT_OR_NOTHROW
1548    { return const_iterator(this->m_holder.start()); }
1549 
1550    //! <b>Effects</b>: Returns a const_iterator to the end of the vector.
1551    //!
1552    //! <b>Throws</b>: Nothing.
1553    //!
1554    //! <b>Complexity</b>: Constant.
1555    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline const_iterator cend() const BOOST_NOEXCEPT_OR_NOTHROW
1556    {
1557       const_iterator it (this->m_holder.start());
1558       it += difference_type(this->m_holder.m_size);
1559       return it;  //Adding zero to null pointer is allowed (non-UB)
1560    }
1561 
1562    //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the beginning
1563    //! of the reversed vector.
1564    //!
1565    //! <b>Throws</b>: Nothing.
1566    //!
1567    //! <b>Complexity</b>: Constant.
1568    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline const_reverse_iterator crbegin() const BOOST_NOEXCEPT_OR_NOTHROW
1569    { return const_reverse_iterator(this->end());}
1570 
1571    //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the end
1572    //! of the reversed vector.
1573    //!
1574    //! <b>Throws</b>: Nothing.
1575    //!
1576    //! <b>Complexity</b>: Constant.
1577    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline const_reverse_iterator crend() const BOOST_NOEXCEPT_OR_NOTHROW
1578    { return const_reverse_iterator(this->begin()); }
1579 
1580    //////////////////////////////////////////////
1581    //
1582    //                capacity
1583    //
1584    //////////////////////////////////////////////
1585 
1586    //! <b>Effects</b>: Returns true if the vector contains no elements.
1587    //!
1588    //! <b>Throws</b>: Nothing.
1589    //!
1590    //! <b>Complexity</b>: Constant.
1591    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline bool empty() const BOOST_NOEXCEPT_OR_NOTHROW
1592    { return !this->m_holder.m_size; }
1593 
1594    //! <b>Effects</b>: Returns the number of the elements contained in the vector.
1595    //!
1596    //! <b>Throws</b>: Nothing.
1597    //!
1598    //! <b>Complexity</b>: Constant.
1599    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline size_type size() const BOOST_NOEXCEPT_OR_NOTHROW
1600    { return this->m_holder.m_size; }
1601 
1602    //! <b>Effects</b>: Returns the largest possible size of the vector.
1603    //!
1604    //! <b>Throws</b>: Nothing.
1605    //!
1606    //! <b>Complexity</b>: Constant.
1607    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline size_type max_size() const BOOST_NOEXCEPT_OR_NOTHROW
1608    { return allocator_traits_type::max_size(this->m_holder.alloc()); }
1609 
1610    //! <b>Effects</b>: Inserts or erases elements at the end such that
1611    //!   the size becomes n. New elements are value initialized.
1612    //!
1613    //! <b>Throws</b>: If memory allocation throws, or T's copy/move or value initialization throws.
1614    //!
1615    //! <b>Complexity</b>: Linear to the difference between size() and new_size.
1616    inline void resize(size_type new_size)
1617    {  this->priv_resize(new_size, value_init, alloc_version());  }
1618 
1619    //! <b>Effects</b>: Inserts or erases elements at the end such that
1620    //!   the size becomes n. New elements are default initialized.
1621    //!
1622    //! <b>Throws</b>: If memory allocation throws, or T's copy/move or default initialization throws.
1623    //!
1624    //! <b>Complexity</b>: Linear to the difference between size() and new_size.
1625    //!
1626    //! <b>Note</b>: Non-standard extension
1627    inline void resize(size_type new_size, default_init_t)
1628    {  this->priv_resize(new_size, default_init, alloc_version());  }
1629 
1630    //! <b>Effects</b>: Inserts or erases elements at the end such that
1631    //!   the size becomes n. New elements are copy constructed from x.
1632    //!
1633    //! <b>Throws</b>: If memory allocation throws, or T's copy/move constructor throws.
1634    //!
1635    //! <b>Complexity</b>: Linear to the difference between size() and new_size.
1636    inline void resize(size_type new_size, const T& x)
1637    {  this->priv_resize(new_size, x, alloc_version());  }
1638 
1639    //! <b>Effects</b>: Number of elements for which memory has been allocated.
1640    //!   capacity() is always greater than or equal to size().
1641    //!
1642    //! <b>Throws</b>: Nothing.
1643    //!
1644    //! <b>Complexity</b>: Constant.
1645    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline size_type capacity() const BOOST_NOEXCEPT_OR_NOTHROW
1646    { return this->m_holder.capacity(); }
1647 
1648    //! <b>Effects</b>: If n is less than or equal to capacity(), this call has no
1649    //!   effect. Otherwise, it is a request for allocation of additional memory.
1650    //!   If the request is successful, then capacity() is greater than or equal to
1651    //!   n; otherwise, capacity() is unchanged. In either case, size() is unchanged.
1652    //!
1653    //! <b>Throws</b>: If memory allocation allocation throws or T's copy/move constructor throws.
1654    inline void reserve(size_type new_cap)
1655    {
1656       if (this->capacity() < new_cap){
1657          this->priv_move_to_new_buffer(new_cap, alloc_version());
1658       }
1659    }
1660 
1661    //! <b>Effects</b>: Tries to deallocate the excess of memory created
1662    //!   with previous allocations. The size of the vector is unchanged
1663    //!
1664    //! <b>Throws</b>: If memory allocation throws, or T's copy/move constructor throws.
1665    //!
1666    //! <b>Complexity</b>: Linear to size().
1667    inline void shrink_to_fit()
1668    {  this->priv_shrink_to_fit(alloc_version());   }
1669 
1670    //////////////////////////////////////////////
1671    //
1672    //               element access
1673    //
1674    //////////////////////////////////////////////
1675 
1676    //! <b>Requires</b>: !empty()
1677    //!
1678    //! <b>Effects</b>: Returns a reference to the first
1679    //!   element of the container.
1680    //!
1681    //! <b>Throws</b>: Nothing.
1682    //!
1683    //! <b>Complexity</b>: Constant.
1684    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline reference front() BOOST_NOEXCEPT_OR_NOTHROW
1685    {
1686       BOOST_ASSERT(!this->empty());
1687       return *this->m_holder.start();
1688    }
1689 
1690    //! <b>Requires</b>: !empty()
1691    //!
1692    //! <b>Effects</b>: Returns a const reference to the first
1693    //!   element of the container.
1694    //!
1695    //! <b>Throws</b>: Nothing.
1696    //!
1697    //! <b>Complexity</b>: Constant.
1698    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline const_reference front() const BOOST_NOEXCEPT_OR_NOTHROW
1699    {
1700       BOOST_ASSERT(!this->empty());
1701       return *this->m_holder.start();
1702    }
1703 
1704    //! <b>Requires</b>: !empty()
1705    //!
1706    //! <b>Effects</b>: Returns a reference to the last
1707    //!   element of the container.
1708    //!
1709    //! <b>Throws</b>: Nothing.
1710    //!
1711    //! <b>Complexity</b>: Constant.
1712    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline reference back() BOOST_NOEXCEPT_OR_NOTHROW
1713    {
1714       BOOST_ASSERT(!this->empty());
1715       return this->m_holder.start()[difference_type(this->m_holder.m_size - 1u)];
1716    }
1717 
1718    //! <b>Requires</b>: !empty()
1719    //!
1720    //! <b>Effects</b>: Returns a const reference to the last
1721    //!   element of the container.
1722    //!
1723    //! <b>Throws</b>: Nothing.
1724    //!
1725    //! <b>Complexity</b>: Constant.
1726    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline const_reference back()  const BOOST_NOEXCEPT_OR_NOTHROW
1727    {
1728       BOOST_ASSERT(!this->empty());
1729       return this->m_holder.start()[this->m_holder.m_size - 1];
1730    }
1731 
1732    //! <b>Requires</b>: size() > n.
1733    //!
1734    //! <b>Effects</b>: Returns a reference to the nth element
1735    //!   from the beginning of the container.
1736    //!
1737    //! <b>Throws</b>: Nothing.
1738    //!
1739    //! <b>Complexity</b>: Constant.
1740    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline reference operator[](size_type n) BOOST_NOEXCEPT_OR_NOTHROW
1741    {
1742       BOOST_ASSERT(this->m_holder.m_size > n);
1743       return this->m_holder.start()[difference_type(n)];
1744    }
1745 
1746    //! <b>Requires</b>: size() > n.
1747    //!
1748    //! <b>Effects</b>: Returns a const reference to the nth element
1749    //!   from the beginning of the container.
1750    //!
1751    //! <b>Throws</b>: Nothing.
1752    //!
1753    //! <b>Complexity</b>: Constant.
1754    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
1755       const_reference operator[](size_type n) const BOOST_NOEXCEPT_OR_NOTHROW
1756    {
1757       BOOST_ASSERT(this->m_holder.m_size > n);
1758       return this->m_holder.start()[n];
1759    }
1760 
1761    //! <b>Requires</b>: size() >= n.
1762    //!
1763    //! <b>Effects</b>: Returns an iterator to the nth element
1764    //!   from the beginning of the container. Returns end()
1765    //!   if n == size().
1766    //!
1767    //! <b>Throws</b>: Nothing.
1768    //!
1769    //! <b>Complexity</b>: Constant.
1770    //!
1771    //! <b>Note</b>: Non-standard extension
1772    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
1773       iterator nth(size_type n) BOOST_NOEXCEPT_OR_NOTHROW
1774    {
1775       BOOST_ASSERT(this->m_holder.m_size >= n);
1776       return iterator(this->m_holder.start()+difference_type(n));
1777    }
1778 
1779    //! <b>Requires</b>: size() >= n.
1780    //!
1781    //! <b>Effects</b>: Returns a const_iterator to the nth element
1782    //!   from the beginning of the container. Returns end()
1783    //!   if n == size().
1784    //!
1785    //! <b>Throws</b>: Nothing.
1786    //!
1787    //! <b>Complexity</b>: Constant.
1788    //!
1789    //! <b>Note</b>: Non-standard extension
1790    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
1791       const_iterator nth(size_type n) const BOOST_NOEXCEPT_OR_NOTHROW
1792    {
1793       BOOST_ASSERT(this->m_holder.m_size >= n);
1794       return const_iterator(this->m_holder.start()+difference_type(n));
1795    }
1796 
1797    //! <b>Requires</b>: begin() <= p <= end().
1798    //!
1799    //! <b>Effects</b>: Returns the index of the element pointed by p
1800    //!   and size() if p == end().
1801    //!
1802    //! <b>Throws</b>: Nothing.
1803    //!
1804    //! <b>Complexity</b>: Constant.
1805    //!
1806    //! <b>Note</b>: Non-standard extension
1807    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
1808       size_type index_of(iterator p) BOOST_NOEXCEPT_OR_NOTHROW
1809    {
1810       //Range check assert done in priv_index_of
1811       return this->priv_index_of(vector_iterator_get_ptr(p));
1812    }
1813 
1814    //! <b>Requires</b>: begin() <= p <= end().
1815    //!
1816    //! <b>Effects</b>: Returns the index of the element pointed by p
1817    //!   and size() if p == end().
1818    //!
1819    //! <b>Throws</b>: Nothing.
1820    //!
1821    //! <b>Complexity</b>: Constant.
1822    //!
1823    //! <b>Note</b>: Non-standard extension
1824    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline
1825       size_type index_of(const_iterator p) const BOOST_NOEXCEPT_OR_NOTHROW
1826    {
1827       //Range check assert done in priv_index_of
1828       return this->priv_index_of(vector_iterator_get_ptr(p));
1829    }
1830 
1831    //! <b>Requires</b>: size() > n.
1832    //!
1833    //! <b>Effects</b>: Returns a reference to the nth element
1834    //!   from the beginning of the container.
1835    //!
1836    //! <b>Throws</b>: range_error if n >= size()
1837    //!
1838    //! <b>Complexity</b>: Constant.
1839    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline reference at(size_type n)
1840    {
1841       this->priv_throw_if_out_of_range(n);
1842       return this->m_holder.start()[difference_type(n)];
1843    }
1844 
1845    //! <b>Requires</b>: size() > n.
1846    //!
1847    //! <b>Effects</b>: Returns a const reference to the nth element
1848    //!   from the beginning of the container.
1849    //!
1850    //! <b>Throws</b>: range_error if n >= size()
1851    //!
1852    //! <b>Complexity</b>: Constant.
1853    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline const_reference at(size_type n) const
1854    {
1855       this->priv_throw_if_out_of_range(n);
1856       return this->m_holder.start()[n];
1857    }
1858 
1859    //////////////////////////////////////////////
1860    //
1861    //                 data access
1862    //
1863    //////////////////////////////////////////////
1864 
1865    //! <b>Returns</b>: A pointer such that [data(),data() + size()) is a valid range.
1866    //!   For a non-empty vector, data() == &front().
1867    //!
1868    //! <b>Throws</b>: Nothing.
1869    //!
1870    //! <b>Complexity</b>: Constant.
1871    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline T* data() BOOST_NOEXCEPT_OR_NOTHROW
1872    { return this->priv_raw_begin(); }
1873 
1874    //! <b>Returns</b>: A pointer such that [data(),data() + size()) is a valid range.
1875    //!   For a non-empty vector, data() == &front().
1876    //!
1877    //! <b>Throws</b>: Nothing.
1878    //!
1879    //! <b>Complexity</b>: Constant.
1880    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline const T * data()  const BOOST_NOEXCEPT_OR_NOTHROW
1881    { return this->priv_raw_begin(); }
1882 
1883    //////////////////////////////////////////////
1884    //
1885    //                modifiers
1886    //
1887    //////////////////////////////////////////////
1888 
1889    #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
1890    //! <b>Effects</b>: Inserts an object of type T constructed with
1891    //!   std::forward<Args>(args)... in the end of the vector.
1892    //!
1893    //! <b>Returns</b>: A reference to the created object.
1894    //!
1895    //! <b>Throws</b>: If memory allocation throws or the in-place constructor throws or
1896    //!   T's copy/move constructor throws.
1897    //!
1898    //! <b>Complexity</b>: Amortized constant time.
1899    template<class ...Args>
1900    inline reference emplace_back(BOOST_FWD_REF(Args)...args)
1901    {
1902       T* const p = this->priv_raw_end();
1903       if (BOOST_LIKELY(this->room_enough())){
1904          //There is more memory, just construct a new object at the end
1905          allocator_traits_type::construct(this->m_holder.alloc(), p, ::boost::forward<Args>(args)...);
1906          ++this->m_holder.m_size;
1907          return *p;
1908       }
1909       else{
1910          typedef dtl::insert_emplace_proxy<allocator_type, Args...> proxy_t;
1911          return *this->priv_insert_forward_range_no_capacity
1912             (p, 1, proxy_t(::boost::forward<Args>(args)...), alloc_version());
1913       }
1914    }
1915 
1916    //! <b>Effects</b>: Inserts an object of type T constructed with
1917    //!   std::forward<Args>(args)... in the end of the vector.
1918    //!
1919    //! <b>Throws</b>: If the in-place constructor throws.
1920    //!
1921    //! <b>Complexity</b>: Constant time.
1922    //!
1923    //! <b>Note</b>: Non-standard extension.
1924    template<class ...Args>
1925    inline bool stable_emplace_back(BOOST_FWD_REF(Args)...args)
1926    {
1927       const bool is_room_enough = this->room_enough() || (alloc_version::value == 2 && this->m_holder.try_expand_fwd(1u));
1928       if (BOOST_LIKELY(is_room_enough)){
1929          //There is more memory, just construct a new object at the end
1930          allocator_traits_type::construct(this->m_holder.alloc(), this->priv_raw_end(), ::boost::forward<Args>(args)...);
1931          ++this->m_holder.m_size;
1932       }
1933       return is_room_enough;
1934    }
1935 
1936    //! <b>Requires</b>: position must be a valid iterator of *this.
1937    //!
1938    //! <b>Effects</b>: Inserts an object of type T constructed with
1939    //!   std::forward<Args>(args)... before position
1940    //!
1941    //! <b>Throws</b>: If memory allocation throws or the in-place constructor throws or
1942    //!   T's copy/move constructor/assignment throws.
1943    //!
1944    //! <b>Complexity</b>: If position is end(), amortized constant time
1945    //!   Linear time otherwise.
1946    template<class ...Args>
1947    inline iterator emplace(const_iterator position, BOOST_FWD_REF(Args) ...args)
1948    {
1949       BOOST_ASSERT(this->priv_in_range_or_end(position));
1950       //Just call more general insert(pos, size, value) and return iterator
1951       typedef dtl::insert_emplace_proxy<allocator_type, Args...> proxy_t;
1952       return this->priv_insert_forward_range( vector_iterator_get_ptr(position), 1
1953                                             , proxy_t(::boost::forward<Args>(args)...));
1954    }
1955 
1956    #else // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
1957 
1958    #define BOOST_CONTAINER_VECTOR_EMPLACE_CODE(N) \
1959    BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
1960    inline reference emplace_back(BOOST_MOVE_UREF##N)\
1961    {\
1962       T* const p = this->priv_raw_end();\
1963       if (BOOST_LIKELY(this->room_enough())){\
1964          allocator_traits_type::construct (this->m_holder.alloc()\
1965             , this->priv_raw_end() BOOST_MOVE_I##N BOOST_MOVE_FWD##N);\
1966          ++this->m_holder.m_size;\
1967          return *p;\
1968       }\
1969       else{\
1970          typedef dtl::insert_emplace_proxy_arg##N<allocator_type BOOST_MOVE_I##N BOOST_MOVE_TARG##N> proxy_t;\
1971          return *this->priv_insert_forward_range_no_capacity\
1972             ( p, 1, proxy_t(BOOST_MOVE_FWD##N), alloc_version());\
1973       }\
1974    }\
1975    \
1976    BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
1977    inline bool stable_emplace_back(BOOST_MOVE_UREF##N)\
1978    {\
1979       const bool is_room_enough = this->room_enough() || (alloc_version::value == 2 && this->m_holder.try_expand_fwd(1u));\
1980       if (BOOST_LIKELY(is_room_enough)){\
1981          allocator_traits_type::construct (this->m_holder.alloc()\
1982             , this->priv_raw_end() BOOST_MOVE_I##N BOOST_MOVE_FWD##N);\
1983          ++this->m_holder.m_size;\
1984       }\
1985       return is_room_enough;\
1986    }\
1987    \
1988    BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
1989    inline iterator emplace(const_iterator pos BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\
1990    {\
1991       BOOST_ASSERT(this->priv_in_range_or_end(pos));\
1992       typedef dtl::insert_emplace_proxy_arg##N<allocator_type BOOST_MOVE_I##N BOOST_MOVE_TARG##N> proxy_t;\
1993       return this->priv_insert_forward_range(vector_iterator_get_ptr(pos), 1, proxy_t(BOOST_MOVE_FWD##N));\
1994    }\
1995    //
1996    BOOST_MOVE_ITERATE_0TO9(BOOST_CONTAINER_VECTOR_EMPLACE_CODE)
1997    #undef BOOST_CONTAINER_VECTOR_EMPLACE_CODE
1998 
1999    #endif
2000 
2001    #if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
2002    //! <b>Effects</b>: Inserts a copy of x at the end of the vector.
2003    //!
2004    //! <b>Throws</b>: If memory allocation throws or
2005    //!   T's copy/move constructor throws.
2006    //!
2007    //! <b>Complexity</b>: Amortized constant time.
2008    void push_back(const T &x);
2009 
2010    //! <b>Effects</b>: Constructs a new element in the end of the vector
2011    //!   and moves the resources of x to this new element.
2012    //!
2013    //! <b>Throws</b>: If memory allocation throws or
2014    //!   T's copy/move constructor throws.
2015    //!
2016    //! <b>Complexity</b>: Amortized constant time.
2017    void push_back(T &&x);
2018    #else
2019    BOOST_MOVE_CONVERSION_AWARE_CATCH(push_back, T, void, priv_push_back)
2020    #endif
2021 
2022    #if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
2023    //! <b>Requires</b>: position must be a valid iterator of *this.
2024    //!
2025    //! <b>Effects</b>: Insert a copy of x before position.
2026    //!
2027    //! <b>Throws</b>: If memory allocation throws or T's copy/move constructor/assignment throws.
2028    //!
2029    //! <b>Complexity</b>: If position is end(), amortized constant time
2030    //!   Linear time otherwise.
2031    iterator insert(const_iterator position, const T &x);
2032 
2033    //! <b>Requires</b>: position must be a valid iterator of *this.
2034    //!
2035    //! <b>Effects</b>: Insert a new element before position with x's resources.
2036    //!
2037    //! <b>Throws</b>: If memory allocation throws.
2038    //!
2039    //! <b>Complexity</b>: If position is end(), amortized constant time
2040    //!   Linear time otherwise.
2041    iterator insert(const_iterator position, T &&x);
2042    #else
2043    BOOST_MOVE_CONVERSION_AWARE_CATCH_1ARG(insert, T, iterator, priv_insert, const_iterator, const_iterator)
2044    #endif
2045 
2046    //! <b>Requires</b>: p must be a valid iterator of *this.
2047    //!
2048    //! <b>Effects</b>: Insert n copies of x before pos.
2049    //!
2050    //! <b>Returns</b>: an iterator to the first inserted element or p if n is 0.
2051    //!
2052    //! <b>Throws</b>: If memory allocation throws or T's copy/move constructor throws.
2053    //!
2054    //! <b>Complexity</b>: Linear to n.
2055    inline iterator insert(const_iterator p, size_type n, const T& x)
2056    {
2057       BOOST_ASSERT(this->priv_in_range_or_end(p));
2058       dtl::insert_n_copies_proxy<allocator_type> proxy(x);
2059       return this->priv_insert_forward_range(vector_iterator_get_ptr(p), n, proxy);
2060    }
2061 
2062    //! <b>Requires</b>: p must be a valid iterator of *this.
2063    //!
2064    //! <b>Effects</b>: Insert a copy of the [first, last) range before pos.
2065    //!
2066    //! <b>Returns</b>: an iterator to the first inserted element or pos if first == last.
2067    //!
2068    //! <b>Throws</b>: If memory allocation throws, T's constructor from a
2069    //!   dereferenced InpIt throws or T's copy/move constructor/assignment throws.
2070    //!
2071    //! <b>Complexity</b>: Linear to boost::container::iterator_distance [first, last).
2072    template <class InIt>
2073    iterator insert(const_iterator pos, InIt first, InIt last
2074       #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
2075       , typename dtl::disable_if_or
2076          < void
2077          , dtl::is_convertible<InIt, size_type>
2078          , dtl::is_not_input_iterator<InIt>
2079          >::type * = 0
2080       #endif
2081       )
2082    {
2083       BOOST_ASSERT(this->priv_in_range_or_end(pos));
2084       const size_type n_pos = size_type(pos - this->cbegin());
2085       iterator it(vector_iterator_get_ptr(pos));
2086       for(;first != last; ++first){
2087          it = this->emplace(it, *first);
2088          ++it;
2089       }
2090       return iterator(this->m_holder.start() + difference_type(n_pos));
2091    }
2092 
2093    #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
2094    template <class FwdIt>
2095    inline iterator insert(const_iterator pos, FwdIt first, FwdIt last
2096       , typename dtl::disable_if_or
2097          < void
2098          , dtl::is_convertible<FwdIt, size_type>
2099          , dtl::is_input_iterator<FwdIt>
2100          >::type * = 0
2101       )
2102    {
2103       typedef typename iter_size<FwdIt>::type it_size_type;
2104       BOOST_ASSERT(this->priv_in_range_or_end(pos));
2105       const it_size_type sz = boost::container::iterator_udistance(first, last);
2106       if (BOOST_UNLIKELY(sz > size_type(-1))){
2107          boost::container::throw_length_error("vector::insert, FwdIt's max length reached");
2108       }
2109 
2110       dtl::insert_range_proxy<allocator_type, FwdIt> proxy(first);
2111       return this->priv_insert_forward_range(vector_iterator_get_ptr(pos), static_cast<size_type>(sz), proxy);
2112    }
2113    #endif
2114 
2115    //! <b>Requires</b>: p must be a valid iterator of *this. num, must
2116    //!   be equal to boost::container::iterator_distance(first, last)
2117    //!
2118    //! <b>Effects</b>: Insert a copy of the [first, last) range before pos.
2119    //!
2120    //! <b>Returns</b>: an iterator to the first inserted element or pos if first == last.
2121    //!
2122    //! <b>Throws</b>: If memory allocation throws, T's constructor from a
2123    //!   dereferenced InpIt throws or T's copy/move constructor/assignment throws.
2124    //!
2125    //! <b>Complexity</b>: Linear to boost::container::iterator_distance [first, last).
2126    //!
2127    //! <b>Note</b>: This function avoids a linear operation to calculate boost::container::iterator_distance[first, last)
2128    //!   for forward and bidirectional iterators, and a one by one insertion for input iterators. This is a
2129    //!   a non-standard extension.
2130    #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
2131    template <class InIt>
2132    inline iterator insert(const_iterator pos, size_type num, InIt first, InIt last)
2133    {
2134       BOOST_ASSERT(this->priv_in_range_or_end(pos));
2135       BOOST_ASSERT(dtl::is_input_iterator<InIt>::value ||
2136                    num == boost::container::iterator_udistance(first, last));
2137       (void)last;
2138       dtl::insert_range_proxy<allocator_type, InIt> proxy(first);
2139       return this->priv_insert_forward_range(vector_iterator_get_ptr(pos), num, proxy);
2140    }
2141    #endif
2142 
2143    #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
2144    //! <b>Requires</b>: position must be a valid iterator of *this.
2145    //!
2146    //! <b>Effects</b>: Insert a copy of the [il.begin(), il.end()) range before position.
2147    //!
2148    //! <b>Returns</b>: an iterator to the first inserted element or position if first == last.
2149    //!
2150    //! <b>Complexity</b>: Linear to the range [il.begin(), il.end()).
2151    inline iterator insert(const_iterator position, std::initializer_list<value_type> il)
2152    {
2153       //Assertion done in insert()
2154       return this->insert(position, il.begin(), il.end());
2155    }
2156    #endif
2157 
2158    //! <b>Effects</b>: Removes the last element from the container.
2159    //!
2160    //! <b>Throws</b>: Nothing.
2161    //!
2162    //! <b>Complexity</b>: Constant time.
2163    inline void pop_back() BOOST_NOEXCEPT_OR_NOTHROW
2164    {
2165       BOOST_ASSERT(!this->empty());
2166       //Destroy last element
2167       allocator_traits_type::destroy(this->get_stored_allocator(), this->priv_raw_end() - 1);
2168       --this->m_holder.m_size;
2169    }
2170 
2171    //! <b>Effects</b>: Erases the element at position pos.
2172    //!
2173    //! <b>Throws</b>: Nothing.
2174    //!
2175    //! <b>Complexity</b>: Linear to the elements between pos and the
2176    //!   last element. Constant if pos is the last element.
2177    iterator erase(const_iterator position)
2178    {
2179       BOOST_ASSERT(this->priv_in_range(position));
2180       const pointer p = vector_iterator_get_ptr(position);
2181       T *const pos_ptr = boost::movelib::to_raw_pointer(p);
2182       T *const end_ptr = this->priv_raw_end();
2183 
2184       //Move elements forward and destroy last
2185       (void)::boost::container::move(pos_ptr + 1, end_ptr, pos_ptr);
2186 
2187       T *const last_ptr = end_ptr-1;
2188       if(!value_traits::trivial_dctr_after_move || pos_ptr == last_ptr){
2189          allocator_traits_type::destroy(this->get_stored_allocator(), last_ptr);
2190       }
2191       --this->m_holder.m_size;
2192       return iterator(p);
2193    }
2194 
2195    //! <b>Effects</b>: Erases the elements pointed by [first, last).
2196    //!
2197    //! <b>Throws</b>: Nothing.
2198    //!
2199    //! <b>Complexity</b>: Linear to the distance between first and last
2200    //!   plus linear to the elements between pos and the last element.
2201    iterator erase(const_iterator first, const_iterator last)
2202    {
2203       BOOST_ASSERT(this->priv_in_range_or_end(first));
2204       BOOST_ASSERT(this->priv_in_range_or_end(last));
2205       BOOST_ASSERT(first <= last);
2206       if(first != last){
2207          T* const old_end_ptr = this->priv_raw_end();
2208          T* const first_ptr = boost::movelib::to_raw_pointer(vector_iterator_get_ptr(first));
2209          T* const last_ptr  = boost::movelib::to_raw_pointer(vector_iterator_get_ptr(last));
2210          T* const new_last_ptr = boost::movelib::to_raw_pointer(boost::container::move(last_ptr, old_end_ptr, first_ptr));
2211          const size_type n = static_cast<size_type>(old_end_ptr - new_last_ptr);
2212          if(!value_traits::trivial_dctr_after_move || old_end_ptr == last_ptr){
2213             boost::container::destroy_alloc_n(this->get_stored_allocator(), new_last_ptr, n);
2214          }
2215          this->m_holder.dec_stored_size(n);
2216       }
2217       return iterator(vector_iterator_get_ptr(first));
2218    }
2219 
2220    //! <b>Effects</b>: Swaps the contents of *this and x.
2221    //!
2222    //! <b>Throws</b>: Nothing.
2223    //!
2224    //! <b>Complexity</b>: Constant.
2225    inline void swap(vector& x)
2226       BOOST_NOEXCEPT_IF( ((allocator_traits_type::propagate_on_container_swap::value
2227                                     || allocator_traits_type::is_always_equal::value) &&
2228                                     !dtl::is_version<allocator_type, 0>::value))
2229    {
2230       this->priv_swap(x, dtl::bool_<dtl::is_version<allocator_type, 0>::value>());
2231    }
2232 
2233    #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
2234 
2235    //! <b>Effects</b>: Swaps the contents of *this and x.
2236    //!
2237    //! <b>Throws</b>: Nothing.
2238    //!
2239    //! <b>Complexity</b>: Linear
2240    //!
2241    //! <b>Note</b>: Non-standard extension to support static_vector
2242    template<class OtherA>
2243    inline void swap(vector<T, OtherA, Options> & x
2244             , typename dtl::enable_if_and
2245                      < void
2246                      , dtl::is_version<typename real_allocator<T, OtherA>::type, 0>
2247                      , dtl::is_different<typename real_allocator<T, OtherA>::type, allocator_type>
2248                      >::type * = 0
2249             )
2250    {  this->m_holder.deep_swap(x.m_holder); }
2251 
2252    #endif   //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
2253 
2254    //! <b>Effects</b>: Erases all the elements of the vector. Leaves the capacity() of the vector unchanged.
2255    //!
2256    //! <b>Throws</b>: Nothing.
2257    //!
2258    //! <b>Complexity</b>: Linear to the number of elements in the container.
2259    inline void clear() BOOST_NOEXCEPT_OR_NOTHROW
2260    {  this->priv_destroy_all();  }
2261 
2262    //! <b>Effects</b>: Returns true if x and y are equal
2263    //!
2264    //! <b>Complexity</b>: Linear to the number of elements in the container.
2265    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline friend bool operator==(const vector& x, const vector& y)
2266    {  return x.size() == y.size() && ::boost::container::algo_equal(x.begin(), x.end(), y.begin());  }
2267 
2268    //! <b>Effects</b>: Returns true if x and y are unequal
2269    //!
2270    //! <b>Complexity</b>: Linear to the number of elements in the container.
2271    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline friend bool operator!=(const vector& x, const vector& y)
2272    {  return !(x == y); }
2273 
2274    //! <b>Effects</b>: Returns true if x is less than y
2275    //!
2276    //! <b>Complexity</b>: Linear to the number of elements in the container.
2277    BOOST_CONTAINER_ATTRIBUTE_NODISCARD friend bool operator<(const vector& x, const vector& y)
2278    {  return boost::container::algo_lexicographical_compare(x.begin(), x.end(), y.begin(), y.end());  }
2279 
2280    //! <b>Effects</b>: Returns true if x is greater than y
2281    //!
2282    //! <b>Complexity</b>: Linear to the number of elements in the container.
2283    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline friend bool operator>(const vector& x, const vector& y)
2284    {  return y < x;  }
2285 
2286    //! <b>Effects</b>: Returns true if x is equal or less than y
2287    //!
2288    //! <b>Complexity</b>: Linear to the number of elements in the container.
2289    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline friend bool operator<=(const vector& x, const vector& y)
2290    {  return !(y < x);  }
2291 
2292    //! <b>Effects</b>: Returns true if x is equal or greater than y
2293    //!
2294    //! <b>Complexity</b>: Linear to the number of elements in the container.
2295    BOOST_CONTAINER_ATTRIBUTE_NODISCARD inline friend bool operator>=(const vector& x, const vector& y)
2296    {  return !(x < y);  }
2297 
2298    //! <b>Effects</b>: x.swap(y)
2299    //!
2300    //! <b>Complexity</b>: Constant.
2301    inline friend void swap(vector& x, vector& y)
2302        BOOST_NOEXCEPT_IF(BOOST_NOEXCEPT(x.swap(y)))
2303    {  x.swap(y);  }
2304 
2305    #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
2306    //! <b>Effects</b>: If n is less than or equal to capacity(), this call has no
2307    //!   effect. Otherwise, it is a request for allocation of additional memory
2308    //!   (memory expansion) that will not invalidate iterators.
2309    //!   If the request is successful, then capacity() is greater than or equal to
2310    //!   n; otherwise, capacity() is unchanged. In either case, size() is unchanged.
2311    //!
2312    //! <b>Throws</b>: If memory allocation allocation throws or T's copy/move constructor throws.
2313    //!
2314    //! <b>Note</b>: Non-standard extension.
2315    bool stable_reserve(size_type new_cap)
2316    {
2317       const size_type cp = this->capacity();
2318       return cp >= new_cap || (alloc_version::value == 2 && this->m_holder.try_expand_fwd(size_type(new_cap - cp)));
2319    }
2320 
2321    #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
2322    //Absolutely experimental. This function might change, disappear or simply crash!
2323    template<class BiDirPosConstIt, class BiDirValueIt>
2324    inline void insert_ordered_at(const size_type element_count, BiDirPosConstIt last_position_it, BiDirValueIt last_value_it)
2325    {
2326       typedef vector_insert_ordered_cursor<BiDirPosConstIt, BiDirValueIt> inserter_t;
2327       return this->priv_insert_ordered_at(element_count, inserter_t(last_position_it, last_value_it));
2328    }
2329 
2330    template<class InputIt>
2331    inline void merge(InputIt first, InputIt last)
2332    {  this->merge(first, last, value_less_t());  }
2333 
2334    template<class InputIt, class Compare>
2335    inline 
2336       typename dtl::enable_if_c
2337          < !dtl::is_input_iterator<InputIt>::value &&
2338            dtl::is_same<value_type, typename iterator_traits<InputIt>::value_type>::value
2339          , void>::type
2340       merge(InputIt first, InputIt last, Compare comp)
2341    {
2342       size_type const s = this->size();
2343       size_type const c = this->capacity();
2344       size_type n = 0;
2345       size_type const free_cap = c - s;
2346       //If not input iterator and new elements don't fit in the remaining capacity, merge in new buffer
2347       if(free_cap < (n = boost::container::iterator_udistance(first, last))){
2348          this->priv_merge_in_new_buffer(first, n, comp, alloc_version());
2349       }
2350       else{
2351          this->priv_merge_generic(first, last, comp);
2352       }
2353    }
2354 
2355    template<class InputIt, class Compare>
2356    inline 
2357       typename dtl::enable_if_c
2358          < dtl::is_input_iterator<InputIt>::value ||
2359            !dtl::is_same<value_type, typename iterator_traits<InputIt>::value_type>::value
2360          , void>::type
2361       merge(InputIt first, InputIt last, Compare comp)
2362    {
2363       this->priv_merge_generic(first, last, comp);
2364    }
2365 
2366    template<class InputIt>
2367    inline void merge_unique(InputIt first, InputIt last)
2368    {  this->merge_unique(first, last, value_less_t());  }
2369 
2370    template<class InputIt, class Compare>
2371    inline 
2372       typename dtl::enable_if_c
2373          < !dtl::is_input_iterator<InputIt>::value &&
2374            dtl::is_same<value_type, typename iterator_traits<InputIt>::value_type>::value
2375          , void>::type
2376       merge_unique(InputIt first, InputIt last, Compare comp)
2377    {
2378       size_type const old_size = this->size();
2379       this->priv_set_difference_back(first, last, comp);
2380       T *const raw_beg = this->priv_raw_begin();
2381       T *const raw_end = this->priv_raw_end();
2382       T *raw_pos = raw_beg + old_size;
2383       boost::movelib::adaptive_merge(raw_beg, raw_pos, raw_end, comp, raw_end, this->capacity() - this->size());
2384    }
2385 
2386    template<class InputIt, class Compare>
2387    inline 
2388       typename dtl::enable_if_c
2389          < dtl::is_input_iterator<InputIt>::value ||
2390            !dtl::is_same<value_type, typename iterator_traits<InputIt>::value_type>::value
2391          , void>::type
2392       merge_unique(InputIt first, InputIt last, Compare comp)
2393    {
2394       iterator pos = this->insert(this->end(), first, last);
2395       const iterator e = boost::movelib::inplace_set_unique_difference(pos, this->end(), this->begin(), pos, comp);
2396       this->erase(e, this->end());
2397       boost::movelib::adaptive_merge( this->begin(), pos, e, comp
2398                                     , this->priv_raw_end(), this->capacity() - this->size());
2399    }
2400 
2401    //Function for optimizations, not for users
2402    T *unused_storage(size_type &sz)
2403    {
2404       sz = static_cast<size_type>(this->capacity() - this->size());
2405       return this->priv_raw_end();
2406    }
2407   
2408    #endif
2409 
2410    private:
2411    template<class InputIt, class Compare>
2412    inline void priv_merge_generic(InputIt first, InputIt last, Compare comp)
2413    {
2414       size_type const old_s = this->size();
2415       this->insert(this->cend(), first, last);
2416       T* const raw_beg = this->priv_raw_begin();
2417       T* const raw_end = this->priv_raw_end();
2418       T* const raw_pos = raw_beg + old_s;
2419       boost::movelib::adaptive_merge(raw_beg, raw_pos, raw_end, comp, raw_end, this->capacity() - this->size());
2420    }
2421 
2422    template<class PositionValue>
2423    void priv_insert_ordered_at(const size_type element_count, PositionValue position_value)
2424    {
2425       const size_type old_size_pos = this->size();
2426       this->reserve(old_size_pos + element_count);
2427       T* const begin_ptr = this->priv_raw_begin();
2428       size_type insertions_left = element_count;
2429       size_type prev_pos = old_size_pos;
2430       size_type old_hole_size = element_count;
2431 
2432       //Exception rollback. If any copy throws before the hole is filled, values
2433       //already inserted/copied at the end of the buffer will be destroyed.
2434       typename value_traits::ArrayDestructor past_hole_values_destroyer
2435          (begin_ptr + old_size_pos + element_count, this->m_holder.alloc(), size_type(0u));
2436       //Loop for each insertion backwards, first moving the elements after the insertion point,
2437       //then inserting the element.
2438       while(insertions_left){
2439          --position_value;
2440          size_type const pos = position_value.get_pos();
2441          BOOST_ASSERT(pos != size_type(-1) && pos <= old_size_pos && pos <= prev_pos);
2442          //If needed shift the range after the insertion point and the previous insertion point.
2443          //Function will take care if the shift crosses the size() boundary, using copy/move
2444          //or uninitialized copy/move if necessary.
2445          size_type new_hole_size = (pos != prev_pos)
2446             ? priv_insert_ordered_at_shift_range(pos, prev_pos, this->size(), insertions_left)
2447             : old_hole_size
2448             ;
2449          if(new_hole_size){
2450             //The hole was reduced by priv_insert_ordered_at_shift_range so expand exception rollback range backwards
2451             past_hole_values_destroyer.increment_size_backwards(prev_pos - pos);
2452             //Insert the new value in the hole
2453             allocator_traits_type::construct(this->m_holder.alloc(), begin_ptr + pos + insertions_left - 1, position_value.get_val());
2454             if(--new_hole_size){
2455                //The hole was reduced by the new insertion by one
2456                past_hole_values_destroyer.increment_size_backwards(size_type(1u));
2457             }
2458             else{
2459                //Hole was just filled, disable exception rollback and change vector size
2460                past_hole_values_destroyer.release();
2461                this->m_holder.inc_stored_size(element_count);
2462             }
2463          }
2464          else{
2465             if(old_hole_size){
2466                //Hole was just filled by priv_insert_ordered_at_shift_range, disable exception rollback and change vector size
2467                past_hole_values_destroyer.release();
2468                this->m_holder.inc_stored_size(element_count);
2469             }
2470             //Insert the new value in the already constructed range
2471             begin_ptr[pos + insertions_left - 1] = position_value.get_val();
2472          }
2473          --insertions_left;
2474          old_hole_size = new_hole_size;
2475          prev_pos = pos;
2476       }
2477    }
2478 
2479    template<class InputIt, class Compare>
2480    void priv_set_difference_back(InputIt first1, InputIt last1, Compare comp)
2481    {
2482       T * old_first2 = this->priv_raw_begin();
2483       T * first2 = old_first2;
2484       T * last2  = this->priv_raw_end();
2485 
2486       while (first1 != last1) {
2487          if (first2 == last2){
2488             this->insert(this->cend(), first1, last1);
2489             return;
2490          }
2491 
2492          if (comp(*first1, *first2)) {
2493             this->emplace_back(*first1);
2494             T * const raw_begin = this->priv_raw_begin();
2495             if(old_first2 != raw_begin)
2496             {
2497                //Reallocation happened, update range
2498                first2 = raw_begin + (first2 - old_first2);
2499                last2  = raw_begin + (last2 - old_first2);
2500                old_first2 = raw_begin;
2501             }
2502             ++first1;
2503          }
2504          else {
2505             if (!comp(*first2, *first1)) {
2506                ++first1;
2507             }
2508             ++first2;
2509          }
2510       }
2511    }
2512 
2513    template<class FwdIt, class Compare>
2514    inline void priv_merge_in_new_buffer(FwdIt, size_type, Compare, version_0)
2515    {
2516       alloc_holder_t::on_capacity_overflow();
2517    }
2518 
2519    template<class FwdIt, class Compare, class Version>
2520    void priv_merge_in_new_buffer(FwdIt first, size_type n, Compare comp, Version)
2521    {
2522       size_type const new_size = this->size() + n;
2523       size_type new_cap = new_size;
2524       pointer p = pointer();
2525       pointer const new_storage = this->m_holder.allocation_command(allocate_new, new_size, new_cap, p);
2526 
2527       BOOST_ASSERT((new_cap >= this->size() ) && (new_cap - this->size()) >= n);
2528       allocator_type &a = this->m_holder.alloc();
2529       typename value_traits::ArrayDeallocator new_buffer_deallocator(new_storage, a, new_cap);
2530       typename value_traits::ArrayDestructor  new_values_destroyer(new_storage, a, 0u);
2531       T* pbeg  = this->priv_raw_begin();
2532       size_type const old_size = this->size();
2533       T* const pend = pbeg + old_size;
2534       T* d_first = boost::movelib::to_raw_pointer(new_storage);
2535       size_type added = n;
2536       //Merge in new buffer loop
2537       while(1){
2538          if(!n) {
2539             ::boost::container::uninitialized_move_alloc(this->m_holder.alloc(), pbeg, pend, d_first);
2540             break;
2541          } 
2542          else if(pbeg == pend) {
2543             ::boost::container::uninitialized_move_alloc_n(this->m_holder.alloc(), first, n, d_first);
2544             break;
2545          }
2546          //maintain stability moving external values only if they are strictly less
2547          else if(comp(*first, *pbeg)) {
2548             allocator_traits_type::construct( this->m_holder.alloc(), d_first, *first );
2549             new_values_destroyer.increment_size(1u);
2550             ++first;
2551             --n;
2552             ++d_first;
2553          }
2554          else{
2555             allocator_traits_type::construct( this->m_holder.alloc(), d_first, boost::move(*pbeg) );
2556             new_values_destroyer.increment_size(1u);
2557             ++pbeg;
2558             ++d_first;
2559          }
2560       }
2561 
2562       //Nothrow operations
2563       pointer const old_p     = this->m_holder.start();
2564       size_type const old_cap = this->m_holder.capacity();
2565       boost::container::destroy_alloc_n(a, boost::movelib::to_raw_pointer(old_p), old_size);
2566       if (old_cap > 0) {
2567          this->m_holder.deallocate(old_p, old_cap);
2568       }
2569       m_holder.set_stored_size(old_size + added);
2570       this->m_holder.start(new_storage);
2571       this->m_holder.capacity(new_cap);
2572       new_buffer_deallocator.release();
2573       new_values_destroyer.release();
2574    }
2575 
2576    inline bool room_enough() const
2577    {  return this->m_holder.m_size != this->m_holder.capacity();   }
2578 
2579    inline pointer back_ptr() const
2580    {  return this->m_holder.start() + difference_type(this->m_holder.m_size);  }
2581 
2582    inline size_type priv_index_of(pointer p) const
2583    {
2584       BOOST_ASSERT(this->m_holder.start() <= p);
2585       BOOST_ASSERT(p <= (this->m_holder.start()+difference_type(this->size())));
2586       return static_cast<size_type>(p - this->m_holder.start());
2587    }
2588 
2589    template<class OtherA>
2590    void priv_move_assign(BOOST_RV_REF_BEG vector<T, OtherA, Options> BOOST_RV_REF_END x
2591       , typename dtl::enable_if_c
2592          < dtl::is_version<typename real_allocator<T, OtherA>::type, 0>::value >::type * = 0)
2593    {
2594       if(!dtl::is_same<typename real_allocator<T, OtherA>::type, allocator_type>::value &&
2595           this->capacity() < x.size()){
2596          alloc_holder_t::on_capacity_overflow();
2597       }
2598       T* const this_start  = this->priv_raw_begin();
2599       T* const other_start = x.priv_raw_begin();
2600       const size_type this_sz  = m_holder.m_size;
2601       const size_type other_sz = static_cast<size_type>(x.m_holder.m_size);
2602       boost::container::move_assign_range_alloc_n(this->m_holder.alloc(), other_start, other_sz, this_start, this_sz);
2603       m_holder.set_stored_size(other_sz);
2604       //Not emptying the source container seems to be confusing for users as drop-in
2605       //replacement for non-static vectors, so clear it.
2606       x.clear();
2607    }
2608 
2609    template<class OtherA>
2610    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*/)
2611    {
2612       this->clear();
2613       if (BOOST_LIKELY(!!this->m_holder.m_start))
2614          this->m_holder.deallocate(this->m_holder.m_start, this->m_holder.m_capacity);
2615       this->m_holder.steal_resources(x.m_holder);
2616    }
2617 
2618    template<class OtherA>
2619    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*/)
2620    {
2621       const bool propagate_alloc = allocator_traits_type::propagate_on_container_move_assignment::value;
2622       allocator_type& this_alloc = this->m_holder.alloc();
2623       allocator_type& x_alloc = x.m_holder.alloc();
2624 
2625       //In this allocator move constructor the allocator might will be propagated, but to support small_vector-like
2626       //types, we need to check the currently owned buffers to know if they are propagable.
2627       const bool is_buffer_propagable_from_x = is_propagable_from<propagate_alloc>(x_alloc, x.m_holder.start(), this_alloc);
2628 
2629       if (is_buffer_propagable_from_x) {
2630          this->priv_move_assign_steal_or_assign(boost::move(x), dtl::true_type());
2631       }
2632       //Else do a one by one move. Also, clear the source as users find confusing
2633       //elements are still alive in the source container.
2634       else {
2635          this->assign( boost::make_move_iterator(boost::movelib::iterator_to_raw_pointer(x.begin()))
2636                      , boost::make_move_iterator(boost::movelib::iterator_to_raw_pointer(x.end()))   );
2637          x.clear();
2638       }
2639    }
2640 
2641    template<class OtherA>
2642    void priv_move_assign(BOOST_RV_REF_BEG vector<T, OtherA, Options> BOOST_RV_REF_END x
2643       , typename dtl::disable_if_or
2644          < void
2645          , dtl::is_version<typename real_allocator<T, OtherA>::type, 0>
2646          , dtl::is_different<typename real_allocator<T, OtherA>::type, allocator_type>
2647          >::type * = 0)
2648    {
2649       //for move assignment, no aliasing (&x != this) is assumed.
2650       //x.size() == 0 is allowed for buggy std libraries.
2651       BOOST_ASSERT(this != &x || x.size() == 0);
2652       const bool alloc_is_always_equal = allocator_traits_type::is_always_equal::value;
2653       const bool propagate_alloc = allocator_traits_type::propagate_on_container_move_assignment::value;
2654       const bool partially_propagable_alloc = allocator_traits_type::is_partially_propagable::value;
2655       const bool data_can_be_always_be_stolen = alloc_is_always_equal || (propagate_alloc && !partially_propagable_alloc);
2656 
2657       this->priv_move_assign_steal_or_assign(boost::move(x), dtl::bool_<data_can_be_always_be_stolen>());
2658 
2659       //Move allocator if needed
2660       allocator_type& this_alloc = this->m_holder.alloc();
2661       allocator_type& x_alloc    = x.m_holder.alloc();
2662       dtl::move_alloc(this_alloc, x_alloc, dtl::bool_<propagate_alloc>());
2663    }
2664 
2665    template<class OtherA>
2666    void priv_copy_assign(const vector<T, OtherA, Options> &x
2667       , typename dtl::enable_if_c
2668          < dtl::is_version<typename real_allocator<T, OtherA>::type, 0>::value >::type * = 0)
2669    {
2670       if(!dtl::is_same<typename real_allocator<T, OtherA>::type, allocator_type>::value &&
2671          this->capacity() < x.size()){
2672          alloc_holder_t::on_capacity_overflow();
2673       }
2674       T* const this_start  = this->priv_raw_begin();
2675       T* const other_start = x.priv_raw_begin();
2676       const size_type this_sz  = m_holder.m_size;
2677       const size_type other_sz = static_cast<size_type>(x.m_holder.m_size);
2678       boost::container::copy_assign_range_alloc_n(this->m_holder.alloc(), other_start, other_sz, this_start, this_sz);
2679       m_holder.set_stored_size(other_sz);
2680    }
2681 
2682    template<class OtherA>
2683    typename dtl::disable_if_or
2684       < void
2685       , dtl::is_version<typename real_allocator<T, OtherA>::type, 0>
2686       , dtl::is_different<typename real_allocator<T, OtherA>::type, allocator_type>
2687       >::type
2688       priv_copy_assign(const vector<T, OtherA, Options> &x)
2689    {
2690       allocator_type &this_alloc     = this->m_holder.alloc();
2691       const allocator_type &x_alloc  = x.m_holder.alloc();
2692       dtl::bool_<allocator_traits_type::
2693          propagate_on_container_copy_assignment::value> flag;
2694       if(flag && this_alloc != x_alloc){
2695          this->clear();
2696          this->shrink_to_fit();
2697       }
2698       dtl::assign_alloc(this_alloc, x_alloc, flag);
2699       this->assign( x.priv_raw_begin(), x.priv_raw_end() );
2700    }
2701 
2702    template<class Vector>  //Template it to avoid it in explicit instantiations
2703    inline void priv_swap(Vector &x, dtl::true_type)   //version_0
2704    {  this->m_holder.deep_swap(x.m_holder);  }
2705 
2706    template<class Vector>  //Template it to avoid it in explicit instantiations
2707    void priv_swap(Vector &x, dtl::false_type)  //version_N
2708    {
2709       BOOST_ASSERT(allocator_traits_type::propagate_on_container_swap::value ||
2710                    allocator_traits_type::is_always_equal::value ||
2711                    this->get_stored_allocator() == x.get_stored_allocator());
2712 
2713       if (BOOST_UNLIKELY(&x == this)) {
2714          return;
2715       }
2716 
2717       //Just swap internals
2718       this->m_holder.swap_resources(x.m_holder);
2719       //And now swap the allocator
2720       dtl::bool_<allocator_traits_type::propagate_on_container_swap::value> flag;
2721       dtl::swap_alloc(this->m_holder.alloc(), x.m_holder.alloc(), flag);
2722    }
2723 
2724    protected:
2725    template<class Vector>  //Template it to avoid it in explicit instantiations
2726    void prot_swap_small(Vector &x, std::size_t internal_capacity)  //version_N
2727    {
2728       if (BOOST_UNLIKELY(&x == this)){
2729          return;
2730       }
2731 
2732       const bool propagate_alloc = allocator_traits_type::propagate_on_container_swap::value;
2733       if(are_swap_propagable<propagate_alloc>
2734          ( this->get_stored_allocator(), this->m_holder.start(), x.get_stored_allocator(), x.m_holder.start())){
2735          this->priv_swap(x, dtl::false_());
2736          return;
2737       }
2738 
2739       allocator_type &th_al = this->get_stored_allocator();
2740       allocator_type &ot_al = x.get_stored_allocator();
2741 
2742       const bool is_this_data_propagable = is_propagable_from<propagate_alloc>(th_al, this->data(), ot_al);
2743       const bool is_that_data_propagable = is_propagable_from<propagate_alloc>(ot_al, x.data(), th_al);
2744 
2745       if(internal_capacity && (is_this_data_propagable || is_that_data_propagable)) {
2746          //steal memory from src to dst, but move elements from dst to src
2747          vector& extmem = is_this_data_propagable ? *this : x;
2748          vector& intmem = is_this_data_propagable ? x : *this;
2749 
2750          //Reset extmem to the internal storage and backup data
2751          pointer const orig_extdata = extmem.data();
2752          const size_type orig_extmem_size = extmem.size();
2753          const size_type orig_extmem_cap = extmem.capacity();
2754 
2755          //New safe state for extmem -> empty, internal storage
2756          extmem.m_holder.m_start = extmem.get_stored_allocator().internal_storage();
2757          extmem.m_holder.set_stored_size(0u);
2758          extmem.m_holder.set_stored_capacity(internal_capacity);
2759 
2760          {
2761             //Deallocate on exception
2762             typename value_traits::ArrayDeallocator new_buffer_deallocator(orig_extdata, extmem.get_stored_allocator(), orig_extmem_cap);
2763             typename value_traits::ArrayDestructor  new_values_destroyer(orig_extdata, extmem.get_stored_allocator(), orig_extmem_size);
2764 
2765             //Move internal memory data to the internal memory data of the target, this can throw
2766             BOOST_ASSERT(extmem.capacity() >= intmem.size());
2767             ::boost::container::uninitialized_move_alloc_n
2768                (intmem.get_stored_allocator(), intmem.priv_raw_begin(), intmem.size(), extmem.priv_raw_begin());
2769 
2770             //Exception not thrown, commit new state
2771             extmem.m_holder.set_stored_size(intmem.size());
2772             //Throwing part passed, disable rollback
2773             new_buffer_deallocator.release();
2774             new_values_destroyer.release();
2775          }
2776 
2777          //Destroy moved elements from intmem
2778          boost::container::destroy_alloc_n
2779             ( intmem.get_stored_allocator(), intmem.priv_raw_begin()
2780             , intmem.size());
2781 
2782          //Adopt dynamic buffer
2783          intmem.m_holder.m_start = orig_extdata;
2784          intmem.m_holder.set_stored_size(orig_extmem_size);
2785          intmem.m_holder.set_stored_capacity(orig_extmem_cap);
2786 
2787          //And now swap the allocator
2788          dtl::swap_alloc(this->m_holder.alloc(), x.m_holder.alloc(), dtl::bool_<propagate_alloc>());
2789       }
2790       else {   //swap element by element and insert rest
2791          bool const t_smaller = this->size() < x.size();
2792          vector &sml = t_smaller ? *this : x;
2793          vector &big = t_smaller ? x : *this;
2794 
2795          //swap element by element until common size
2796          size_type const common_elements = sml.size();
2797          for(size_type i = 0; i != common_elements; ++i){
2798             boost::adl_move_swap(sml[i], big[i]);
2799          }
2800 
2801          //And now swap the allocator to be able to construct new elements in sml with the proper allocator
2802          dtl::swap_alloc(this->m_holder.alloc(), x.m_holder.alloc(), dtl::bool_<propagate_alloc>());
2803 
2804          //move-insert the remaining range
2805          T *const raw_big_nth = boost::movelib::iterator_to_raw_pointer(big.nth(common_elements));
2806          sml.insert(sml.cend()
2807             , boost::make_move_iterator(raw_big_nth)
2808             , boost::make_move_iterator(boost::movelib::iterator_to_raw_pointer(big.end())));
2809 
2810          //Destroy remaining, moved, elements with their original allocator
2811          boost::container::destroy_alloc_n
2812             ( sml.get_stored_allocator(), raw_big_nth
2813             , std::size_t(big.m_holder.m_size - common_elements));
2814          big.m_holder.set_stored_size(common_elements);
2815       }
2816    }
2817    private:
2818    inline void priv_move_to_new_buffer(size_type, version_0)
2819    {  alloc_holder_t::on_capacity_overflow();  }
2820 
2821    inline dtl::insert_range_proxy<allocator_type, boost::move_iterator<T*> > priv_dummy_empty_proxy()
2822    {
2823       return dtl::insert_range_proxy<allocator_type, boost::move_iterator<T*> >
2824          (::boost::make_move_iterator((T *)0));
2825    }
2826 
2827    inline void priv_move_to_new_buffer(size_type new_cap, version_1)
2828    {
2829       //There is not enough memory, allocate a new buffer
2830       //Pass the hint so that allocators can take advantage of this.
2831       pointer const p = this->m_holder.allocate(new_cap);
2832       #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
2833       ++this->num_alloc;
2834       #endif
2835       //We will reuse insert code, so create a dummy input iterator
2836       this->priv_insert_forward_range_new_allocation
2837          ( boost::movelib::to_raw_pointer(p), new_cap, this->priv_raw_end(), 0, this->priv_dummy_empty_proxy());
2838    }
2839 
2840    void priv_move_to_new_buffer(size_type new_cap, version_2)
2841    {
2842       //There is not enough memory, allocate a new
2843       //buffer or expand the old one.
2844       bool same_buffer_start;
2845       size_type real_cap = 0;
2846       pointer reuse(this->m_holder.start());
2847       pointer const ret(this->m_holder.allocation_command(allocate_new | expand_fwd | expand_bwd, new_cap, real_cap = new_cap, reuse));
2848 
2849       //Check for forward expansion
2850       same_buffer_start = reuse && this->m_holder.start() == ret;
2851       if(same_buffer_start){
2852          #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
2853          ++this->num_expand_fwd;
2854          #endif
2855          this->m_holder.capacity(real_cap);
2856       }
2857       else{ //If there is no forward expansion, move objects, we will reuse insertion code
2858          T * const new_mem = boost::movelib::to_raw_pointer(ret);
2859          T * const ins_pos = this->priv_raw_end();
2860          if(reuse){   //Backwards (and possibly forward) expansion
2861             #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
2862             ++this->num_expand_bwd;
2863             #endif
2864             this->priv_insert_forward_range_expand_backwards
2865                ( new_mem, real_cap, ins_pos, 0, this->priv_dummy_empty_proxy());
2866          }
2867          else{ //New buffer
2868             #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
2869             ++this->num_alloc;
2870             #endif
2871             this->priv_insert_forward_range_new_allocation
2872                ( new_mem, real_cap, ins_pos, 0, this->priv_dummy_empty_proxy());
2873          }
2874       }
2875    }
2876 
2877    void priv_destroy_last_n(const size_type n) BOOST_NOEXCEPT_OR_NOTHROW
2878    {
2879       BOOST_ASSERT(n <= this->m_holder.m_size);
2880       boost::container::destroy_alloc_n(this->get_stored_allocator(), this->priv_raw_end() - n, n);
2881       this->m_holder.dec_stored_size(n);
2882    }
2883 
2884    template<class InpIt>
2885    void priv_uninitialized_construct_at_end(InpIt first, InpIt last)
2886    {
2887       T* const old_end_pos = this->priv_raw_end();
2888       T* const new_end_pos = boost::container::uninitialized_copy_alloc(this->m_holder.alloc(), first, last, old_end_pos);
2889       this->m_holder.inc_stored_size(static_cast<size_type>(new_end_pos - old_end_pos));
2890    }
2891 
2892    void priv_destroy_all() BOOST_NOEXCEPT_OR_NOTHROW
2893    {
2894       boost::container::destroy_alloc_n
2895          (this->get_stored_allocator(), this->priv_raw_begin(), this->m_holder.m_size);
2896       this->m_holder.m_size = 0;
2897    }
2898 
2899    template<class U>
2900    inline iterator priv_insert(const const_iterator &p, BOOST_FWD_REF(U) u)
2901    {
2902       return this->emplace(p, ::boost::forward<U>(u));
2903    }
2904 
2905    template <class U>
2906    inline void priv_push_back(BOOST_FWD_REF(U) u)
2907    {
2908       this->emplace_back(::boost::forward<U>(u));
2909    }
2910 
2911    //Overload to support compiler errors that instantiate too much
2912    inline void priv_push_back(::boost::move_detail::nat)
2913    {}
2914 
2915    inline iterator priv_insert(const_iterator, ::boost::move_detail::nat)
2916    {  return iterator();  }
2917 
2918    inline dtl::insert_n_copies_proxy<allocator_type> priv_resize_proxy(const T &x)
2919    {  return dtl::insert_n_copies_proxy<allocator_type>(x);   }
2920 
2921    inline dtl::insert_default_initialized_n_proxy<allocator_type> priv_resize_proxy(default_init_t)
2922    {  return dtl::insert_default_initialized_n_proxy<allocator_type>();  }
2923 
2924    inline dtl::insert_value_initialized_n_proxy<allocator_type> priv_resize_proxy(value_init_t)
2925    {  return dtl::insert_value_initialized_n_proxy<allocator_type>(); }
2926 
2927    protected:
2928    void prot_shrink_to_fit_small(pointer const small_buffer, const size_type small_capacity)
2929    {
2930       const size_type cp = this->m_holder.capacity();
2931       if (cp && this->m_holder.m_start != small_buffer) {   //Do something only if a dynamic buffer is used
2932          const size_type sz = this->size();
2933          if (!sz) {
2934             if (BOOST_LIKELY(!!this->m_holder.m_start))
2935                this->m_holder.deallocate(this->m_holder.m_start, cp);
2936             this->m_holder.m_start = small_buffer;
2937             this->m_holder.set_stored_capacity(small_capacity);
2938          }
2939          else if(sz <= small_capacity) {
2940             T *const oldbuf = boost::movelib::to_raw_pointer(this->m_holder.m_start);
2941             ::boost::container::uninitialized_move_alloc_n
2942                ( this->get_stored_allocator()
2943                , oldbuf
2944                , sz
2945                , boost::movelib::to_raw_pointer(small_buffer)
2946                );
2947             boost::container::destroy_alloc_n(this->get_stored_allocator(), oldbuf, sz);
2948 
2949             if (BOOST_LIKELY(!!this->m_holder.m_start))
2950                this->m_holder.deallocate(this->m_holder.m_start, cp);
2951 
2952             this->m_holder.m_start = small_buffer;
2953             this->m_holder.set_stored_capacity(small_capacity);
2954          }
2955          else if (sz < cp) {
2956             this->priv_move_to_new_buffer(sz, alloc_version());
2957          }
2958       }
2959    }
2960 
2961    private:
2962    inline void priv_shrink_to_fit(version_0) BOOST_NOEXCEPT_OR_NOTHROW
2963    {}
2964 
2965    void priv_shrink_to_fit(version_1)
2966    {
2967       const size_type cp = this->m_holder.capacity();
2968       if(cp){
2969          const size_type sz = this->size();
2970          if(!sz){
2971             if(BOOST_LIKELY(!!this->m_holder.m_start))
2972                this->m_holder.deallocate(this->m_holder.m_start, cp);
2973             this->m_holder.m_start     = pointer();
2974             this->m_holder.m_capacity  = 0;
2975          }
2976          else if(sz < cp){
2977             this->priv_move_to_new_buffer(sz, alloc_version());
2978          }
2979       }
2980    }
2981 
2982    void priv_shrink_to_fit(version_2) BOOST_NOEXCEPT_OR_NOTHROW
2983    {
2984       const size_type cp = this->m_holder.capacity();
2985       if(cp){
2986          const size_type sz = this->size();
2987          if(!sz){
2988             if(BOOST_LIKELY(!!this->m_holder.m_start))
2989                this->m_holder.deallocate(this->m_holder.m_start, cp);
2990             this->m_holder.m_start     = pointer();
2991             this->m_holder.m_capacity  = 0;
2992          }
2993          else{
2994             size_type received_size = sz;
2995             pointer reuse(this->m_holder.start());
2996             if(this->m_holder.allocation_command
2997                (shrink_in_place | nothrow_allocation, cp, received_size, reuse)){
2998                this->m_holder.capacity(received_size);
2999                #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
3000                ++this->num_shrink;
3001                #endif
3002             }
3003          }
3004       }
3005    }
3006 
3007    #ifdef _MSC_VER
3008    #pragma warning (push)
3009    #pragma warning(disable: 4702)   //Disable unreachable code warning
3010    #endif
3011    template <class InsertionProxy>
3012    inline iterator priv_insert_forward_range_no_capacity
3013       (T * const, const size_type, const InsertionProxy , version_0)
3014    {
3015       return alloc_holder_t::on_capacity_overflow(), iterator();
3016    }
3017    #ifdef _MSC_VER
3018    #pragma warning (pop)
3019    #endif
3020 
3021    template <class InsertionProxy>
3022    BOOST_CONTAINER_NOINLINE iterator priv_insert_forward_range_no_capacity
3023       (T *const raw_pos, const size_type n, const InsertionProxy insert_range_proxy, version_1)
3024    {
3025       //Check if we have enough memory or try to expand current memory
3026       const size_type n_pos = static_cast<size_type>(raw_pos - this->priv_raw_begin());
3027 
3028       const size_type new_cap = this->m_holder.template next_capacity<growth_factor_type>(n);
3029       //Pass the hint so that allocators can take advantage of this.
3030       T * const new_buf = boost::movelib::to_raw_pointer(this->m_holder.allocate(new_cap));
3031       #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
3032       ++this->num_alloc;
3033       #endif
3034       this->priv_insert_forward_range_new_allocation(new_buf, new_cap, raw_pos, n, insert_range_proxy);
3035       return iterator(this->m_holder.start() + difference_type(n_pos));
3036    }
3037 
3038    template <class InsertionProxy>
3039    BOOST_CONTAINER_NOINLINE iterator priv_insert_forward_range_no_capacity
3040       (T *const raw_pos, const size_type n, const InsertionProxy insert_range_proxy, version_2)
3041    {
3042       //Check if we have enough memory or try to expand current memory
3043       const size_type n_pos = size_type(raw_pos - this->priv_raw_begin());
3044 
3045       //There is not enough memory, allocate a new
3046       //buffer or expand the old one.
3047       size_type real_cap = this->m_holder.template next_capacity<growth_factor_type>(n);
3048       pointer reuse(this->m_holder.start());
3049       pointer const ret (this->m_holder.allocation_command
3050          (allocate_new | expand_fwd | expand_bwd, size_type(this->m_holder.m_size + n), real_cap, reuse));
3051 
3052       //Buffer reallocated
3053       if(reuse){
3054          //Forward expansion, delay insertion
3055          if(this->m_holder.start() == ret){
3056             #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
3057             ++this->num_expand_fwd;
3058             #endif
3059             this->m_holder.capacity(real_cap);
3060             //Expand forward
3061             this->priv_insert_forward_range_expand_forward
3062                (raw_pos, n, insert_range_proxy, dtl::bool_<dtl::is_single_value_proxy<InsertionProxy>::value>());
3063          }
3064          //Backwards (and possibly forward) expansion
3065          else{
3066             #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
3067             ++this->num_expand_bwd;
3068             #endif
3069             this->priv_insert_forward_range_expand_backwards
3070                (boost::movelib::to_raw_pointer(ret), real_cap, raw_pos, n, insert_range_proxy);
3071          }
3072       }
3073       //New buffer
3074       else{
3075          #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
3076          ++this->num_alloc;
3077          #endif
3078          this->priv_insert_forward_range_new_allocation
3079             ( boost::movelib::to_raw_pointer(ret), real_cap, raw_pos, n, insert_range_proxy);
3080       }
3081 
3082       return iterator(this->m_holder.start() + (difference_type)(n_pos));
3083    }
3084 
3085    template <class InsertionProxy>
3086    inline iterator priv_insert_forward_range
3087       (const pointer &pos, const size_type n, const InsertionProxy insert_range_proxy)
3088    {
3089       BOOST_ASSERT(this->m_holder.capacity() >= this->m_holder.m_size);
3090       T *const p = boost::movelib::to_raw_pointer(pos);
3091       //Check if we have enough memory or try to expand current memory
3092       if (BOOST_LIKELY(n <= (this->m_holder.capacity() - this->m_holder.m_size))){
3093          //Expand forward
3094          this->priv_insert_forward_range_expand_forward
3095             (p, n, insert_range_proxy, dtl::bool_<dtl::is_single_value_proxy<InsertionProxy>::value>());
3096          return iterator(pos);
3097       }
3098       else{
3099          return this->priv_insert_forward_range_no_capacity(p, n, insert_range_proxy, alloc_version());
3100       }
3101    }
3102 
3103    template <class U>
3104    void priv_resize(const size_type new_size, const U &u, version_0)
3105    {
3106       const size_type sz = this->m_holder.m_size;
3107       if (new_size > this->capacity()){
3108          //This will trigger an error
3109          alloc_holder_t::on_capacity_overflow();
3110       }
3111       else if (new_size < sz){
3112          //Destroy last elements
3113          this->priv_destroy_last_n(sz - new_size);
3114       }
3115       else{
3116          T* const old_finish = this->priv_raw_end();
3117          this->priv_resize_proxy(u).uninitialized_copy_n_and_update(this->m_holder.alloc(), old_finish, new_size - sz);
3118          this->m_holder.set_stored_size(new_size);
3119       }
3120    }
3121 
3122    template <class U, class AllocVersion>
3123    void priv_resize(const size_type new_size, const U &u, AllocVersion)
3124    {
3125       const size_type sz = this->m_holder.m_size;
3126       if (new_size < sz){
3127          //Destroy last elements
3128          this->priv_destroy_last_n(size_type(sz - new_size));
3129       }
3130       else {
3131          this->priv_insert_forward_range(this->back_ptr(), size_type(new_size - sz), this->priv_resize_proxy(u));
3132       }
3133    }
3134 
3135    //Takes the range pointed by [first_pos, last_pos) and shifts it to the right
3136    //by 'shift_count'. 'limit_pos' marks the end of constructed elements.
3137    //
3138    //Precondition: first_pos <= last_pos <= limit_pos
3139    //
3140    //The shift operation might cross limit_pos so elements to moved beyond limit_pos
3141    //are uninitialized_moved with an allocator. Other elements are moved.
3142    //
3143    //The shift operation might left uninitialized elements after limit_pos
3144    //and the number of uninitialized elements is returned by the function.
3145    //
3146    //Old situation:
3147    //       first_pos   last_pos         old_limit
3148    //             |       |                  |
3149    // ____________V_______V__________________V_____________
3150    //|   prefix   | range |     suffix       |raw_mem      ~
3151    //|____________|_______|__________________|_____________~
3152    //
3153    //New situation in Case A (hole_size == 0):
3154    // range is moved through move assignments
3155    //
3156    //       first_pos   last_pos         limit_pos
3157    //             |       |                  |
3158    // ____________V_______V__________________V_____________
3159    //|   prefix'  |       |  | range |suffix'|raw_mem      ~
3160    //|________________+______|___^___|_______|_____________~
3161    //                 |          |
3162    //                 |_>_>_>_>_>^
3163    //
3164    //
3165    //New situation in Case B (hole_size >= 0):
3166    // range is moved through uninitialized moves
3167    //
3168    //       first_pos   last_pos         limit_pos
3169    //             |       |                  |
3170    // ____________V_______V__________________V________________
3171    //|    prefix' |       |                  | [hole] | range |
3172    //|_______________________________________|________|___^___|
3173    //                 |                                   |
3174    //                 |_>_>_>_>_>_>_>_>_>_>_>_>_>_>_>_>_>_^
3175    //
3176    //New situation in Case C (hole_size == 0):
3177    // range is moved through move assignments and uninitialized moves
3178    //
3179    //       first_pos   last_pos         limit_pos
3180    //             |       |                  |
3181    // ____________V_______V__________________V___
3182    //|   prefix'  |       |              | range |
3183    //|___________________________________|___^___|
3184    //                 |                      |
3185    //                 |_>_>_>_>_>_>_>_>_>_>_>^
3186    size_type priv_insert_ordered_at_shift_range
3187       (size_type first_pos, size_type last_pos, size_type limit_pos, size_type shift_count)
3188    {
3189       BOOST_ASSERT(first_pos <= last_pos);
3190       BOOST_ASSERT(last_pos <= limit_pos);
3191       //
3192       T* const begin_ptr = this->priv_raw_begin();
3193       T* const first_ptr = begin_ptr + first_pos;
3194       T* const last_ptr  = begin_ptr + last_pos;
3195 
3196       size_type hole_size = 0;
3197       //Case A:
3198       if((last_pos + shift_count) <= limit_pos){
3199          //All move assigned
3200          boost::container::move_backward(first_ptr, last_ptr, last_ptr + shift_count);
3201       }
3202       //Case B:
3203       else if((first_pos + shift_count) >= limit_pos){
3204          //All uninitialized_moved
3205          ::boost::container::uninitialized_move_alloc
3206             (this->m_holder.alloc(), first_ptr, last_ptr, first_ptr + shift_count);
3207          //Cast in case size_type is narrower than int, promotions are applied
3208          //and Wconversion is in place
3209          hole_size = static_cast<size_type>(first_pos + shift_count - limit_pos);
3210       }
3211       //Case C:
3212       else{
3213          //Some uninitialized_moved
3214          T* const limit_ptr    = begin_ptr + limit_pos;
3215          T* const boundary_ptr = limit_ptr - shift_count;
3216          ::boost::container::uninitialized_move_alloc(this->m_holder.alloc(), boundary_ptr, last_ptr, limit_ptr);
3217          //The rest is move assigned
3218          boost::container::move_backward(first_ptr, boundary_ptr, limit_ptr);
3219       }
3220       return hole_size;
3221    }
3222 
3223    private:
3224    inline T *priv_raw_begin() const
3225    {  return boost::movelib::to_raw_pointer(m_holder.start());  }
3226 
3227    inline T* priv_raw_end() const
3228    {  return this->priv_raw_begin() + this->m_holder.m_size;  }
3229 
3230    template <class InsertionProxy>  //inline single-element version as it is significantly smaller
3231    inline void priv_insert_forward_range_expand_forward
3232       (T* const raw_pos, const size_type, InsertionProxy insert_range_proxy, dtl::true_type)
3233    {
3234       BOOST_ASSERT(this->room_enough());
3235       //There is enough memory
3236       T* const old_finish = this->priv_raw_end();
3237       allocator_type & a = this->m_holder.alloc();
3238 
3239       if (old_finish == raw_pos){
3240          insert_range_proxy.uninitialized_copy_n_and_update(a, old_finish, 1);
3241          ++this->m_holder.m_size;
3242       }
3243       else{
3244          //New elements can be just copied.
3245          //Move to uninitialized memory last objects
3246          T * const before_old_finish = old_finish-1;
3247 
3248          allocator_traits_type::construct(a, old_finish, ::boost::move(*before_old_finish));
3249          ++this->m_holder.m_size;
3250          //Copy previous to last objects to the initialized end
3251          boost::container::move_backward(raw_pos, before_old_finish, old_finish);
3252          //Insert new objects in the raw_pos
3253          insert_range_proxy.copy_n_and_update(a, raw_pos, 1);
3254       }
3255    }
3256 
3257    template <class InsertionProxy>
3258    inline void priv_insert_forward_range_expand_forward
3259       (T* const raw_pos, const size_type n, InsertionProxy insert_range_proxy, dtl::false_type)
3260    {
3261       //There is enough memory
3262       boost::container::expand_forward_and_insert_alloc
3263          ( this->m_holder.alloc(), raw_pos, this->priv_raw_end(), n, insert_range_proxy);
3264       this->m_holder.inc_stored_size(n);
3265    }
3266 
3267    template <class InsertionProxy>
3268    void priv_insert_forward_range_new_allocation
3269       (T* const new_start, size_type new_cap, T* const pos, const size_type n, InsertionProxy insert_range_proxy)
3270    {
3271       //n can be zero, if we want to reallocate!
3272       allocator_type &a =  this->m_holder.alloc();
3273       T * const raw_old_buffer = this->priv_raw_begin();
3274 
3275       typename value_traits::ArrayDeallocator new_buffer_deallocator(new_start, a, new_cap);
3276       boost::container::uninitialized_move_and_insert_alloc
3277          (a, raw_old_buffer, pos, this->priv_raw_end(), new_start, n, insert_range_proxy);
3278       new_buffer_deallocator.release();
3279 
3280       //Destroy and deallocate old elements
3281       if(raw_old_buffer){
3282          BOOST_IF_CONSTEXPR(!has_trivial_destructor_after_move<value_type>::value)
3283             boost::container::destroy_alloc_n(a, raw_old_buffer, this->m_holder.m_size);
3284          this->m_holder.deallocate(this->m_holder.start(), this->m_holder.capacity());
3285       }
3286 
3287       this->m_holder.start(new_start);
3288       this->m_holder.inc_stored_size(n);
3289       this->m_holder.capacity(new_cap);
3290    }
3291 
3292    template <class InsertionProxy>
3293    void priv_insert_forward_range_expand_backwards
3294          (T* const new_start, const size_type new_capacity,
3295           T* const pos, const size_type n, InsertionProxy insert_range_proxy)
3296    {
3297       T* const old_start = this->priv_raw_begin();
3298       const size_type old_size = this->m_holder.m_size;
3299       allocator_type& a = this->m_holder.alloc();
3300 
3301       //Update the vector buffer information to a safe state
3302       this->m_holder.start(new_start);
3303       this->m_holder.capacity(new_capacity);
3304       this->m_holder.m_size = 0;
3305 
3306       expand_backward_forward_and_insert_alloc(old_start, old_size, new_start, pos, n, insert_range_proxy, a);
3307 
3308       //Update the vector buffer information to a safe state
3309       this->m_holder.m_size = stored_size_type(old_size + n);
3310    }
3311 
3312    void priv_throw_if_out_of_range(size_type n) const
3313    {
3314       //If n is out of range, throw an out_of_range exception
3315       if (n >= this->size()){
3316          throw_out_of_range("vector::at out of range");
3317       }
3318    }
3319 
3320    inline bool priv_in_range(const_iterator pos) const
3321    {
3322       return (this->begin() <= pos) && (pos < this->end());
3323    }
3324 
3325    inline bool priv_in_range_or_end(const_iterator pos) const
3326    {
3327       return (this->begin() <= pos) && (pos <= this->end());
3328    }
3329 
3330    #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
3331    public:
3332    unsigned int num_expand_fwd;
3333    unsigned int num_expand_bwd;
3334    unsigned int num_shrink;
3335    unsigned int num_alloc;
3336    void reset_alloc_stats()
3337    {  num_expand_fwd = num_expand_bwd = num_alloc = 0, num_shrink = 0;   }
3338    #endif
3339    #endif   //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
3340 };
3341 
3342 #ifndef BOOST_CONTAINER_NO_CXX17_CTAD
3343 
3344 template <typename InputIterator>
3345 vector(InputIterator, InputIterator) ->
3346    vector<typename iter_value<InputIterator>::type>;
3347 
3348 template <typename InputIterator, typename Allocator>
3349 vector(InputIterator, InputIterator, Allocator const&) ->
3350    vector<typename iter_value<InputIterator>::type, Allocator>;
3351 
3352 #endif
3353 
3354 
3355 }} //namespace boost::container
3356 
3357 #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
3358 
3359 namespace boost {
3360 
3361 //!has_trivial_destructor_after_move<> == true_type
3362 //!specialization for optimizations
3363 template <class T, class Allocator, class Options>
3364 struct has_trivial_destructor_after_move<boost::container::vector<T, Allocator, Options> >
3365 {
3366    typedef typename boost::container::vector<T, Allocator, Options>::allocator_type allocator_type;
3367    typedef typename ::boost::container::allocator_traits<allocator_type>::pointer pointer;
3368    BOOST_STATIC_CONSTEXPR bool value = ::boost::has_trivial_destructor_after_move<allocator_type>::value &&
3369                                                 ::boost::has_trivial_destructor_after_move<pointer>::value;
3370 };
3371 
3372 }
3373 
3374 //See comments on vec_iterator::element_type to know why is this needed
3375 #ifdef BOOST_GNU_STDLIB
3376 
3377 #include <boost/move/detail/std_ns_begin.hpp>
3378 
3379 BOOST_MOVE_STD_NS_BEG
3380 
3381 template <class Pointer, bool IsConst>
3382 struct pointer_traits< boost::container::vec_iterator<Pointer, IsConst> >
3383    : public boost::intrusive::pointer_traits< boost::container::vec_iterator<Pointer, IsConst> >
3384 {};
3385 
3386 BOOST_MOVE_STD_NS_END
3387 
3388 #include <boost/move/detail/std_ns_end.hpp>
3389 
3390 #endif   //BOOST_GNU_STDLIB
3391 
3392 #endif   //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
3393 
3394 #include <boost/container/detail/config_end.hpp>
3395 
3396 #endif //   #ifndef  BOOST_CONTAINER_CONTAINER_VECTOR_HPP