• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //////////////////////////////////////////////////////////////////////////////
2 //
3 // (C) Copyright Ion Gaztanaga 2005-2015. Distributed under the Boost
4 // Software License, Version 1.0. (See accompanying file
5 // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6 //
7 // See http://www.boost.org/libs/container for documentation.
8 //
9 //////////////////////////////////////////////////////////////////////////////
10 
11 #ifndef BOOST_CONTAINER_CONTAINER_VECTOR_HPP
12 #define BOOST_CONTAINER_CONTAINER_VECTOR_HPP
13 
14 #ifndef BOOST_CONFIG_HPP
15 #  include <boost/config.hpp>
16 #endif
17 
18 #if defined(BOOST_HAS_PRAGMA_ONCE)
19 #  pragma once
20 #endif
21 
22 #include <boost/container/detail/config_begin.hpp>
23 #include <boost/container/detail/workaround.hpp>
24 
25 // container
26 #include <boost/container/container_fwd.hpp>
27 #include <boost/container/allocator_traits.hpp>
28 #include <boost/container/new_allocator.hpp> //new_allocator
29 #include <boost/container/throw_exception.hpp>
30 #include <boost/container/options.hpp>
31 // container detail
32 #include <boost/container/detail/advanced_insert_int.hpp>
33 #include <boost/container/detail/algorithm.hpp> //equal()
34 #include <boost/container/detail/alloc_helpers.hpp>
35 #include <boost/container/detail/allocation_type.hpp>
36 #include <boost/container/detail/copy_move_algo.hpp>
37 #include <boost/container/detail/destroyers.hpp>
38 #include <boost/container/detail/iterator.hpp>
39 #include <boost/container/detail/iterators.hpp>
40 #include <boost/move/detail/iterator_to_raw_pointer.hpp>
41 #include <boost/container/detail/mpl.hpp>
42 #include <boost/container/detail/next_capacity.hpp>
43 #include <boost/container/detail/value_functors.hpp>
44 #include <boost/move/detail/to_raw_pointer.hpp>
45 #include <boost/container/detail/type_traits.hpp>
46 #include <boost/container/detail/version_type.hpp>
47 // intrusive
48 #include <boost/intrusive/pointer_traits.hpp>
49 // move
50 #include <boost/move/adl_move_swap.hpp>
51 #include <boost/move/iterator.hpp>
52 #include <boost/move/traits.hpp>
53 #include <boost/move/utility_core.hpp>
54 // move/detail
55 #if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
56 #include <boost/move/detail/fwd_macros.hpp>
57 #endif
58 #include <boost/move/detail/move_helpers.hpp>
59 // move/algo
60 #include <boost/move/algo/adaptive_merge.hpp>
61 #include <boost/move/algo/unique.hpp>
62 #include <boost/move/algo/predicate.hpp>
63 #include <boost/move/algo/detail/set_difference.hpp>
64 // other
65 #include <boost/core/no_exceptions_support.hpp>
66 #include <boost/assert.hpp>
67 #include <boost/cstdint.hpp>
68 
69 //std
70 #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
71 #include <initializer_list>   //for std::initializer_list
72 #endif
73 
74 namespace boost {
75 namespace container {
76 
77 #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
78 
79 
80 template <class Pointer, bool IsConst>
81 class vec_iterator
82 {
83    public:
84    typedef std::random_access_iterator_tag                                          iterator_category;
85    typedef typename boost::intrusive::pointer_traits<Pointer>::element_type         value_type;
86    typedef typename boost::intrusive::pointer_traits<Pointer>::difference_type      difference_type;
87    typedef typename dtl::if_c
88       < IsConst
89       , typename boost::intrusive::pointer_traits<Pointer>::template
90                                  rebind_pointer<const value_type>::type
91       , Pointer
92       >::type                                                                       pointer;
93    typedef typename boost::intrusive::pointer_traits<pointer>                       ptr_traits;
94    typedef typename ptr_traits::reference                                           reference;
95 
96    #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
97    private:
98    Pointer m_ptr;
99 
100    class nat
101    {
102       public:
get_ptr() const103       Pointer get_ptr() const
104       { return Pointer();  }
105    };
106    typedef typename dtl::if_c< IsConst
107                              , vec_iterator<Pointer, false>
108                              , nat>::type                                           nonconst_iterator;
109 
110    public:
get_ptr() const111    BOOST_CONTAINER_FORCEINLINE const Pointer &get_ptr() const BOOST_NOEXCEPT_OR_NOTHROW
112    {  return   m_ptr;  }
113 
get_ptr()114    BOOST_CONTAINER_FORCEINLINE Pointer &get_ptr() BOOST_NOEXCEPT_OR_NOTHROW
115    {  return   m_ptr;  }
116 
vec_iterator(Pointer ptr)117    BOOST_CONTAINER_FORCEINLINE explicit vec_iterator(Pointer ptr) BOOST_NOEXCEPT_OR_NOTHROW
118       : m_ptr(ptr)
119    {}
120    #endif   //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
121 
122    public:
123 
124    //Constructors
vec_iterator()125    BOOST_CONTAINER_FORCEINLINE vec_iterator() BOOST_NOEXCEPT_OR_NOTHROW
126       : m_ptr()   //Value initialization to achieve "null iterators" (N3644)
127    {}
128 
vec_iterator(const vec_iterator & other)129    BOOST_CONTAINER_FORCEINLINE vec_iterator(const vec_iterator& other) BOOST_NOEXCEPT_OR_NOTHROW
130       :  m_ptr(other.get_ptr())
131    {}
132 
vec_iterator(const nonconst_iterator & other)133    BOOST_CONTAINER_FORCEINLINE vec_iterator(const nonconst_iterator &other) BOOST_NOEXCEPT_OR_NOTHROW
134       :  m_ptr(other.get_ptr())
135    {}
136 
operator =(const vec_iterator & other)137    BOOST_CONTAINER_FORCEINLINE vec_iterator & operator=(const vec_iterator& other) BOOST_NOEXCEPT_OR_NOTHROW
138    {  m_ptr = other.get_ptr();   return *this;  }
139 
140    //Pointer like operators
operator *() const141    BOOST_CONTAINER_FORCEINLINE reference operator*()   const BOOST_NOEXCEPT_OR_NOTHROW
142    {  BOOST_ASSERT(!!m_ptr);  return *m_ptr;  }
143 
operator ->() const144    BOOST_CONTAINER_FORCEINLINE pointer operator->()  const BOOST_NOEXCEPT_OR_NOTHROW
145    {  return m_ptr;  }
146 
operator [](difference_type off) const147    BOOST_CONTAINER_FORCEINLINE reference operator[](difference_type off) const BOOST_NOEXCEPT_OR_NOTHROW
148    {  BOOST_ASSERT(!!m_ptr);  return m_ptr[off];  }
149 
150    //Increment / Decrement
operator ++()151    BOOST_CONTAINER_FORCEINLINE vec_iterator& operator++() BOOST_NOEXCEPT_OR_NOTHROW
152    {  BOOST_ASSERT(!!m_ptr); ++m_ptr;  return *this; }
153 
operator ++(int)154    BOOST_CONTAINER_FORCEINLINE vec_iterator operator++(int) BOOST_NOEXCEPT_OR_NOTHROW
155    {  BOOST_ASSERT(!!m_ptr); return vec_iterator(m_ptr++); }
156 
operator --()157    BOOST_CONTAINER_FORCEINLINE vec_iterator& operator--() BOOST_NOEXCEPT_OR_NOTHROW
158    {  BOOST_ASSERT(!!m_ptr); --m_ptr; return *this;  }
159 
operator --(int)160    BOOST_CONTAINER_FORCEINLINE vec_iterator operator--(int) BOOST_NOEXCEPT_OR_NOTHROW
161    {  BOOST_ASSERT(!!m_ptr); return vec_iterator(m_ptr--); }
162 
163    //Arithmetic
operator +=(difference_type off)164    BOOST_CONTAINER_FORCEINLINE vec_iterator& operator+=(difference_type off) BOOST_NOEXCEPT_OR_NOTHROW
165    {  BOOST_ASSERT(m_ptr || !off); m_ptr += off; return *this;   }
166 
operator -=(difference_type off)167    BOOST_CONTAINER_FORCEINLINE vec_iterator& operator-=(difference_type off) BOOST_NOEXCEPT_OR_NOTHROW
168    {  BOOST_ASSERT(m_ptr || !off); m_ptr -= off; return *this;   }
169 
operator +(const vec_iterator & x,difference_type off)170    BOOST_CONTAINER_FORCEINLINE friend vec_iterator operator+(const vec_iterator &x, difference_type off) BOOST_NOEXCEPT_OR_NOTHROW
171    {  BOOST_ASSERT(x.m_ptr || !off); return vec_iterator(x.m_ptr+off);  }
172 
operator +(difference_type off,vec_iterator right)173    BOOST_CONTAINER_FORCEINLINE friend vec_iterator operator+(difference_type off, vec_iterator right) BOOST_NOEXCEPT_OR_NOTHROW
174    {  BOOST_ASSERT(right.m_ptr || !off); right.m_ptr += off;  return right; }
175 
operator -(vec_iterator left,difference_type off)176    BOOST_CONTAINER_FORCEINLINE friend vec_iterator operator-(vec_iterator left, difference_type off) BOOST_NOEXCEPT_OR_NOTHROW
177    {  BOOST_ASSERT(left.m_ptr || !off); left.m_ptr -= off;  return left; }
178 
operator -(const vec_iterator & left,const vec_iterator & right)179    BOOST_CONTAINER_FORCEINLINE friend difference_type operator-(const vec_iterator &left, const vec_iterator& right) BOOST_NOEXCEPT_OR_NOTHROW
180    {  return left.m_ptr - right.m_ptr;   }
181 
182    //Comparison operators
operator ==(const vec_iterator & l,const vec_iterator & r)183    BOOST_CONTAINER_FORCEINLINE friend bool operator==   (const vec_iterator& l, const vec_iterator& r) BOOST_NOEXCEPT_OR_NOTHROW
184    {  return l.m_ptr == r.m_ptr;  }
185 
operator !=(const vec_iterator & l,const vec_iterator & r)186    BOOST_CONTAINER_FORCEINLINE friend bool operator!=   (const vec_iterator& l, const vec_iterator& r) BOOST_NOEXCEPT_OR_NOTHROW
187    {  return l.m_ptr != r.m_ptr;  }
188 
operator <(const vec_iterator & l,const vec_iterator & r)189    BOOST_CONTAINER_FORCEINLINE friend bool operator<    (const vec_iterator& l, const vec_iterator& r) BOOST_NOEXCEPT_OR_NOTHROW
190    {  return l.m_ptr < r.m_ptr;  }
191 
operator <=(const vec_iterator & l,const vec_iterator & r)192    BOOST_CONTAINER_FORCEINLINE friend bool operator<=   (const vec_iterator& l, const vec_iterator& r) BOOST_NOEXCEPT_OR_NOTHROW
193    {  return l.m_ptr <= r.m_ptr;  }
194 
operator >(const vec_iterator & l,const vec_iterator & r)195    BOOST_CONTAINER_FORCEINLINE friend bool operator>    (const vec_iterator& l, const vec_iterator& r) BOOST_NOEXCEPT_OR_NOTHROW
196    {  return l.m_ptr > r.m_ptr;  }
197 
operator >=(const vec_iterator & l,const vec_iterator & r)198    BOOST_CONTAINER_FORCEINLINE friend bool operator>=   (const vec_iterator& l, const vec_iterator& r) BOOST_NOEXCEPT_OR_NOTHROW
199    {  return l.m_ptr >= r.m_ptr;  }
200 };
201 
202 template<class BiDirPosConstIt, class BiDirValueIt>
203 struct vector_insert_ordered_cursor
204 {
205    typedef typename iterator_traits<BiDirPosConstIt>::value_type  size_type;
206    typedef typename iterator_traits<BiDirValueIt>::reference      reference;
207 
vector_insert_ordered_cursorboost::container::vector_insert_ordered_cursor208    BOOST_CONTAINER_FORCEINLINE vector_insert_ordered_cursor(BiDirPosConstIt posit, BiDirValueIt valueit)
209       : last_position_it(posit), last_value_it(valueit)
210    {}
211 
operator --boost::container::vector_insert_ordered_cursor212    void operator --()
213    {
214       --last_value_it;
215       --last_position_it;
216       while(this->get_pos() == size_type(-1)){
217          --last_value_it;
218          --last_position_it;
219       }
220    }
221 
get_posboost::container::vector_insert_ordered_cursor222    BOOST_CONTAINER_FORCEINLINE size_type get_pos() const
223    {  return *last_position_it;  }
224 
get_valboost::container::vector_insert_ordered_cursor225    BOOST_CONTAINER_FORCEINLINE reference get_val()
226    {  return *last_value_it;  }
227 
228    BiDirPosConstIt last_position_it;
229    BiDirValueIt last_value_it;
230 };
231 
232 struct initial_capacity_t{};
233 
234 template<class Pointer, bool IsConst>
vector_iterator_get_ptr(const vec_iterator<Pointer,IsConst> & it)235 BOOST_CONTAINER_FORCEINLINE const Pointer &vector_iterator_get_ptr(const vec_iterator<Pointer, IsConst> &it) BOOST_NOEXCEPT_OR_NOTHROW
236 {  return   it.get_ptr();  }
237 
238 template<class Pointer, bool IsConst>
get_ptr(vec_iterator<Pointer,IsConst> & it)239 BOOST_CONTAINER_FORCEINLINE Pointer &get_ptr(vec_iterator<Pointer, IsConst> &it) BOOST_NOEXCEPT_OR_NOTHROW
240 {  return  it.get_ptr();  }
241 
242 struct vector_uninitialized_size_t {};
243 static const vector_uninitialized_size_t vector_uninitialized_size = vector_uninitialized_size_t();
244 
245 template <class T>
246 struct vector_value_traits_base
247 {
248    static const bool trivial_dctr = dtl::is_trivially_destructible<T>::value;
249    static const bool trivial_dctr_after_move = has_trivial_destructor_after_move<T>::value;
250    static const bool trivial_copy = dtl::is_trivially_copy_constructible<T>::value;
251    static const bool nothrow_copy = dtl::is_nothrow_copy_constructible<T>::value || trivial_copy;
252    static const bool trivial_assign = dtl::is_trivially_copy_assignable<T>::value;
253    static const bool nothrow_assign = dtl::is_nothrow_copy_assignable<T>::value || trivial_assign;
254 };
255 
256 template <class Allocator>
257 struct vector_value_traits
258    : public vector_value_traits_base<typename Allocator::value_type>
259 {
260    typedef vector_value_traits_base<typename Allocator::value_type> base_t;
261    //This is the anti-exception array destructor
262    //to deallocate values already constructed
263    typedef typename dtl::if_c
264       <base_t::trivial_dctr
265       ,dtl::null_scoped_destructor_n<Allocator>
266       ,dtl::scoped_destructor_n<Allocator>
267       >::type   ArrayDestructor;
268    //This is the anti-exception array deallocator
269    typedef dtl::scoped_array_deallocator<Allocator> ArrayDeallocator;
270 };
271 
272 //!This struct deallocates and allocated memory
273 template < class Allocator
274          , class StoredSizeType
275          , class AllocatorVersion = typename dtl::version<Allocator>::type
276          >
277 struct vector_alloc_holder
278    : public Allocator
279 {
280    private:
281    BOOST_MOVABLE_BUT_NOT_COPYABLE(vector_alloc_holder)
282 
283    public:
284    typedef Allocator                                           allocator_type;
285    typedef StoredSizeType                                      stored_size_type;
286    typedef boost::container::allocator_traits<allocator_type>  allocator_traits_type;
287    typedef typename allocator_traits_type::pointer             pointer;
288    typedef typename allocator_traits_type::size_type           size_type;
289    typedef typename allocator_traits_type::value_type          value_type;
290 
is_propagable_fromboost::container::vector_alloc_holder291    BOOST_CONTAINER_FORCEINLINE static bool is_propagable_from(const allocator_type &from_alloc, pointer p, const allocator_type &to_alloc, bool const propagate_allocator)
292    {
293       (void)propagate_allocator; (void)p; (void)to_alloc; (void)from_alloc;
294       const bool all_storage_propagable = !allocator_traits_type::is_partially_propagable::value ||
295                                           !allocator_traits_type::storage_is_unpropagable(from_alloc, p);
296       return all_storage_propagable && (propagate_allocator || allocator_traits_type::equal(from_alloc, to_alloc));
297    }
298 
are_swap_propagableboost::container::vector_alloc_holder299    BOOST_CONTAINER_FORCEINLINE static bool are_swap_propagable(const allocator_type &l_a, pointer l_p, const allocator_type &r_a, pointer r_p, bool const propagate_allocator)
300    {
301       (void)propagate_allocator; (void)l_p; (void)r_p; (void)l_a; (void)r_a;
302       const bool all_storage_propagable = !allocator_traits_type::is_partially_propagable::value ||
303               !(allocator_traits_type::storage_is_unpropagable(l_a, l_p) || allocator_traits_type::storage_is_unpropagable(r_a, r_p));
304       return all_storage_propagable && (propagate_allocator || allocator_traits_type::equal(l_a, r_a));
305    }
306 
307    //Constructor, does not throw
308    vector_alloc_holder()
BOOST_NOEXCEPT_IFboost::container::vector_alloc_holder309       BOOST_NOEXCEPT_IF(dtl::is_nothrow_default_constructible<allocator_type>::value)
310       : allocator_type(), m_start(), m_size(), m_capacity()
311    {}
312 
313    //Constructor, does not throw
314    template<class AllocConvertible>
vector_alloc_holderboost::container::vector_alloc_holder315    explicit vector_alloc_holder(BOOST_FWD_REF(AllocConvertible) a) BOOST_NOEXCEPT_OR_NOTHROW
316       : allocator_type(boost::forward<AllocConvertible>(a)), m_start(), m_size(), m_capacity()
317    {}
318 
319    //Constructor, does not throw
320    template<class AllocConvertible>
vector_alloc_holderboost::container::vector_alloc_holder321    vector_alloc_holder(vector_uninitialized_size_t, BOOST_FWD_REF(AllocConvertible) a, size_type initial_size)
322       : allocator_type(boost::forward<AllocConvertible>(a))
323       , m_start()
324       //Size is initialized here so vector should only call uninitialized_xxx after this
325       , m_size(static_cast<stored_size_type>(initial_size))
326       , m_capacity()
327    {
328       if(initial_size){
329          pointer reuse = pointer();
330          size_type final_cap = initial_size;
331          m_start = this->allocation_command(allocate_new, initial_size, final_cap, reuse);
332          m_capacity = static_cast<stored_size_type>(final_cap);
333       }
334    }
335 
336    //Constructor, does not throw
vector_alloc_holderboost::container::vector_alloc_holder337    vector_alloc_holder(vector_uninitialized_size_t, size_type initial_size)
338       : allocator_type()
339       , m_start()
340       //Size is initialized here so vector should only call uninitialized_xxx after this
341       , m_size(static_cast<stored_size_type>(initial_size))
342       , m_capacity()
343    {
344       if(initial_size){
345          pointer reuse = pointer();
346          size_type final_cap = initial_size;
347          m_start = this->allocation_command(allocate_new, initial_size, final_cap, reuse);
348          m_capacity = static_cast<stored_size_type>(final_cap);
349       }
350    }
351 
vector_alloc_holderboost::container::vector_alloc_holder352    vector_alloc_holder(BOOST_RV_REF(vector_alloc_holder) holder) BOOST_NOEXCEPT_OR_NOTHROW
353       : allocator_type(BOOST_MOVE_BASE(allocator_type, holder))
354       , m_start(holder.m_start)
355       , m_size(holder.m_size)
356       , m_capacity(holder.m_capacity)
357    {
358       holder.m_start = pointer();
359       holder.m_size = holder.m_capacity = 0;
360    }
361 
vector_alloc_holderboost::container::vector_alloc_holder362    vector_alloc_holder(initial_capacity_t, pointer p, size_type n)
363       BOOST_NOEXCEPT_IF(dtl::is_nothrow_default_constructible<allocator_type>::value)
364       : allocator_type()
365       , m_start(p)
366       , m_size()
367       //n is guaranteed to fit into stored_size_type
368       , m_capacity(static_cast<stored_size_type>(n))
369    {}
370 
371    template<class AllocFwd>
vector_alloc_holderboost::container::vector_alloc_holder372    vector_alloc_holder(initial_capacity_t, pointer p, size_type n, BOOST_FWD_REF(AllocFwd) a)
373       : allocator_type(::boost::forward<AllocFwd>(a))
374       , m_start(p)
375       , m_size()
376       , m_capacity(n)
377    {}
378 
~vector_alloc_holderboost::container::vector_alloc_holder379    BOOST_CONTAINER_FORCEINLINE ~vector_alloc_holder() BOOST_NOEXCEPT_OR_NOTHROW
380    {
381       if(this->m_capacity){
382          this->deallocate(this->m_start, this->m_capacity);
383       }
384    }
385 
allocation_commandboost::container::vector_alloc_holder386    BOOST_CONTAINER_FORCEINLINE pointer allocation_command(boost::container::allocation_type command,
387                               size_type limit_size, size_type &prefer_in_recvd_out_size, pointer &reuse)
388    {
389       typedef typename dtl::version<allocator_type>::type alloc_version;
390       return this->priv_allocation_command(alloc_version(), command, limit_size, prefer_in_recvd_out_size, reuse);
391    }
392 
allocateboost::container::vector_alloc_holder393    BOOST_CONTAINER_FORCEINLINE pointer allocate(size_type n)
394    {
395       const size_type max_alloc = allocator_traits_type::max_size(this->alloc());
396       const size_type max = max_alloc <= stored_size_type(-1) ? max_alloc : stored_size_type(-1);
397       if ( max < n )
398          boost::container::throw_length_error("get_next_capacity, allocator's max size reached");
399 
400       return allocator_traits_type::allocate(this->alloc(), n);
401    }
402 
deallocateboost::container::vector_alloc_holder403    BOOST_CONTAINER_FORCEINLINE void deallocate(const pointer &p, size_type n)
404    {
405       allocator_traits_type::deallocate(this->alloc(), p, n);
406    }
407 
try_expand_fwdboost::container::vector_alloc_holder408    bool try_expand_fwd(size_type at_least)
409    {
410       //There is not enough memory, try to expand the old one
411       const size_type new_cap = this->capacity() + at_least;
412       size_type real_cap = new_cap;
413       pointer reuse = this->start();
414       bool const success = !!this->allocation_command(expand_fwd, new_cap, real_cap, reuse);
415       //Check for forward expansion
416       if(success){
417          #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
418          ++this->num_expand_fwd;
419          #endif
420          this->capacity(real_cap);
421       }
422       return success;
423    }
424 
425    template<class GrowthFactorType>
next_capacityboost::container::vector_alloc_holder426    size_type next_capacity(size_type additional_objects) const
427    {
428       BOOST_ASSERT(additional_objects > size_type(this->m_capacity - this->m_size));
429       size_type max = allocator_traits_type::max_size(this->alloc());
430       (clamp_by_stored_size_type)(max, stored_size_type());
431       const size_type remaining_cap = max - size_type(this->m_capacity);
432       const size_type min_additional_cap = additional_objects - size_type(this->m_capacity - this->m_size);
433 
434       if ( remaining_cap < min_additional_cap )
435          boost::container::throw_length_error("get_next_capacity, allocator's max size reached");
436 
437       return GrowthFactorType()( size_type(this->m_capacity), min_additional_cap, max);
438    }
439 
440    pointer           m_start;
441    stored_size_type  m_size;
442    stored_size_type  m_capacity;
443 
swap_resourcesboost::container::vector_alloc_holder444    void swap_resources(vector_alloc_holder &x) BOOST_NOEXCEPT_OR_NOTHROW
445    {
446       boost::adl_move_swap(this->m_start, x.m_start);
447       boost::adl_move_swap(this->m_size, x.m_size);
448       boost::adl_move_swap(this->m_capacity, x.m_capacity);
449    }
450 
steal_resourcesboost::container::vector_alloc_holder451    void steal_resources(vector_alloc_holder &x) BOOST_NOEXCEPT_OR_NOTHROW
452    {
453       this->m_start     = x.m_start;
454       this->m_size      = x.m_size;
455       this->m_capacity  = x.m_capacity;
456       x.m_start = pointer();
457       x.m_size = x.m_capacity = 0;
458    }
459 
allocboost::container::vector_alloc_holder460    BOOST_CONTAINER_FORCEINLINE allocator_type &alloc() BOOST_NOEXCEPT_OR_NOTHROW
461    {  return *this;  }
462 
allocboost::container::vector_alloc_holder463    BOOST_CONTAINER_FORCEINLINE const allocator_type &alloc() const BOOST_NOEXCEPT_OR_NOTHROW
464    {  return *this;  }
465 
startboost::container::vector_alloc_holder466    BOOST_CONTAINER_FORCEINLINE const pointer   &start() const     BOOST_NOEXCEPT_OR_NOTHROW
467       {  return m_start;  }
capacityboost::container::vector_alloc_holder468    BOOST_CONTAINER_FORCEINLINE       size_type capacity() const     BOOST_NOEXCEPT_OR_NOTHROW
469       {  return m_capacity;  }
startboost::container::vector_alloc_holder470    BOOST_CONTAINER_FORCEINLINE void start(const pointer &p)       BOOST_NOEXCEPT_OR_NOTHROW
471       {  m_start = p;  }
capacityboost::container::vector_alloc_holder472    BOOST_CONTAINER_FORCEINLINE void capacity(const size_type &c)  BOOST_NOEXCEPT_OR_NOTHROW
473       {  BOOST_ASSERT( c <= stored_size_type(-1)); m_capacity = c;  }
474 
on_capacity_overflowboost::container::vector_alloc_holder475    static BOOST_CONTAINER_FORCEINLINE void on_capacity_overflow()
476    { }
477 
478    private:
priv_first_allocationboost::container::vector_alloc_holder479    void priv_first_allocation(size_type cap)
480    {
481       if(cap){
482          pointer reuse = pointer();
483          m_start = this->allocation_command(allocate_new, cap, cap, reuse);
484          m_capacity = cap;
485          #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
486          ++this->num_alloc;
487          #endif
488       }
489    }
490 
clamp_by_stored_size_typeboost::container::vector_alloc_holder491    BOOST_CONTAINER_FORCEINLINE static void clamp_by_stored_size_type(size_type &, size_type)
492    {}
493 
494    template<class SomeStoredSizeType>
clamp_by_stored_size_typeboost::container::vector_alloc_holder495    BOOST_CONTAINER_FORCEINLINE static void clamp_by_stored_size_type(size_type &s, SomeStoredSizeType)
496    {
497       if (s >= SomeStoredSizeType(-1) )
498          s = SomeStoredSizeType(-1);
499    }
500 
priv_allocation_commandboost::container::vector_alloc_holder501    BOOST_CONTAINER_FORCEINLINE pointer priv_allocation_command(version_1, boost::container::allocation_type command,
502                          size_type limit_size,
503                          size_type &prefer_in_recvd_out_size,
504                          pointer &reuse)
505    {
506       (void)command;
507       BOOST_ASSERT( (command & allocate_new));
508       BOOST_ASSERT(!(command & nothrow_allocation));
509       //First detect overflow on smaller stored_size_types
510       if (limit_size > stored_size_type(-1)){
511          boost::container::throw_length_error("get_next_capacity, allocator's max size reached");
512       }
513       (clamp_by_stored_size_type)(prefer_in_recvd_out_size, stored_size_type());
514       pointer const p = this->allocate(prefer_in_recvd_out_size);
515       reuse = pointer();
516       return p;
517    }
518 
priv_allocation_commandboost::container::vector_alloc_holder519    pointer priv_allocation_command(version_2, boost::container::allocation_type command,
520                          size_type limit_size,
521                          size_type &prefer_in_recvd_out_size,
522                          pointer &reuse)
523    {
524       //First detect overflow on smaller stored_size_types
525       if (limit_size > stored_size_type(-1)){
526          boost::container::throw_length_error("get_next_capacity, allocator's max size reached");
527       }
528       (clamp_by_stored_size_type)(prefer_in_recvd_out_size, stored_size_type());
529       //Allocate memory
530       pointer p = this->alloc().allocation_command(command, limit_size, prefer_in_recvd_out_size, reuse);
531       //If after allocation prefer_in_recvd_out_size is not representable by stored_size_type, truncate it.
532       (clamp_by_stored_size_type)(prefer_in_recvd_out_size, stored_size_type());
533       return p;
534    }
535 };
536 
537 //!This struct deallocates and allocated memory
538 template <class Allocator, class StoredSizeType>
539 struct vector_alloc_holder<Allocator, StoredSizeType, version_0>
540    : public Allocator
541 {
542    private:
543    BOOST_MOVABLE_BUT_NOT_COPYABLE(vector_alloc_holder)
544 
545    public:
546    typedef Allocator                                     allocator_type;
547    typedef boost::container::
548       allocator_traits<allocator_type>                   allocator_traits_type;
549    typedef typename allocator_traits_type::pointer       pointer;
550    typedef typename allocator_traits_type::size_type     size_type;
551    typedef typename allocator_traits_type::value_type    value_type;
552    typedef StoredSizeType                                stored_size_type;
553 
554    template <class OtherAllocator, class OtherStoredSizeType, class OtherAllocatorVersion>
555    friend struct vector_alloc_holder;
556 
557    //Constructor, does not throw
558    vector_alloc_holder()
BOOST_NOEXCEPT_IFboost::container::vector_alloc_holder559       BOOST_NOEXCEPT_IF(dtl::is_nothrow_default_constructible<allocator_type>::value)
560       : allocator_type(), m_size()
561    {}
562 
563    //Constructor, does not throw
564    template<class AllocConvertible>
vector_alloc_holderboost::container::vector_alloc_holder565    explicit vector_alloc_holder(BOOST_FWD_REF(AllocConvertible) a) BOOST_NOEXCEPT_OR_NOTHROW
566       : allocator_type(boost::forward<AllocConvertible>(a)), m_size()
567    {}
568 
569    //Constructor, does not throw
570    template<class AllocConvertible>
vector_alloc_holderboost::container::vector_alloc_holder571    vector_alloc_holder(vector_uninitialized_size_t, BOOST_FWD_REF(AllocConvertible) a, size_type initial_size)
572       : allocator_type(boost::forward<AllocConvertible>(a))
573       , m_size(initial_size)  //Size is initialized here...
574    {
575       //... and capacity here, so vector, must call uninitialized_xxx in the derived constructor
576       this->priv_first_allocation(initial_size);
577    }
578 
579    //Constructor, does not throw
vector_alloc_holderboost::container::vector_alloc_holder580    vector_alloc_holder(vector_uninitialized_size_t, size_type initial_size)
581       : allocator_type()
582       , m_size(initial_size)  //Size is initialized here...
583    {
584       //... and capacity here, so vector, must call uninitialized_xxx in the derived constructor
585       this->priv_first_allocation(initial_size);
586    }
587 
vector_alloc_holderboost::container::vector_alloc_holder588    vector_alloc_holder(BOOST_RV_REF(vector_alloc_holder) holder)
589       : allocator_type(BOOST_MOVE_BASE(allocator_type, holder))
590       , m_size(holder.m_size) //Size is initialized here so vector should only call uninitialized_xxx after this
591    {
592       ::boost::container::uninitialized_move_alloc_n
593          (this->alloc(), boost::movelib::to_raw_pointer(holder.start()), m_size, boost::movelib::to_raw_pointer(this->start()));
594       ::boost::container::destroy_alloc_n
595          (this->alloc(), boost::movelib::to_raw_pointer(holder.start()), m_size);
596       holder.m_size = 0;
597    }
598 
599    template<class OtherAllocator, class OtherStoredSizeType, class OtherAllocatorVersion>
vector_alloc_holderboost::container::vector_alloc_holder600    vector_alloc_holder(BOOST_RV_REF_BEG vector_alloc_holder<OtherAllocator, OtherStoredSizeType, OtherAllocatorVersion> BOOST_RV_REF_END holder)
601       : allocator_type()
602       , m_size(holder.m_size) //Initialize it to m_size as first_allocation can only succeed or abort
603    {
604       //Different allocator type so we must check we have enough storage
605       const size_type n = holder.m_size;
606       this->priv_first_allocation(n);
607       ::boost::container::uninitialized_move_alloc_n
608          (this->alloc(), boost::movelib::to_raw_pointer(holder.start()), n, boost::movelib::to_raw_pointer(this->start()));
609    }
610 
on_capacity_overflowboost::container::vector_alloc_holder611    static BOOST_CONTAINER_FORCEINLINE void on_capacity_overflow()
612    {  allocator_type::on_capacity_overflow();  }
613 
priv_first_allocationboost::container::vector_alloc_holder614    BOOST_CONTAINER_FORCEINLINE void priv_first_allocation(size_type cap)
615    {
616       if(cap > allocator_type::internal_capacity){
617          on_capacity_overflow();
618       }
619    }
620 
deep_swapboost::container::vector_alloc_holder621    BOOST_CONTAINER_FORCEINLINE void deep_swap(vector_alloc_holder &x)
622    {
623       this->priv_deep_swap(x);
624    }
625 
626    template<class OtherAllocator, class OtherStoredSizeType, class OtherAllocatorVersion>
deep_swapboost::container::vector_alloc_holder627    void deep_swap(vector_alloc_holder<OtherAllocator, OtherStoredSizeType, OtherAllocatorVersion> &x)
628    {
629       typedef typename real_allocator<value_type, OtherAllocator>::type other_allocator_type;
630       if(this->m_size > other_allocator_type::internal_capacity || x.m_size > allocator_type::internal_capacity){
631          on_capacity_overflow();
632       }
633       this->priv_deep_swap(x);
634    }
635 
swap_resourcesboost::container::vector_alloc_holder636    BOOST_CONTAINER_FORCEINLINE void swap_resources(vector_alloc_holder &) BOOST_NOEXCEPT_OR_NOTHROW
637    {  //Containers with version 0 allocators can't be moved without moving elements one by one
638       on_capacity_overflow();
639    }
640 
641 
steal_resourcesboost::container::vector_alloc_holder642    BOOST_CONTAINER_FORCEINLINE void steal_resources(vector_alloc_holder &)
643    {  //Containers with version 0 allocators can't be moved without moving elements one by one
644       on_capacity_overflow();
645    }
646 
allocboost::container::vector_alloc_holder647    BOOST_CONTAINER_FORCEINLINE allocator_type &alloc() BOOST_NOEXCEPT_OR_NOTHROW
648    {  return *this;  }
649 
allocboost::container::vector_alloc_holder650    BOOST_CONTAINER_FORCEINLINE const allocator_type &alloc() const BOOST_NOEXCEPT_OR_NOTHROW
651    {  return *this;  }
652 
try_expand_fwdboost::container::vector_alloc_holder653    BOOST_CONTAINER_FORCEINLINE bool try_expand_fwd(size_type at_least)
654    {  return !at_least;  }
655 
startboost::container::vector_alloc_holder656    BOOST_CONTAINER_FORCEINLINE pointer start() const       BOOST_NOEXCEPT_OR_NOTHROW
657    {  return allocator_type::internal_storage();  }
658 
capacityboost::container::vector_alloc_holder659    BOOST_CONTAINER_FORCEINLINE size_type  capacity() const BOOST_NOEXCEPT_OR_NOTHROW
660    {  return allocator_type::internal_capacity;  }
661 
662    stored_size_type m_size;
663 
664    private:
665 
666    template<class OtherAllocator, class OtherStoredSizeType, class OtherAllocatorVersion>
priv_deep_swapboost::container::vector_alloc_holder667    void priv_deep_swap(vector_alloc_holder<OtherAllocator, OtherStoredSizeType, OtherAllocatorVersion> &x)
668    {
669       const size_type MaxTmpStorage = sizeof(value_type)*allocator_type::internal_capacity;
670       value_type *const first_this = boost::movelib::to_raw_pointer(this->start());
671       value_type *const first_x = boost::movelib::to_raw_pointer(x.start());
672 
673       if(this->m_size < x.m_size){
674          boost::container::deep_swap_alloc_n<MaxTmpStorage>(this->alloc(), first_this, this->m_size, first_x, x.m_size);
675       }
676       else{
677          boost::container::deep_swap_alloc_n<MaxTmpStorage>(this->alloc(), first_x, x.m_size, first_this, this->m_size);
678       }
679       boost::adl_move_swap(this->m_size, x.m_size);
680    }
681 };
682 
683 struct growth_factor_60;
684 
685 template<class Options, class AllocatorSizeType>
686 struct get_vector_opt
687 {
688    typedef vector_opt< typename default_if_void<typename Options::growth_factor_type, growth_factor_60>::type
689                      , typename default_if_void<typename Options::stored_size_type, AllocatorSizeType>::type
690                      > type;
691 };
692 
693 template<class AllocatorSizeType>
694 struct get_vector_opt<void, AllocatorSizeType>
695 {
696    typedef vector_opt<growth_factor_60, AllocatorSizeType> type;
697 };
698 
699 #endif   //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
700 
701 //! A vector is a sequence that supports random access to elements, constant
702 //! time insertion and removal of elements at the end, and linear time insertion
703 //! and removal of elements at the beginning or in the middle. The number of
704 //! elements in a vector may vary dynamically; memory management is automatic.
705 //!
706 //! \tparam T The type of object that is stored in the vector
707 //! \tparam A The allocator used for all internal memory management, use void
708 //!   for the default allocator
709 //! \tparam Options A type produced from \c boost::container::vector_options.
710 template <class T, class A BOOST_CONTAINER_DOCONLY(= void), class Options BOOST_CONTAINER_DOCONLY(= void) >
711 class vector
712 {
713 public:
714    //////////////////////////////////////////////
715    //
716    //                    types
717    //
718    //////////////////////////////////////////////
719    typedef T                                                                           value_type;
720    typedef BOOST_CONTAINER_IMPDEF
721       (typename real_allocator<T BOOST_MOVE_I A>::type)                                allocator_type;
722    typedef ::boost::container::allocator_traits<allocator_type>                        allocator_traits_t;
723    typedef typename   allocator_traits<allocator_type>::pointer                        pointer;
724    typedef typename   allocator_traits<allocator_type>::const_pointer                  const_pointer;
725    typedef typename   allocator_traits<allocator_type>::reference                      reference;
726    typedef typename   allocator_traits<allocator_type>::const_reference                const_reference;
727    typedef typename   allocator_traits<allocator_type>::size_type                      size_type;
728    typedef typename   allocator_traits<allocator_type>::difference_type                difference_type;
729    typedef allocator_type                                                              stored_allocator_type;
730    typedef BOOST_CONTAINER_IMPDEF(vec_iterator<pointer BOOST_MOVE_I false>)            iterator;
731    typedef BOOST_CONTAINER_IMPDEF(vec_iterator<pointer BOOST_MOVE_I true >)            const_iterator;
732    typedef BOOST_CONTAINER_IMPDEF(boost::container::reverse_iterator<iterator>)        reverse_iterator;
733    typedef BOOST_CONTAINER_IMPDEF(boost::container::reverse_iterator<const_iterator>)  const_reverse_iterator;
734 
735 private:
736 
737    #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
738    typedef typename boost::container::
739       allocator_traits<allocator_type>::size_type                             alloc_size_type;
740    typedef typename get_vector_opt<Options, alloc_size_type>::type            options_type;
741    typedef typename options_type::growth_factor_type                          growth_factor_type;
742    typedef typename options_type::stored_size_type                            stored_size_type;
743    typedef value_less<T>                                                      value_less_t;
744 
745    //If provided the stored_size option must specify a type that is equal or a type that is smaller.
746    BOOST_STATIC_ASSERT( (sizeof(stored_size_type) < sizeof(alloc_size_type) ||
747                         dtl::is_same<stored_size_type, alloc_size_type>::value) );
748 
749    typedef typename dtl::version<allocator_type>::type alloc_version;
750    typedef boost::container::vector_alloc_holder
751       <allocator_type, stored_size_type> alloc_holder_t;
752 
753    alloc_holder_t m_holder;
754 
755    typedef allocator_traits<allocator_type>                      allocator_traits_type;
756    template <class U, class UA, class UOptions>
757    friend class vector;
758 
759 
760    protected:
761    BOOST_CONTAINER_FORCEINLINE
is_propagable_from(const allocator_type & from_alloc,pointer p,const allocator_type & to_alloc,bool const propagate_allocator)762       static bool is_propagable_from(const allocator_type &from_alloc, pointer p, const allocator_type &to_alloc, bool const propagate_allocator)
763    {  return alloc_holder_t::is_propagable_from(from_alloc, p, to_alloc, propagate_allocator);  }
764 
765    BOOST_CONTAINER_FORCEINLINE
are_swap_propagable(const allocator_type & l_a,pointer l_p,const allocator_type & r_a,pointer r_p,bool const propagate_allocator)766       static bool are_swap_propagable( const allocator_type &l_a, pointer l_p
767                                      , const allocator_type &r_a, pointer r_p, bool const propagate_allocator)
768    {  return alloc_holder_t::are_swap_propagable(l_a, l_p, r_a, r_p, propagate_allocator);  }
769 
770    #endif   //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
771    #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
772    private:
773    BOOST_COPYABLE_AND_MOVABLE(vector)
774    typedef vector_value_traits<allocator_type> value_traits;
775    typedef constant_iterator<T, difference_type>            cvalue_iterator;
776 
777    protected:
778 
steal_resources(vector & x)779    BOOST_CONTAINER_FORCEINLINE void steal_resources(vector &x)
780    {  return this->m_holder.steal_resources(x.m_holder);   }
781 
782    template<class AllocFwd>
vector(initial_capacity_t,pointer initial_memory,size_type capacity,BOOST_FWD_REF (AllocFwd)a)783    BOOST_CONTAINER_FORCEINLINE vector(initial_capacity_t, pointer initial_memory, size_type capacity, BOOST_FWD_REF(AllocFwd) a)
784       : m_holder(initial_capacity_t(), initial_memory, capacity, ::boost::forward<AllocFwd>(a))
785    {}
786 
vector(initial_capacity_t,pointer initial_memory,size_type capacity)787    BOOST_CONTAINER_FORCEINLINE vector(initial_capacity_t, pointer initial_memory, size_type capacity)
788       : m_holder(initial_capacity_t(), initial_memory, capacity)
789    {}
790 
791    #endif   //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
792 
793    public:
794    //////////////////////////////////////////////
795    //
796    //          construct/copy/destroy
797    //
798    //////////////////////////////////////////////
799 
800    //! <b>Effects</b>: Constructs a vector taking the allocator as parameter.
801    //!
802    //! <b>Throws</b>: Nothing.
803    //!
804    //! <b>Complexity</b>: Constant.
BOOST_NOEXCEPT_IF(dtl::is_nothrow_default_constructible<allocator_type>::value)805    vector() BOOST_NOEXCEPT_IF(dtl::is_nothrow_default_constructible<allocator_type>::value)
806       : m_holder()
807    {}
808 
809    //! <b>Effects</b>: Constructs a vector taking the allocator as parameter.
810    //!
811    //! <b>Throws</b>: Nothing
812    //!
813    //! <b>Complexity</b>: Constant.
vector(const allocator_type & a)814    explicit vector(const allocator_type& a) BOOST_NOEXCEPT_OR_NOTHROW
815       : m_holder(a)
816    {}
817 
818    //! <b>Effects</b>: Constructs a vector and inserts n value initialized values.
819    //!
820    //! <b>Throws</b>: If allocator_type's allocation
821    //!   throws or T's value initialization throws.
822    //!
823    //! <b>Complexity</b>: Linear to n.
vector(size_type n)824    explicit vector(size_type n)
825       :  m_holder(vector_uninitialized_size, n)
826    {
827       #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
828       this->num_alloc += n != 0;
829       #endif
830       boost::container::uninitialized_value_init_alloc_n
831          (this->m_holder.alloc(), n, this->priv_raw_begin());
832    }
833 
834    //! <b>Effects</b>: Constructs a vector that will use a copy of allocator a
835    //!   and inserts n value initialized values.
836    //!
837    //! <b>Throws</b>: If allocator_type's allocation
838    //!   throws or T's value initialization throws.
839    //!
840    //! <b>Complexity</b>: Linear to n.
vector(size_type n,const allocator_type & a)841    explicit vector(size_type n, const allocator_type &a)
842       :  m_holder(vector_uninitialized_size, a, n)
843    {
844       #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
845       this->num_alloc += n != 0;
846       #endif
847       boost::container::uninitialized_value_init_alloc_n
848          (this->m_holder.alloc(), n, this->priv_raw_begin());
849    }
850 
851    //! <b>Effects</b>: Constructs a vector that will use a copy of allocator a
852    //!   and inserts n default initialized values.
853    //!
854    //! <b>Throws</b>: If allocator_type's allocation
855    //!   throws or T's default initialization throws.
856    //!
857    //! <b>Complexity</b>: Linear to n.
858    //!
859    //! <b>Note</b>: Non-standard extension
vector(size_type n,default_init_t)860    vector(size_type n, default_init_t)
861       :  m_holder(vector_uninitialized_size, n)
862    {
863       #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
864       this->num_alloc += n != 0;
865       #endif
866       boost::container::uninitialized_default_init_alloc_n
867          (this->m_holder.alloc(), n, this->priv_raw_begin());
868    }
869 
870    //! <b>Effects</b>: Constructs a vector that will use a copy of allocator a
871    //!   and inserts n default initialized values.
872    //!
873    //! <b>Throws</b>: If allocator_type's allocation
874    //!   throws or T's default initialization throws.
875    //!
876    //! <b>Complexity</b>: Linear to n.
877    //!
878    //! <b>Note</b>: Non-standard extension
vector(size_type n,default_init_t,const allocator_type & a)879    vector(size_type n, default_init_t, const allocator_type &a)
880       :  m_holder(vector_uninitialized_size, a, n)
881    {
882       #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
883       this->num_alloc += n != 0;
884       #endif
885       boost::container::uninitialized_default_init_alloc_n
886          (this->m_holder.alloc(), n, this->priv_raw_begin());
887    }
888 
889    //! <b>Effects</b>: Constructs a vector
890    //!   and inserts n copies of value.
891    //!
892    //! <b>Throws</b>: If allocator_type's allocation
893    //!   throws or T's copy constructor throws.
894    //!
895    //! <b>Complexity</b>: Linear to n.
vector(size_type n,const T & value)896    vector(size_type n, const T& value)
897       :  m_holder(vector_uninitialized_size, n)
898    {
899       #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
900       this->num_alloc += n != 0;
901       #endif
902       boost::container::uninitialized_fill_alloc_n
903          (this->m_holder.alloc(), value, n, this->priv_raw_begin());
904    }
905 
906    //! <b>Effects</b>: Constructs a vector that will use a copy of allocator a
907    //!   and inserts n copies of value.
908    //!
909    //! <b>Throws</b>: If allocation
910    //!   throws or T's copy constructor throws.
911    //!
912    //! <b>Complexity</b>: Linear to n.
vector(size_type n,const T & value,const allocator_type & a)913    vector(size_type n, const T& value, const allocator_type& a)
914       :  m_holder(vector_uninitialized_size, a, n)
915    {
916       #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
917       this->num_alloc += n != 0;
918       #endif
919       boost::container::uninitialized_fill_alloc_n
920          (this->m_holder.alloc(), value, n, this->priv_raw_begin());
921    }
922 
923    //! <b>Effects</b>: Constructs a vector
924    //!   and inserts a copy of the range [first, last) in the vector.
925    //!
926    //! <b>Throws</b>: If allocator_type's allocation
927    //!   throws or T's constructor taking a dereferenced InIt throws.
928    //!
929    //! <b>Complexity</b>: Linear to the range [first, last).
930 //    template <class InIt>
931 //    vector(InIt first, InIt last
932 //           BOOST_CONTAINER_DOCIGN(BOOST_MOVE_I typename dtl::disable_if_c
933 //                                  < dtl::is_convertible<InIt BOOST_MOVE_I size_type>::value
934 //                                  BOOST_MOVE_I dtl::nat >::type * = 0)
935 //           ) -> vector<typename iterator_traits<InIt>::value_type, new_allocator<typename iterator_traits<InIt>::value_type>>;
936    template <class InIt>
937    vector(InIt first, InIt last
938       BOOST_CONTAINER_DOCIGN(BOOST_MOVE_I typename dtl::disable_if_c
939          < dtl::is_convertible<InIt BOOST_MOVE_I size_type>::value
940          BOOST_MOVE_I dtl::nat >::type * = 0)
941       )
942       :  m_holder()
943    {  this->assign(first, last); }
944 
945    //! <b>Effects</b>: Constructs a vector that will use a copy of allocator a
946    //!   and inserts a copy of the range [first, last) in the vector.
947    //!
948    //! <b>Throws</b>: If allocator_type's allocation
949    //!   throws or T's constructor taking a dereferenced InIt throws.
950    //!
951    //! <b>Complexity</b>: Linear to the range [first, last).
952    template <class InIt>
953    vector(InIt first, InIt last, const allocator_type& a
954       BOOST_CONTAINER_DOCIGN(BOOST_MOVE_I typename dtl::disable_if_c
955          < dtl::is_convertible<InIt BOOST_MOVE_I size_type>::value
956          BOOST_MOVE_I dtl::nat >::type * = 0)
957       )
958       :  m_holder(a)
959    {  this->assign(first, last); }
960 
961    //! <b>Effects</b>: Copy constructs a vector.
962    //!
963    //! <b>Postcondition</b>: x == *this.
964    //!
965    //! <b>Throws</b>: If allocator_type's allocation
966    //!   throws or T's copy constructor throws.
967    //!
968    //! <b>Complexity</b>: Linear to the elements x contains.
vector(const vector & x)969    vector(const vector &x)
970       :  m_holder( vector_uninitialized_size
971                  , allocator_traits_type::select_on_container_copy_construction(x.m_holder.alloc())
972                  , x.size())
973    {
974       #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
975       this->num_alloc += x.size() != 0;
976       #endif
977       ::boost::container::uninitialized_copy_alloc_n
978          ( this->m_holder.alloc(), x.priv_raw_begin()
979          , x.size(), this->priv_raw_begin());
980    }
981 
982    //! <b>Effects</b>: Move constructor. Moves x's resources to *this.
983    //!
984    //! <b>Throws</b>: Nothing
985    //!
986    //! <b>Complexity</b>: Constant.
vector(BOOST_RV_REF (vector)x)987    vector(BOOST_RV_REF(vector) x) BOOST_NOEXCEPT_OR_NOTHROW
988       :  m_holder(boost::move(x.m_holder))
989    {  BOOST_STATIC_ASSERT((!allocator_traits_type::is_partially_propagable::value));  }
990 
991    #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
992    //! <b>Effects</b>: Constructs a vector that will use a copy of allocator a
993    //!  and inserts a copy of the range [il.begin(), il.last()) in the vector
994    //!
995    //! <b>Throws</b>: If T's constructor taking a dereferenced initializer_list iterator throws.
996    //!
997    //! <b>Complexity</b>: Linear to the range [il.begin(), il.end()).
vector(std::initializer_list<value_type> il,const allocator_type & a=allocator_type ())998    vector(std::initializer_list<value_type> il, const allocator_type& a = allocator_type())
999       :  m_holder(vector_uninitialized_size, a, il.size())
1000    {
1001       #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
1002       this->num_alloc += il.size() != 0;
1003       #endif
1004       ::boost::container::uninitialized_copy_alloc_n_source
1005          ( this->m_holder.alloc(), il.begin()
1006          , il.size(), this->priv_raw_begin());
1007    }
1008    #endif
1009 
1010    #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
1011 
1012    //! <b>Effects</b>: Move constructor. Moves x's resources to *this.
1013    //!
1014    //! <b>Throws</b>: If T's move constructor or allocation throws
1015    //!
1016    //! <b>Complexity</b>: Linear.
1017    //!
1018    //! <b>Note</b>: Non-standard extension to support static_vector
1019    template<class OtherA>
vector(BOOST_RV_REF_BEG vector<T,OtherA,Options> BOOST_RV_REF_END x,typename dtl::enable_if_c<dtl::is_version<typename real_allocator<T,OtherA>::type,0>::value>::type * =0)1020    vector(BOOST_RV_REF_BEG vector<T, OtherA, Options> BOOST_RV_REF_END x
1021          , typename dtl::enable_if_c
1022             < dtl::is_version<typename real_allocator<T, OtherA>::type, 0>::value>::type * = 0
1023          )
1024       :  m_holder(boost::move(x.m_holder))
1025    {}
1026 
1027    #endif   //!defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
1028 
1029    //! <b>Effects</b>: Copy constructs a vector using the specified allocator.
1030    //!
1031    //! <b>Postcondition</b>: x == *this.
1032    //!
1033    //! <b>Throws</b>: If allocation
1034    //!   throws or T's copy constructor throws.
1035    //!
1036    //! <b>Complexity</b>: Linear to the elements x contains.
vector(const vector & x,const allocator_type & a)1037    vector(const vector &x, const allocator_type &a)
1038       :  m_holder(vector_uninitialized_size, a, x.size())
1039    {
1040       #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
1041       this->num_alloc += x.size() != 0;
1042       #endif
1043       ::boost::container::uninitialized_copy_alloc_n_source
1044          ( this->m_holder.alloc(), x.priv_raw_begin()
1045          , x.size(), this->priv_raw_begin());
1046    }
1047 
1048    //! <b>Effects</b>: Move constructor using the specified allocator.
1049    //!                 Moves x's resources to *this if a == allocator_type().
1050    //!                 Otherwise copies values from x to *this.
1051    //!
1052    //! <b>Throws</b>: If allocation or T's copy constructor throws.
1053    //!
1054    //! <b>Complexity</b>: Constant if a == x.get_allocator(), linear otherwise.
vector(BOOST_RV_REF (vector)x,const allocator_type & a)1055    vector(BOOST_RV_REF(vector) x, const allocator_type &a)
1056       :  m_holder( vector_uninitialized_size, a
1057                  //In this allocator move constructor the allocator won't be propagated --v
1058                  , is_propagable_from(x.get_stored_allocator(), x.m_holder.start(), a, false) ? 0 : x.size()
1059                  )
1060    {
1061       //In this allocator move constructor the allocator won't be propagated ---v
1062       if(is_propagable_from(x.get_stored_allocator(), x.m_holder.start(), a, false)){
1063          this->m_holder.steal_resources(x.m_holder);
1064       }
1065       else{
1066          const size_type n = x.size();
1067          #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
1068          this->num_alloc += n != 0;
1069          #endif
1070          ::boost::container::uninitialized_move_alloc_n_source
1071             ( this->m_holder.alloc(), x.priv_raw_begin()
1072             , n, this->priv_raw_begin());
1073       }
1074    }
1075 
1076    //! <b>Effects</b>: Destroys the vector. All stored values are destroyed
1077    //!   and used memory is deallocated.
1078    //!
1079    //! <b>Throws</b>: Nothing.
1080    //!
1081    //! <b>Complexity</b>: Linear to the number of elements.
~vector()1082    ~vector() BOOST_NOEXCEPT_OR_NOTHROW
1083    {
1084       boost::container::destroy_alloc_n
1085          (this->get_stored_allocator(), this->priv_raw_begin(), this->m_holder.m_size);
1086       //vector_alloc_holder deallocates the data
1087    }
1088 
1089    //! <b>Effects</b>: Makes *this contain the same elements as x.
1090    //!
1091    //! <b>Postcondition</b>: this->size() == x.size(). *this contains a copy
1092    //! of each of x's elements.
1093    //!
1094    //! <b>Throws</b>: If memory allocation throws or T's copy/move constructor/assignment throws.
1095    //!
1096    //! <b>Complexity</b>: Linear to the number of elements in x.
operator =(BOOST_COPY_ASSIGN_REF (vector)x)1097    BOOST_CONTAINER_FORCEINLINE vector& operator=(BOOST_COPY_ASSIGN_REF(vector) x)
1098    {
1099       if (BOOST_LIKELY(&x != this)){
1100          this->priv_copy_assign(x);
1101       }
1102       return *this;
1103    }
1104 
1105    #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
1106    //! <b>Effects</b>: Make *this container contains elements from il.
1107    //!
1108    //! <b>Complexity</b>: Linear to the range [il.begin(), il.end()).
operator =(std::initializer_list<value_type> il)1109    BOOST_CONTAINER_FORCEINLINE vector& operator=(std::initializer_list<value_type> il)
1110    {
1111       this->assign(il.begin(), il.end());
1112       return *this;
1113    }
1114    #endif
1115 
1116    //! <b>Effects</b>: Move assignment. All x's values are transferred to *this.
1117    //!
1118    //! <b>Postcondition</b>: x.empty(). *this contains a the elements x had
1119    //!   before the function.
1120    //!
1121    //! <b>Throws</b>: If allocator_traits_type::propagate_on_container_move_assignment
1122    //!   is false and (allocation throws or value_type's move constructor throws)
1123    //!
1124    //! <b>Complexity</b>: Constant if allocator_traits_type::
1125    //!   propagate_on_container_move_assignment is true or
1126    //!   this->get>allocator() == x.get_allocator(). Linear otherwise.
operator =(BOOST_RV_REF (vector)x)1127    BOOST_CONTAINER_FORCEINLINE vector& operator=(BOOST_RV_REF(vector) x)
1128       BOOST_NOEXCEPT_IF(allocator_traits_type::propagate_on_container_move_assignment::value
1129                         || allocator_traits_type::is_always_equal::value)
1130    {
1131       if (BOOST_LIKELY(&x != this)){
1132          this->priv_move_assign(boost::move(x));
1133       }
1134       return *this;
1135    }
1136 
1137    #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
1138 
1139    //! <b>Effects</b>: Move assignment. All x's values are transferred to *this.
1140    //!
1141    //! <b>Postcondition</b>: x.empty(). *this contains a the elements x had
1142    //!   before the function.
1143    //!
1144    //! <b>Throws</b>: If move constructor/assignment of T throws or allocation throws
1145    //!
1146    //! <b>Complexity</b>: Linear.
1147    //!
1148    //! <b>Note</b>: Non-standard extension to support static_vector
1149    template<class OtherA>
1150    BOOST_CONTAINER_FORCEINLINE typename dtl::enable_if_and
1151                            < vector&
1152                            , dtl::is_version<typename real_allocator<T, OtherA>::type, 0>
1153                            , dtl::is_different<typename real_allocator<T, OtherA>::type, allocator_type>
1154                            >::type
operator =(BOOST_RV_REF_BEG vector<value_type,OtherA,Options> BOOST_RV_REF_END x)1155       operator=(BOOST_RV_REF_BEG vector<value_type, OtherA, Options> BOOST_RV_REF_END x)
1156    {
1157       this->priv_move_assign(boost::move(x));
1158       return *this;
1159    }
1160 
1161    //! <b>Effects</b>: Copy assignment. All x's values are copied to *this.
1162    //!
1163    //! <b>Postcondition</b>: x.empty(). *this contains a the elements x had
1164    //!   before the function.
1165    //!
1166    //! <b>Throws</b>: If move constructor/assignment of T throws or allocation throws
1167    //!
1168    //! <b>Complexity</b>: Linear.
1169    //!
1170    //! <b>Note</b>: Non-standard extension to support static_vector
1171    template<class OtherA>
1172    BOOST_CONTAINER_FORCEINLINE typename dtl::enable_if_and
1173                            < vector&
1174                            , dtl::is_version<typename real_allocator<T, OtherA>::type, 0>
1175                            , dtl::is_different<typename real_allocator<T, OtherA>::type, allocator_type>
1176                            >::type
operator =(const vector<value_type,OtherA,Options> & x)1177       operator=(const vector<value_type, OtherA, Options> &x)
1178    {
1179       this->priv_copy_assign(x);
1180       return *this;
1181    }
1182 
1183    #endif
1184 
1185    //! <b>Effects</b>: Assigns the the range [first, last) to *this.
1186    //!
1187    //! <b>Throws</b>: If memory allocation throws or T's copy/move constructor/assignment or
1188    //!   T's constructor/assignment from dereferencing InpIt throws.
1189    //!
1190    //! <b>Complexity</b>: Linear to n.
1191    template <class InIt>
1192    void assign(InIt first, InIt last
1193       //Input iterators or version 0 allocator
1194       BOOST_CONTAINER_DOCIGN(BOOST_MOVE_I typename dtl::disable_if_or
1195          < void
1196          BOOST_MOVE_I dtl::is_convertible<InIt BOOST_MOVE_I size_type>
1197          BOOST_MOVE_I dtl::and_
1198             < dtl::is_different<alloc_version BOOST_MOVE_I version_0>
1199             BOOST_MOVE_I dtl::is_not_input_iterator<InIt>
1200             >
1201          >::type * = 0)
1202       )
1203    {
1204       //Overwrite all elements we can from [first, last)
1205       iterator cur = this->begin();
1206       const iterator end_it = this->end();
1207       for ( ; first != last && cur != end_it; ++cur, ++first){
1208          *cur = *first;
1209       }
1210 
1211       if (first == last){
1212          //There are no more elements in the sequence, erase remaining
1213          T* const end_pos = this->priv_raw_end();
1214          const size_type n = static_cast<size_type>(end_pos - boost::movelib::iterator_to_raw_pointer(cur));
1215          this->priv_destroy_last_n(n);
1216       }
1217       else{
1218          //There are more elements in the range, insert the remaining ones
1219          this->insert(this->cend(), first, last);
1220       }
1221    }
1222 
1223    #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
1224    //! <b>Effects</b>: Assigns the the range [il.begin(), il.end()) to *this.
1225    //!
1226    //! <b>Throws</b>: If memory allocation throws or
1227    //!   T's constructor from dereferencing iniializer_list iterator throws.
1228    //!
assign(std::initializer_list<T> il)1229    BOOST_CONTAINER_FORCEINLINE void assign(std::initializer_list<T> il)
1230    {
1231       this->assign(il.begin(), il.end());
1232    }
1233    #endif
1234 
1235    //! <b>Effects</b>: Assigns the the range [first, last) to *this.
1236    //!
1237    //! <b>Throws</b>: If memory allocation throws or T's copy/move constructor/assignment or
1238    //!   T's constructor/assignment from dereferencing InpIt throws.
1239    //!
1240    //! <b>Complexity</b>: Linear to n.
1241    template <class FwdIt>
1242    void assign(FwdIt first, FwdIt last
1243       //Forward iterators and version > 0 allocator
1244       BOOST_CONTAINER_DOCIGN(BOOST_MOVE_I typename dtl::disable_if_or
1245          < void
1246          BOOST_MOVE_I dtl::is_same<alloc_version BOOST_MOVE_I version_0>
1247          BOOST_MOVE_I dtl::is_convertible<FwdIt BOOST_MOVE_I size_type>
1248          BOOST_MOVE_I dtl::is_input_iterator<FwdIt>
1249          >::type * = 0)
1250       )
1251    {
1252       //For Fwd iterators the standard only requires EmplaceConstructible and assignable from *first
1253       //so we can't do any backwards allocation
1254       const size_type input_sz = static_cast<size_type>(boost::container::iterator_distance(first, last));
1255       const size_type old_capacity = this->capacity();
1256       if(input_sz > old_capacity){  //If input range is too big, we need to reallocate
1257          size_type real_cap = 0;
1258          pointer reuse(this->m_holder.start());
1259          pointer const ret(this->m_holder.allocation_command(allocate_new|expand_fwd, input_sz, real_cap = input_sz, reuse));
1260          if(!reuse){  //New allocation, just emplace new values
1261             #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
1262             ++this->num_alloc;
1263             #endif
1264             pointer const old_p = this->m_holder.start();
1265             if(old_p){
1266                this->priv_destroy_all();
1267                this->m_holder.deallocate(old_p, old_capacity);
1268             }
1269             this->m_holder.start(ret);
1270             this->m_holder.capacity(real_cap);
1271             this->m_holder.m_size = 0;
1272             this->priv_uninitialized_construct_at_end(first, last);
1273             return;
1274          }
1275          else{
1276             #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
1277             ++this->num_expand_fwd;
1278             #endif
1279             this->m_holder.capacity(real_cap);
1280             //Forward expansion, use assignment + back deletion/construction that comes later
1281          }
1282       }
1283 
1284       boost::container::copy_assign_range_alloc_n(this->m_holder.alloc(), first, input_sz, this->priv_raw_begin(), this->size());
1285       this->m_holder.m_size = input_sz;
1286    }
1287 
1288    //! <b>Effects</b>: Assigns the n copies of val to *this.
1289    //!
1290    //! <b>Throws</b>: If memory allocation throws or
1291    //!   T's copy/move constructor/assignment throws.
1292    //!
1293    //! <b>Complexity</b>: Linear to n.
assign(size_type n,const value_type & val)1294    BOOST_CONTAINER_FORCEINLINE void assign(size_type n, const value_type& val)
1295    {  this->assign(cvalue_iterator(val, n), cvalue_iterator());   }
1296 
1297    //! <b>Effects</b>: Returns a copy of the internal allocator.
1298    //!
1299    //! <b>Throws</b>: If allocator's copy constructor throws.
1300    //!
1301    //! <b>Complexity</b>: Constant.
get_allocator() const1302    allocator_type get_allocator() const BOOST_NOEXCEPT_OR_NOTHROW
1303    { return this->m_holder.alloc();  }
1304 
1305    //! <b>Effects</b>: Returns a reference to the internal allocator.
1306    //!
1307    //! <b>Throws</b>: Nothing
1308    //!
1309    //! <b>Complexity</b>: Constant.
1310    //!
1311    //! <b>Note</b>: Non-standard extension.
get_stored_allocator()1312    BOOST_CONTAINER_FORCEINLINE stored_allocator_type &get_stored_allocator() BOOST_NOEXCEPT_OR_NOTHROW
1313    {  return this->m_holder.alloc(); }
1314 
1315    //! <b>Effects</b>: Returns a reference to the internal allocator.
1316    //!
1317    //! <b>Throws</b>: Nothing
1318    //!
1319    //! <b>Complexity</b>: Constant.
1320    //!
1321    //! <b>Note</b>: Non-standard extension.
get_stored_allocator() const1322    BOOST_CONTAINER_FORCEINLINE const stored_allocator_type &get_stored_allocator() const BOOST_NOEXCEPT_OR_NOTHROW
1323    {  return this->m_holder.alloc(); }
1324 
1325    //////////////////////////////////////////////
1326    //
1327    //                iterators
1328    //
1329    //////////////////////////////////////////////
1330 
1331    //! <b>Effects</b>: Returns an iterator to the first element contained in the vector.
1332    //!
1333    //! <b>Throws</b>: Nothing.
1334    //!
1335    //! <b>Complexity</b>: Constant.
begin()1336    BOOST_CONTAINER_FORCEINLINE iterator begin() BOOST_NOEXCEPT_OR_NOTHROW
1337    { return iterator(this->m_holder.start()); }
1338 
1339    //! <b>Effects</b>: Returns a const_iterator to the first element contained in the vector.
1340    //!
1341    //! <b>Throws</b>: Nothing.
1342    //!
1343    //! <b>Complexity</b>: Constant.
begin() const1344    BOOST_CONTAINER_FORCEINLINE const_iterator begin() const BOOST_NOEXCEPT_OR_NOTHROW
1345    { return const_iterator(this->m_holder.start()); }
1346 
1347    //! <b>Effects</b>: Returns an iterator to the end of the vector.
1348    //!
1349    //! <b>Throws</b>: Nothing.
1350    //!
1351    //! <b>Complexity</b>: Constant.
end()1352    BOOST_CONTAINER_FORCEINLINE iterator end() BOOST_NOEXCEPT_OR_NOTHROW
1353    {
1354       pointer   const bg = this->m_holder.start();
1355       size_type const sz = this->m_holder.m_size;
1356       return iterator(BOOST_LIKELY(sz) ? bg + sz : bg);  //Avoid UB on null-pointer arithmetic
1357    }
1358 
1359    //! <b>Effects</b>: Returns a const_iterator to the end of the vector.
1360    //!
1361    //! <b>Throws</b>: Nothing.
1362    //!
1363    //! <b>Complexity</b>: Constant.
end() const1364    BOOST_CONTAINER_FORCEINLINE const_iterator end() const BOOST_NOEXCEPT_OR_NOTHROW
1365    { return this->cend(); }
1366 
1367    //! <b>Effects</b>: Returns a reverse_iterator pointing to the beginning
1368    //! of the reversed vector.
1369    //!
1370    //! <b>Throws</b>: Nothing.
1371    //!
1372    //! <b>Complexity</b>: Constant.
rbegin()1373    BOOST_CONTAINER_FORCEINLINE reverse_iterator rbegin() BOOST_NOEXCEPT_OR_NOTHROW
1374    { return reverse_iterator(this->end());      }
1375 
1376    //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the beginning
1377    //! of the reversed vector.
1378    //!
1379    //! <b>Throws</b>: Nothing.
1380    //!
1381    //! <b>Complexity</b>: Constant.
rbegin() const1382    BOOST_CONTAINER_FORCEINLINE const_reverse_iterator rbegin() const BOOST_NOEXCEPT_OR_NOTHROW
1383    { return this->crbegin(); }
1384 
1385    //! <b>Effects</b>: Returns a reverse_iterator pointing to the end
1386    //! of the reversed vector.
1387    //!
1388    //! <b>Throws</b>: Nothing.
1389    //!
1390    //! <b>Complexity</b>: Constant.
rend()1391    BOOST_CONTAINER_FORCEINLINE reverse_iterator rend() BOOST_NOEXCEPT_OR_NOTHROW
1392    { return reverse_iterator(this->begin());       }
1393 
1394    //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the end
1395    //! of the reversed vector.
1396    //!
1397    //! <b>Throws</b>: Nothing.
1398    //!
1399    //! <b>Complexity</b>: Constant.
rend() const1400    BOOST_CONTAINER_FORCEINLINE const_reverse_iterator rend() const BOOST_NOEXCEPT_OR_NOTHROW
1401    { return this->crend(); }
1402 
1403    //! <b>Effects</b>: Returns a const_iterator to the first element contained in the vector.
1404    //!
1405    //! <b>Throws</b>: Nothing.
1406    //!
1407    //! <b>Complexity</b>: Constant.
cbegin() const1408    BOOST_CONTAINER_FORCEINLINE const_iterator cbegin() const BOOST_NOEXCEPT_OR_NOTHROW
1409    { return const_iterator(this->m_holder.start()); }
1410 
1411    //! <b>Effects</b>: Returns a const_iterator to the end of the vector.
1412    //!
1413    //! <b>Throws</b>: Nothing.
1414    //!
1415    //! <b>Complexity</b>: Constant.
cend() const1416    BOOST_CONTAINER_FORCEINLINE const_iterator cend() const BOOST_NOEXCEPT_OR_NOTHROW
1417    {
1418       pointer   const bg = this->m_holder.start();
1419       size_type const sz = this->m_holder.m_size;
1420       return const_iterator(BOOST_LIKELY(sz) ? bg + sz : bg);  //Avoid UB on null-pointer arithmetic
1421    }
1422    //{ return const_iterator(this->m_holder.start() + this->m_holder.m_size); }
1423 
1424    //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the beginning
1425    //! of the reversed vector.
1426    //!
1427    //! <b>Throws</b>: Nothing.
1428    //!
1429    //! <b>Complexity</b>: Constant.
crbegin() const1430    BOOST_CONTAINER_FORCEINLINE const_reverse_iterator crbegin() const BOOST_NOEXCEPT_OR_NOTHROW
1431    { return const_reverse_iterator(this->end());}
1432 
1433    //! <b>Effects</b>: Returns a const_reverse_iterator pointing to the end
1434    //! of the reversed vector.
1435    //!
1436    //! <b>Throws</b>: Nothing.
1437    //!
1438    //! <b>Complexity</b>: Constant.
crend() const1439    BOOST_CONTAINER_FORCEINLINE const_reverse_iterator crend() const BOOST_NOEXCEPT_OR_NOTHROW
1440    { return const_reverse_iterator(this->begin()); }
1441 
1442    //////////////////////////////////////////////
1443    //
1444    //                capacity
1445    //
1446    //////////////////////////////////////////////
1447 
1448    //! <b>Effects</b>: Returns true if the vector contains no elements.
1449    //!
1450    //! <b>Throws</b>: Nothing.
1451    //!
1452    //! <b>Complexity</b>: Constant.
empty() const1453    BOOST_CONTAINER_FORCEINLINE bool empty() const BOOST_NOEXCEPT_OR_NOTHROW
1454    { return !this->m_holder.m_size; }
1455 
1456    //! <b>Effects</b>: Returns the number of the elements contained in the vector.
1457    //!
1458    //! <b>Throws</b>: Nothing.
1459    //!
1460    //! <b>Complexity</b>: Constant.
size() const1461    BOOST_CONTAINER_FORCEINLINE size_type size() const BOOST_NOEXCEPT_OR_NOTHROW
1462    { return this->m_holder.m_size; }
1463 
1464    //! <b>Effects</b>: Returns the largest possible size of the vector.
1465    //!
1466    //! <b>Throws</b>: Nothing.
1467    //!
1468    //! <b>Complexity</b>: Constant.
max_size() const1469    BOOST_CONTAINER_FORCEINLINE size_type max_size() const BOOST_NOEXCEPT_OR_NOTHROW
1470    { return allocator_traits_type::max_size(this->m_holder.alloc()); }
1471 
1472    //! <b>Effects</b>: Inserts or erases elements at the end such that
1473    //!   the size becomes n. New elements are value initialized.
1474    //!
1475    //! <b>Throws</b>: If memory allocation throws, or T's copy/move or value initialization throws.
1476    //!
1477    //! <b>Complexity</b>: Linear to the difference between size() and new_size.
resize(size_type new_size)1478    void resize(size_type new_size)
1479    {  this->priv_resize(new_size, value_init);  }
1480 
1481    //! <b>Effects</b>: Inserts or erases elements at the end such that
1482    //!   the size becomes n. New elements are default initialized.
1483    //!
1484    //! <b>Throws</b>: If memory allocation throws, or T's copy/move or default initialization throws.
1485    //!
1486    //! <b>Complexity</b>: Linear to the difference between size() and new_size.
1487    //!
1488    //! <b>Note</b>: Non-standard extension
resize(size_type new_size,default_init_t)1489    void resize(size_type new_size, default_init_t)
1490    {  this->priv_resize(new_size, default_init);  }
1491 
1492    //! <b>Effects</b>: Inserts or erases elements at the end such that
1493    //!   the size becomes n. New elements are copy constructed from x.
1494    //!
1495    //! <b>Throws</b>: If memory allocation throws, or T's copy/move constructor throws.
1496    //!
1497    //! <b>Complexity</b>: Linear to the difference between size() and new_size.
resize(size_type new_size,const T & x)1498    void resize(size_type new_size, const T& x)
1499    {  this->priv_resize(new_size, x);  }
1500 
1501    //! <b>Effects</b>: Number of elements for which memory has been allocated.
1502    //!   capacity() is always greater than or equal to size().
1503    //!
1504    //! <b>Throws</b>: Nothing.
1505    //!
1506    //! <b>Complexity</b>: Constant.
capacity() const1507    BOOST_CONTAINER_FORCEINLINE size_type capacity() const BOOST_NOEXCEPT_OR_NOTHROW
1508    { return this->m_holder.capacity(); }
1509 
1510    //! <b>Effects</b>: If n is less than or equal to capacity(), this call has no
1511    //!   effect. Otherwise, it is a request for allocation of additional memory.
1512    //!   If the request is successful, then capacity() is greater than or equal to
1513    //!   n; otherwise, capacity() is unchanged. In either case, size() is unchanged.
1514    //!
1515    //! <b>Throws</b>: If memory allocation allocation throws or T's copy/move constructor throws.
reserve(size_type new_cap)1516    BOOST_CONTAINER_FORCEINLINE void reserve(size_type new_cap)
1517    {
1518       if (this->capacity() < new_cap){
1519          this->priv_reserve_no_capacity(new_cap, alloc_version());
1520       }
1521    }
1522 
1523    //! <b>Effects</b>: Tries to deallocate the excess of memory created
1524    //!   with previous allocations. The size of the vector is unchanged
1525    //!
1526    //! <b>Throws</b>: If memory allocation throws, or T's copy/move constructor throws.
1527    //!
1528    //! <b>Complexity</b>: Linear to size().
shrink_to_fit()1529    BOOST_CONTAINER_FORCEINLINE void shrink_to_fit()
1530    {  this->priv_shrink_to_fit(alloc_version());   }
1531 
1532    //////////////////////////////////////////////
1533    //
1534    //               element access
1535    //
1536    //////////////////////////////////////////////
1537 
1538    //! <b>Requires</b>: !empty()
1539    //!
1540    //! <b>Effects</b>: Returns a reference to the first
1541    //!   element of the container.
1542    //!
1543    //! <b>Throws</b>: Nothing.
1544    //!
1545    //! <b>Complexity</b>: Constant.
front()1546    reference         front() BOOST_NOEXCEPT_OR_NOTHROW
1547    {
1548       BOOST_ASSERT(!this->empty());
1549       return *this->m_holder.start();
1550    }
1551 
1552    //! <b>Requires</b>: !empty()
1553    //!
1554    //! <b>Effects</b>: Returns a const reference to the first
1555    //!   element of the container.
1556    //!
1557    //! <b>Throws</b>: Nothing.
1558    //!
1559    //! <b>Complexity</b>: Constant.
front() const1560    const_reference   front() const BOOST_NOEXCEPT_OR_NOTHROW
1561    {
1562       BOOST_ASSERT(!this->empty());
1563       return *this->m_holder.start();
1564    }
1565 
1566    //! <b>Requires</b>: !empty()
1567    //!
1568    //! <b>Effects</b>: Returns a reference to the last
1569    //!   element of the container.
1570    //!
1571    //! <b>Throws</b>: Nothing.
1572    //!
1573    //! <b>Complexity</b>: Constant.
back()1574    reference         back() BOOST_NOEXCEPT_OR_NOTHROW
1575    {
1576       BOOST_ASSERT(!this->empty());
1577       return this->m_holder.start()[this->m_holder.m_size - 1];
1578    }
1579 
1580    //! <b>Requires</b>: !empty()
1581    //!
1582    //! <b>Effects</b>: Returns a const reference to the last
1583    //!   element of the container.
1584    //!
1585    //! <b>Throws</b>: Nothing.
1586    //!
1587    //! <b>Complexity</b>: Constant.
back() const1588    const_reference   back()  const BOOST_NOEXCEPT_OR_NOTHROW
1589    {
1590       BOOST_ASSERT(!this->empty());
1591       return this->m_holder.start()[this->m_holder.m_size - 1];
1592    }
1593 
1594    //! <b>Requires</b>: size() > n.
1595    //!
1596    //! <b>Effects</b>: Returns a reference to the nth element
1597    //!   from the beginning of the container.
1598    //!
1599    //! <b>Throws</b>: Nothing.
1600    //!
1601    //! <b>Complexity</b>: Constant.
operator [](size_type n)1602    reference operator[](size_type n) BOOST_NOEXCEPT_OR_NOTHROW
1603    {
1604       BOOST_ASSERT(this->m_holder.m_size > n);
1605       return this->m_holder.start()[n];
1606    }
1607 
1608    //! <b>Requires</b>: size() > n.
1609    //!
1610    //! <b>Effects</b>: Returns a const reference to the nth element
1611    //!   from the beginning of the container.
1612    //!
1613    //! <b>Throws</b>: Nothing.
1614    //!
1615    //! <b>Complexity</b>: Constant.
operator [](size_type n) const1616    const_reference operator[](size_type n) const BOOST_NOEXCEPT_OR_NOTHROW
1617    {
1618       BOOST_ASSERT(this->m_holder.m_size > n);
1619       return this->m_holder.start()[n];
1620    }
1621 
1622    //! <b>Requires</b>: size() >= n.
1623    //!
1624    //! <b>Effects</b>: Returns an iterator to the nth element
1625    //!   from the beginning of the container. Returns end()
1626    //!   if n == size().
1627    //!
1628    //! <b>Throws</b>: Nothing.
1629    //!
1630    //! <b>Complexity</b>: Constant.
1631    //!
1632    //! <b>Note</b>: Non-standard extension
nth(size_type n)1633    iterator nth(size_type n) BOOST_NOEXCEPT_OR_NOTHROW
1634    {
1635       BOOST_ASSERT(this->m_holder.m_size >= n);
1636       return iterator(this->m_holder.start()+n);
1637    }
1638 
1639    //! <b>Requires</b>: size() >= n.
1640    //!
1641    //! <b>Effects</b>: Returns a const_iterator to the nth element
1642    //!   from the beginning of the container. Returns end()
1643    //!   if n == size().
1644    //!
1645    //! <b>Throws</b>: Nothing.
1646    //!
1647    //! <b>Complexity</b>: Constant.
1648    //!
1649    //! <b>Note</b>: Non-standard extension
nth(size_type n) const1650    const_iterator nth(size_type n) const BOOST_NOEXCEPT_OR_NOTHROW
1651    {
1652       BOOST_ASSERT(this->m_holder.m_size >= n);
1653       return const_iterator(this->m_holder.start()+n);
1654    }
1655 
1656    //! <b>Requires</b>: begin() <= p <= end().
1657    //!
1658    //! <b>Effects</b>: Returns the index of the element pointed by p
1659    //!   and size() if p == end().
1660    //!
1661    //! <b>Throws</b>: Nothing.
1662    //!
1663    //! <b>Complexity</b>: Constant.
1664    //!
1665    //! <b>Note</b>: Non-standard extension
index_of(iterator p)1666    size_type index_of(iterator p) BOOST_NOEXCEPT_OR_NOTHROW
1667    {
1668       //Range check assert done in priv_index_of
1669       return this->priv_index_of(vector_iterator_get_ptr(p));
1670    }
1671 
1672    //! <b>Requires</b>: begin() <= p <= end().
1673    //!
1674    //! <b>Effects</b>: Returns the index of the element pointed by p
1675    //!   and size() if p == end().
1676    //!
1677    //! <b>Throws</b>: Nothing.
1678    //!
1679    //! <b>Complexity</b>: Constant.
1680    //!
1681    //! <b>Note</b>: Non-standard extension
index_of(const_iterator p) const1682    size_type index_of(const_iterator p) const BOOST_NOEXCEPT_OR_NOTHROW
1683    {
1684       //Range check assert done in priv_index_of
1685       return this->priv_index_of(vector_iterator_get_ptr(p));
1686    }
1687 
1688    //! <b>Requires</b>: size() > n.
1689    //!
1690    //! <b>Effects</b>: Returns a reference to the nth element
1691    //!   from the beginning of the container.
1692    //!
1693    //! <b>Throws</b>: std::range_error if n >= size()
1694    //!
1695    //! <b>Complexity</b>: Constant.
at(size_type n)1696    reference at(size_type n)
1697    {
1698       this->priv_throw_if_out_of_range(n);
1699       return this->m_holder.start()[n];
1700    }
1701 
1702    //! <b>Requires</b>: size() > n.
1703    //!
1704    //! <b>Effects</b>: Returns a const reference to the nth element
1705    //!   from the beginning of the container.
1706    //!
1707    //! <b>Throws</b>: std::range_error if n >= size()
1708    //!
1709    //! <b>Complexity</b>: Constant.
at(size_type n) const1710    const_reference at(size_type n) const
1711    {
1712       this->priv_throw_if_out_of_range(n);
1713       return this->m_holder.start()[n];
1714    }
1715 
1716    //////////////////////////////////////////////
1717    //
1718    //                 data access
1719    //
1720    //////////////////////////////////////////////
1721 
1722    //! <b>Returns</b>: A pointer such that [data(),data() + size()) is a valid range.
1723    //!   For a non-empty vector, data() == &front().
1724    //!
1725    //! <b>Throws</b>: Nothing.
1726    //!
1727    //! <b>Complexity</b>: Constant.
data()1728    T* data() BOOST_NOEXCEPT_OR_NOTHROW
1729    { return this->priv_raw_begin(); }
1730 
1731    //! <b>Returns</b>: A pointer such that [data(),data() + size()) is a valid range.
1732    //!   For a non-empty vector, data() == &front().
1733    //!
1734    //! <b>Throws</b>: Nothing.
1735    //!
1736    //! <b>Complexity</b>: Constant.
data() const1737    const T * data()  const BOOST_NOEXCEPT_OR_NOTHROW
1738    { return this->priv_raw_begin(); }
1739 
1740    //////////////////////////////////////////////
1741    //
1742    //                modifiers
1743    //
1744    //////////////////////////////////////////////
1745 
1746    #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
1747    //! <b>Effects</b>: Inserts an object of type T constructed with
1748    //!   std::forward<Args>(args)... in the end of the vector.
1749    //!
1750    //! <b>Returns</b>: A reference to the created object.
1751    //!
1752    //! <b>Throws</b>: If memory allocation throws or the in-place constructor throws or
1753    //!   T's copy/move constructor throws.
1754    //!
1755    //! <b>Complexity</b>: Amortized constant time.
1756    template<class ...Args>
emplace_back(BOOST_FWD_REF (Args)...args)1757    BOOST_CONTAINER_FORCEINLINE reference emplace_back(BOOST_FWD_REF(Args)...args)
1758    {
1759       if (BOOST_LIKELY(this->room_enough())){
1760          //There is more memory, just construct a new object at the end
1761          T* const p = this->priv_raw_end();
1762          allocator_traits_type::construct(this->m_holder.alloc(), p, ::boost::forward<Args>(args)...);
1763          ++this->m_holder.m_size;
1764          return *p;
1765       }
1766       else{
1767          typedef dtl::insert_emplace_proxy<allocator_type, T*, Args...> type;
1768          return *this->priv_forward_range_insert_no_capacity
1769             (this->back_ptr(), 1, type(::boost::forward<Args>(args)...), alloc_version());
1770       }
1771    }
1772 
1773    //! <b>Effects</b>: Inserts an object of type T constructed with
1774    //!   std::forward<Args>(args)... in the end of the vector.
1775    //!
1776    //! <b>Throws</b>: If the in-place constructor throws.
1777    //!
1778    //! <b>Complexity</b>: Constant time.
1779    //!
1780    //! <b>Note</b>: Non-standard extension.
1781    template<class ...Args>
stable_emplace_back(BOOST_FWD_REF (Args)...args)1782    BOOST_CONTAINER_FORCEINLINE bool stable_emplace_back(BOOST_FWD_REF(Args)...args)
1783    {
1784       const bool is_room_enough = this->room_enough() || (alloc_version::value == 2 && this->m_holder.try_expand_fwd(1u));
1785       if (BOOST_LIKELY(is_room_enough)){
1786          //There is more memory, just construct a new object at the end
1787          allocator_traits_type::construct(this->m_holder.alloc(), this->priv_raw_end(), ::boost::forward<Args>(args)...);
1788          ++this->m_holder.m_size;
1789       }
1790       return is_room_enough;
1791    }
1792 
1793    //! <b>Requires</b>: position must be a valid iterator of *this.
1794    //!
1795    //! <b>Effects</b>: Inserts an object of type T constructed with
1796    //!   std::forward<Args>(args)... before position
1797    //!
1798    //! <b>Throws</b>: If memory allocation throws or the in-place constructor throws or
1799    //!   T's copy/move constructor/assignment throws.
1800    //!
1801    //! <b>Complexity</b>: If position is end(), amortized constant time
1802    //!   Linear time otherwise.
1803    template<class ...Args>
emplace(const_iterator position,BOOST_FWD_REF (Args)...args)1804    iterator emplace(const_iterator position, BOOST_FWD_REF(Args) ...args)
1805    {
1806       BOOST_ASSERT(this->priv_in_range_or_end(position));
1807       //Just call more general insert(pos, size, value) and return iterator
1808       typedef dtl::insert_emplace_proxy<allocator_type, T*, Args...> type;
1809       return this->priv_forward_range_insert( vector_iterator_get_ptr(position), 1
1810                                             , type(::boost::forward<Args>(args)...));
1811    }
1812 
1813    #else // !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
1814 
1815    #define BOOST_CONTAINER_VECTOR_EMPLACE_CODE(N) \
1816    BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
1817    BOOST_CONTAINER_FORCEINLINE reference emplace_back(BOOST_MOVE_UREF##N)\
1818    {\
1819       if (BOOST_LIKELY(this->room_enough())){\
1820          T* const p = this->priv_raw_end();\
1821          allocator_traits_type::construct (this->m_holder.alloc()\
1822             , this->priv_raw_end() BOOST_MOVE_I##N BOOST_MOVE_FWD##N);\
1823          ++this->m_holder.m_size;\
1824          return *p;\
1825       }\
1826       else{\
1827          typedef dtl::insert_emplace_proxy_arg##N<allocator_type, T* BOOST_MOVE_I##N BOOST_MOVE_TARG##N> type;\
1828          return *this->priv_forward_range_insert_no_capacity\
1829             ( this->back_ptr(), 1, type(BOOST_MOVE_FWD##N), alloc_version());\
1830       }\
1831    }\
1832    \
1833    BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
1834    BOOST_CONTAINER_FORCEINLINE bool stable_emplace_back(BOOST_MOVE_UREF##N)\
1835    {\
1836       const bool is_room_enough = this->room_enough() || (alloc_version::value == 2 && this->m_holder.try_expand_fwd(1u));\
1837       if (BOOST_LIKELY(is_room_enough)){\
1838          allocator_traits_type::construct (this->m_holder.alloc()\
1839             , this->priv_raw_end() BOOST_MOVE_I##N BOOST_MOVE_FWD##N);\
1840          ++this->m_holder.m_size;\
1841       }\
1842       return is_room_enough;\
1843    }\
1844    \
1845    BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
1846    iterator emplace(const_iterator pos BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\
1847    {\
1848       BOOST_ASSERT(this->priv_in_range_or_end(pos));\
1849       typedef dtl::insert_emplace_proxy_arg##N<allocator_type, T* BOOST_MOVE_I##N BOOST_MOVE_TARG##N> type;\
1850       return this->priv_forward_range_insert(vector_iterator_get_ptr(pos), 1, type(BOOST_MOVE_FWD##N));\
1851    }\
1852    //
1853    BOOST_MOVE_ITERATE_0TO9(BOOST_CONTAINER_VECTOR_EMPLACE_CODE)
1854    #undef BOOST_CONTAINER_VECTOR_EMPLACE_CODE
1855 
1856    #endif
1857 
1858    #if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
1859    //! <b>Effects</b>: Inserts a copy of x at the end of the vector.
1860    //!
1861    //! <b>Throws</b>: If memory allocation throws or
1862    //!   T's copy/move constructor throws.
1863    //!
1864    //! <b>Complexity</b>: Amortized constant time.
1865    void push_back(const T &x);
1866 
1867    //! <b>Effects</b>: Constructs a new element in the end of the vector
1868    //!   and moves the resources of x to this new element.
1869    //!
1870    //! <b>Throws</b>: If memory allocation throws or
1871    //!   T's copy/move constructor throws.
1872    //!
1873    //! <b>Complexity</b>: Amortized constant time.
1874    void push_back(T &&x);
1875    #else
1876    BOOST_MOVE_CONVERSION_AWARE_CATCH(push_back, T, void, priv_push_back)
1877    #endif
1878 
1879    #if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
1880    //! <b>Requires</b>: position must be a valid iterator of *this.
1881    //!
1882    //! <b>Effects</b>: Insert a copy of x before position.
1883    //!
1884    //! <b>Throws</b>: If memory allocation throws or T's copy/move constructor/assignment throws.
1885    //!
1886    //! <b>Complexity</b>: If position is end(), amortized constant time
1887    //!   Linear time otherwise.
1888    iterator insert(const_iterator position, const T &x);
1889 
1890    //! <b>Requires</b>: position must be a valid iterator of *this.
1891    //!
1892    //! <b>Effects</b>: Insert a new element before position with x's resources.
1893    //!
1894    //! <b>Throws</b>: If memory allocation throws.
1895    //!
1896    //! <b>Complexity</b>: If position is end(), amortized constant time
1897    //!   Linear time otherwise.
1898    iterator insert(const_iterator position, T &&x);
1899    #else
BOOST_MOVE_CONVERSION_AWARE_CATCH_1ARG(insert,T,iterator,priv_insert,const_iterator,const_iterator)1900    BOOST_MOVE_CONVERSION_AWARE_CATCH_1ARG(insert, T, iterator, priv_insert, const_iterator, const_iterator)
1901    #endif
1902 
1903    //! <b>Requires</b>: p must be a valid iterator of *this.
1904    //!
1905    //! <b>Effects</b>: Insert n copies of x before pos.
1906    //!
1907    //! <b>Returns</b>: an iterator to the first inserted element or p if n is 0.
1908    //!
1909    //! <b>Throws</b>: If memory allocation throws or T's copy/move constructor throws.
1910    //!
1911    //! <b>Complexity</b>: Linear to n.
1912    iterator insert(const_iterator p, size_type n, const T& x)
1913    {
1914       BOOST_ASSERT(this->priv_in_range_or_end(p));
1915       dtl::insert_n_copies_proxy<allocator_type, T*> proxy(x);
1916       return this->priv_forward_range_insert(vector_iterator_get_ptr(p), n, proxy);
1917    }
1918 
1919    //! <b>Requires</b>: p must be a valid iterator of *this.
1920    //!
1921    //! <b>Effects</b>: Insert a copy of the [first, last) range before pos.
1922    //!
1923    //! <b>Returns</b>: an iterator to the first inserted element or pos if first == last.
1924    //!
1925    //! <b>Throws</b>: If memory allocation throws, T's constructor from a
1926    //!   dereferenced InpIt throws or T's copy/move constructor/assignment throws.
1927    //!
1928    //! <b>Complexity</b>: Linear to boost::container::iterator_distance [first, last).
1929    template <class InIt>
insert(const_iterator pos,InIt first,InIt last,typename dtl::disable_if_or<void,dtl::is_convertible<InIt,size_type>,dtl::is_not_input_iterator<InIt>>::type * =0)1930    iterator insert(const_iterator pos, InIt first, InIt last
1931       #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
1932       , typename dtl::disable_if_or
1933          < void
1934          , dtl::is_convertible<InIt, size_type>
1935          , dtl::is_not_input_iterator<InIt>
1936          >::type * = 0
1937       #endif
1938       )
1939    {
1940       BOOST_ASSERT(this->priv_in_range_or_end(pos));
1941       const size_type n_pos = pos - this->cbegin();
1942       iterator it(vector_iterator_get_ptr(pos));
1943       for(;first != last; ++first){
1944          it = this->emplace(it, *first);
1945          ++it;
1946       }
1947       return iterator(this->m_holder.start() + n_pos);
1948    }
1949 
1950    #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
1951    template <class FwdIt>
insert(const_iterator pos,FwdIt first,FwdIt last,typename dtl::disable_if_or<void,dtl::is_convertible<FwdIt,size_type>,dtl::is_input_iterator<FwdIt>>::type * =0)1952    iterator insert(const_iterator pos, FwdIt first, FwdIt last
1953       , typename dtl::disable_if_or
1954          < void
1955          , dtl::is_convertible<FwdIt, size_type>
1956          , dtl::is_input_iterator<FwdIt>
1957          >::type * = 0
1958       )
1959    {
1960       BOOST_ASSERT(this->priv_in_range_or_end(pos));
1961       dtl::insert_range_proxy<allocator_type, FwdIt, T*> proxy(first);
1962       return this->priv_forward_range_insert(vector_iterator_get_ptr(pos), boost::container::iterator_distance(first, last), proxy);
1963    }
1964    #endif
1965 
1966    //! <b>Requires</b>: p must be a valid iterator of *this. num, must
1967    //!   be equal to boost::container::iterator_distance(first, last)
1968    //!
1969    //! <b>Effects</b>: Insert a copy of the [first, last) range before pos.
1970    //!
1971    //! <b>Returns</b>: an iterator to the first inserted element or pos if first == last.
1972    //!
1973    //! <b>Throws</b>: If memory allocation throws, T's constructor from a
1974    //!   dereferenced InpIt throws or T's copy/move constructor/assignment throws.
1975    //!
1976    //! <b>Complexity</b>: Linear to boost::container::iterator_distance [first, last).
1977    //!
1978    //! <b>Note</b>: This function avoids a linear operation to calculate boost::container::iterator_distance[first, last)
1979    //!   for forward and bidirectional iterators, and a one by one insertion for input iterators. This is a
1980    //!   a non-standard extension.
1981    #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
1982    template <class InIt>
insert(const_iterator pos,size_type num,InIt first,InIt last)1983    iterator insert(const_iterator pos, size_type num, InIt first, InIt last)
1984    {
1985       BOOST_ASSERT(this->priv_in_range_or_end(pos));
1986       BOOST_ASSERT(dtl::is_input_iterator<InIt>::value ||
1987                    num == static_cast<size_type>(boost::container::iterator_distance(first, last)));
1988       (void)last;
1989       dtl::insert_range_proxy<allocator_type, InIt, T*> proxy(first);
1990       return this->priv_forward_range_insert(vector_iterator_get_ptr(pos), num, proxy);
1991    }
1992    #endif
1993 
1994    #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
1995    //! <b>Requires</b>: position must be a valid iterator of *this.
1996    //!
1997    //! <b>Effects</b>: Insert a copy of the [il.begin(), il.end()) range before position.
1998    //!
1999    //! <b>Returns</b>: an iterator to the first inserted element or position if first == last.
2000    //!
2001    //! <b>Complexity</b>: Linear to the range [il.begin(), il.end()).
insert(const_iterator position,std::initializer_list<value_type> il)2002    iterator insert(const_iterator position, std::initializer_list<value_type> il)
2003    {
2004       //Assertion done in insert()
2005       return this->insert(position, il.begin(), il.end());
2006    }
2007    #endif
2008 
2009    //! <b>Effects</b>: Removes the last element from the container.
2010    //!
2011    //! <b>Throws</b>: Nothing.
2012    //!
2013    //! <b>Complexity</b>: Constant time.
pop_back()2014    void pop_back() BOOST_NOEXCEPT_OR_NOTHROW
2015    {
2016       BOOST_ASSERT(!this->empty());
2017       //Destroy last element
2018       this->priv_destroy_last();
2019    }
2020 
2021    //! <b>Effects</b>: Erases the element at position pos.
2022    //!
2023    //! <b>Throws</b>: Nothing.
2024    //!
2025    //! <b>Complexity</b>: Linear to the elements between pos and the
2026    //!   last element. Constant if pos is the last element.
erase(const_iterator position)2027    iterator erase(const_iterator position)
2028    {
2029       BOOST_ASSERT(this->priv_in_range(position));
2030       const pointer p = vector_iterator_get_ptr(position);
2031       T *const pos_ptr = boost::movelib::to_raw_pointer(p);
2032       T *const beg_ptr = this->priv_raw_begin();
2033       T *const new_end_ptr = ::boost::container::move(pos_ptr + 1, beg_ptr + this->m_holder.m_size, pos_ptr);
2034       //Move elements forward and destroy last
2035       this->priv_destroy_last(pos_ptr != new_end_ptr);
2036       return iterator(p);
2037    }
2038 
2039    //! <b>Effects</b>: Erases the elements pointed by [first, last).
2040    //!
2041    //! <b>Throws</b>: Nothing.
2042    //!
2043    //! <b>Complexity</b>: Linear to the distance between first and last
2044    //!   plus linear to the elements between pos and the last element.
erase(const_iterator first,const_iterator last)2045    iterator erase(const_iterator first, const_iterator last)
2046    {
2047       if (first != last){
2048          BOOST_ASSERT(this->priv_in_range(first));
2049          BOOST_ASSERT(this->priv_in_range_or_end(last));
2050          BOOST_ASSERT(first < last);
2051          T* const old_end_ptr = this->priv_raw_end();
2052          T* const first_ptr = boost::movelib::to_raw_pointer(vector_iterator_get_ptr(first));
2053          T* const last_ptr  = boost::movelib::to_raw_pointer(vector_iterator_get_ptr(last));
2054          T* const ptr = boost::movelib::to_raw_pointer(boost::container::move(last_ptr, old_end_ptr, first_ptr));
2055          this->priv_destroy_last_n(old_end_ptr - ptr);
2056       }
2057       return iterator(vector_iterator_get_ptr(first));
2058    }
2059 
2060    //! <b>Effects</b>: Swaps the contents of *this and x.
2061    //!
2062    //! <b>Throws</b>: Nothing.
2063    //!
2064    //! <b>Complexity</b>: Constant.
swap(vector & x)2065    BOOST_CONTAINER_FORCEINLINE void swap(vector& x)
2066       BOOST_NOEXCEPT_IF( ((allocator_traits_type::propagate_on_container_swap::value
2067                                     || allocator_traits_type::is_always_equal::value) &&
2068                                     !dtl::is_version<allocator_type, 0>::value))
2069    {
2070       this->priv_swap(x, dtl::bool_<dtl::is_version<allocator_type, 0>::value>());
2071    }
2072 
2073    #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
2074 
2075    //! <b>Effects</b>: Swaps the contents of *this and x.
2076    //!
2077    //! <b>Throws</b>: Nothing.
2078    //!
2079    //! <b>Complexity</b>: Linear
2080    //!
2081    //! <b>Note</b>: Non-standard extension to support static_vector
2082    template<class OtherA>
swap(vector<T,OtherA,Options> & x,typename dtl::enable_if_and<void,dtl::is_version<typename real_allocator<T,OtherA>::type,0>,dtl::is_different<typename real_allocator<T,OtherA>::type,allocator_type>>::type * =0)2083    BOOST_CONTAINER_FORCEINLINE void swap(vector<T, OtherA, Options> & x
2084             , typename dtl::enable_if_and
2085                      < void
2086                      , dtl::is_version<typename real_allocator<T, OtherA>::type, 0>
2087                      , dtl::is_different<typename real_allocator<T, OtherA>::type, allocator_type>
2088                      >::type * = 0
2089             )
2090    {  this->m_holder.deep_swap(x.m_holder); }
2091 
2092    #endif   //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
2093 
2094    //! <b>Effects</b>: Erases all the elements of the vector.
2095    //!
2096    //! <b>Throws</b>: Nothing.
2097    //!
2098    //! <b>Complexity</b>: Linear to the number of elements in the container.
clear()2099    BOOST_CONTAINER_FORCEINLINE void clear() BOOST_NOEXCEPT_OR_NOTHROW
2100    {  this->priv_destroy_all();  }
2101 
2102    //! <b>Effects</b>: Returns true if x and y are equal
2103    //!
2104    //! <b>Complexity</b>: Linear to the number of elements in the container.
operator ==(const vector & x,const vector & y)2105    BOOST_CONTAINER_FORCEINLINE friend bool operator==(const vector& x, const vector& y)
2106    {  return x.size() == y.size() && ::boost::container::algo_equal(x.begin(), x.end(), y.begin());  }
2107 
2108    //! <b>Effects</b>: Returns true if x and y are unequal
2109    //!
2110    //! <b>Complexity</b>: Linear to the number of elements in the container.
operator !=(const vector & x,const vector & y)2111    BOOST_CONTAINER_FORCEINLINE friend bool operator!=(const vector& x, const vector& y)
2112    {  return !(x == y); }
2113 
2114    //! <b>Effects</b>: Returns true if x is less than y
2115    //!
2116    //! <b>Complexity</b>: Linear to the number of elements in the container.
operator <(const vector & x,const vector & y)2117    friend bool operator<(const vector& x, const vector& y)
2118    {  return boost::container::algo_lexicographical_compare(x.begin(), x.end(), y.begin(), y.end());  }
2119 
2120    //! <b>Effects</b>: Returns true if x is greater than y
2121    //!
2122    //! <b>Complexity</b>: Linear to the number of elements in the container.
operator >(const vector & x,const vector & y)2123    BOOST_CONTAINER_FORCEINLINE friend bool operator>(const vector& x, const vector& y)
2124    {  return y < x;  }
2125 
2126    //! <b>Effects</b>: Returns true if x is equal or less than y
2127    //!
2128    //! <b>Complexity</b>: Linear to the number of elements in the container.
operator <=(const vector & x,const vector & y)2129    BOOST_CONTAINER_FORCEINLINE friend bool operator<=(const vector& x, const vector& y)
2130    {  return !(y < x);  }
2131 
2132    //! <b>Effects</b>: Returns true if x is equal or greater than y
2133    //!
2134    //! <b>Complexity</b>: Linear to the number of elements in the container.
operator >=(const vector & x,const vector & y)2135    BOOST_CONTAINER_FORCEINLINE friend bool operator>=(const vector& x, const vector& y)
2136    {  return !(x < y);  }
2137 
2138    //! <b>Effects</b>: x.swap(y)
2139    //!
2140    //! <b>Complexity</b>: Constant.
swap(vector & x,vector & y)2141    BOOST_CONTAINER_FORCEINLINE friend void swap(vector& x, vector& y)
2142    {  x.swap(y);  }
2143 
2144    #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
2145    //! <b>Effects</b>: If n is less than or equal to capacity(), this call has no
2146    //!   effect. Otherwise, it is a request for allocation of additional memory
2147    //!   (memory expansion) that will not invalidate iterators.
2148    //!   If the request is successful, then capacity() is greater than or equal to
2149    //!   n; otherwise, capacity() is unchanged. In either case, size() is unchanged.
2150    //!
2151    //! <b>Throws</b>: If memory allocation allocation throws or T's copy/move constructor throws.
2152    //!
2153    //! <b>Note</b>: Non-standard extension.
stable_reserve(size_type new_cap)2154    bool stable_reserve(size_type new_cap)
2155    {
2156       const size_type cp = this->capacity();
2157       return cp >= new_cap || (alloc_version::value == 2 && this->m_holder.try_expand_fwd(new_cap - cp));
2158    }
2159 
2160    //Absolutely experimental. This function might change, disappear or simply crash!
2161    template<class BiDirPosConstIt, class BiDirValueIt>
insert_ordered_at(const size_type element_count,BiDirPosConstIt last_position_it,BiDirValueIt last_value_it)2162    BOOST_CONTAINER_FORCEINLINE void insert_ordered_at(const size_type element_count, BiDirPosConstIt last_position_it, BiDirValueIt last_value_it)
2163    {
2164       typedef vector_insert_ordered_cursor<BiDirPosConstIt, BiDirValueIt> inserter_t;
2165       return this->priv_insert_ordered_at(element_count, inserter_t(last_position_it, last_value_it));
2166    }
2167 
2168    template<class InputIt>
merge(InputIt first,InputIt last)2169    BOOST_CONTAINER_FORCEINLINE void merge(InputIt first, InputIt last)
2170    {  this->merge(first, last, value_less_t());  }
2171 
2172    template<class InputIt, class Compare>
merge(InputIt first,InputIt last,Compare comp)2173    BOOST_CONTAINER_FORCEINLINE void merge(InputIt first, InputIt last, Compare comp)
2174    {
2175       size_type const s = this->size();
2176       size_type const c = this->capacity();
2177       size_type n = 0;
2178       size_type const free_cap = c - s;
2179       //If not input iterator and new elements don't fit in the remaining capacity, merge in new buffer
2180       if(!dtl::is_input_iterator<InputIt>::value &&
2181          free_cap < (n = static_cast<size_type>(boost::container::iterator_distance(first, last)))){
2182          this->priv_merge_in_new_buffer(first, n, comp, alloc_version());
2183       }
2184       else{
2185          this->insert(this->cend(), first, last);
2186          T *const raw_beg = this->priv_raw_begin();
2187          T *const raw_end = this->priv_raw_end();
2188          T *const raw_pos = raw_beg + s;
2189          boost::movelib::adaptive_merge(raw_beg, raw_pos, raw_end, comp, raw_end, free_cap - n);
2190       }
2191    }
2192 
2193    template<class InputIt>
merge_unique(InputIt first,InputIt last)2194    BOOST_CONTAINER_FORCEINLINE void merge_unique(InputIt first, InputIt last)
2195    {  this->merge_unique(first, last, value_less_t());  }
2196 
2197    template<class InputIt, class Compare>
merge_unique(InputIt first,InputIt last,Compare comp)2198    BOOST_CONTAINER_FORCEINLINE void merge_unique(InputIt first, InputIt last, Compare comp)
2199    {
2200       size_type const old_size = this->size();
2201       this->priv_set_difference_back(first, last, comp);
2202       T *const raw_beg = this->priv_raw_begin();
2203       T *const raw_end = this->priv_raw_end();
2204       T *raw_pos = raw_beg + old_size;
2205       boost::movelib::adaptive_merge(raw_beg, raw_pos, raw_end, comp, raw_end, this->capacity() - this->size());
2206    }
2207 
2208    private:
2209    template<class PositionValue>
priv_insert_ordered_at(const size_type element_count,PositionValue position_value)2210    void priv_insert_ordered_at(const size_type element_count, PositionValue position_value)
2211    {
2212       const size_type old_size_pos = this->size();
2213       this->reserve(old_size_pos + element_count);
2214       T* const begin_ptr = this->priv_raw_begin();
2215       size_type insertions_left = element_count;
2216       size_type prev_pos = old_size_pos;
2217       size_type old_hole_size = element_count;
2218 
2219       //Exception rollback. If any copy throws before the hole is filled, values
2220       //already inserted/copied at the end of the buffer will be destroyed.
2221       typename value_traits::ArrayDestructor past_hole_values_destroyer
2222          (begin_ptr + old_size_pos + element_count, this->m_holder.alloc(), size_type(0u));
2223       //Loop for each insertion backwards, first moving the elements after the insertion point,
2224       //then inserting the element.
2225       while(insertions_left){
2226          --position_value;
2227          size_type const pos = position_value.get_pos();
2228          BOOST_ASSERT(pos != size_type(-1) && pos <= old_size_pos && pos <= prev_pos);
2229          //If needed shift the range after the insertion point and the previous insertion point.
2230          //Function will take care if the shift crosses the size() boundary, using copy/move
2231          //or uninitialized copy/move if necessary.
2232          size_type new_hole_size = (pos != prev_pos)
2233             ? priv_insert_ordered_at_shift_range(pos, prev_pos, this->size(), insertions_left)
2234             : old_hole_size
2235             ;
2236          if(new_hole_size){
2237             //The hole was reduced by priv_insert_ordered_at_shift_range so expand exception rollback range backwards
2238             past_hole_values_destroyer.increment_size_backwards(prev_pos - pos);
2239             //Insert the new value in the hole
2240             allocator_traits_type::construct(this->m_holder.alloc(), begin_ptr + pos + insertions_left - 1, position_value.get_val());
2241             if(--new_hole_size){
2242                //The hole was reduced by the new insertion by one
2243                past_hole_values_destroyer.increment_size_backwards(size_type(1u));
2244             }
2245             else{
2246                //Hole was just filled, disable exception rollback and change vector size
2247                past_hole_values_destroyer.release();
2248                this->m_holder.m_size += element_count;
2249             }
2250          }
2251          else{
2252             if(old_hole_size){
2253                //Hole was just filled by priv_insert_ordered_at_shift_range, disable exception rollback and change vector size
2254                past_hole_values_destroyer.release();
2255                this->m_holder.m_size += element_count;
2256             }
2257             //Insert the new value in the already constructed range
2258             begin_ptr[pos + insertions_left - 1] = position_value.get_val();
2259          }
2260          --insertions_left;
2261          old_hole_size = new_hole_size;
2262          prev_pos = pos;
2263       }
2264    }
2265 
2266    template<class InputIt, class Compare>
priv_set_difference_back(InputIt first1,InputIt last1,Compare comp)2267    void priv_set_difference_back(InputIt first1, InputIt last1, Compare comp)
2268    {
2269       T * old_first2 = this->priv_raw_begin();
2270       T * first2 = old_first2;
2271       T * last2  = this->priv_raw_end();
2272 
2273       while (first1 != last1) {
2274          if (first2 == last2){
2275             this->insert(this->cend(), first1, last1);
2276             return;
2277          }
2278 
2279          if (comp(*first1, *first2)) {
2280             this->emplace_back(*first1);
2281             T * const raw_begin = this->priv_raw_begin();
2282             if(old_first2 != raw_begin)
2283             {
2284                //Reallocation happened, update range
2285                first2 = raw_begin + (first2 - old_first2);
2286                last2  = raw_begin + (last2 - old_first2);
2287                old_first2 = raw_begin;
2288             }
2289             ++first1;
2290          }
2291          else {
2292             if (!comp(*first2, *first1)) {
2293                ++first1;
2294             }
2295             ++first2;
2296          }
2297       }
2298    }
2299 
2300    template<class FwdIt, class Compare>
priv_merge_in_new_buffer(FwdIt,size_type,Compare,version_0)2301    BOOST_CONTAINER_FORCEINLINE void priv_merge_in_new_buffer(FwdIt, size_type, Compare, version_0)
2302    {
2303       alloc_holder_t::on_capacity_overflow();
2304    }
2305 
2306    template<class FwdIt, class Compare, class Version>
priv_merge_in_new_buffer(FwdIt first,size_type n,Compare comp,Version)2307    void priv_merge_in_new_buffer(FwdIt first, size_type n, Compare comp, Version)
2308    {
2309       size_type const new_size = this->size() + n;
2310       size_type new_cap = new_size;
2311       pointer p = pointer();
2312       pointer const new_storage = this->m_holder.allocation_command(allocate_new, new_size, new_cap, p);
2313 
2314       BOOST_ASSERT((new_cap >= this->size() ) && (new_cap - this->size()) >= n);
2315       allocator_type &a = this->m_holder.alloc();
2316       typename value_traits::ArrayDeallocator new_buffer_deallocator(new_storage, a, new_cap);
2317       typename value_traits::ArrayDestructor  new_values_destroyer(new_storage, a, 0u);
2318       T* pbeg  = this->priv_raw_begin();
2319       size_type const old_size = this->size();
2320       T* const pend = pbeg + old_size;
2321       T* d_first = boost::movelib::to_raw_pointer(new_storage);
2322       size_type added = n;
2323       //Merge in new buffer loop
2324       while(1){
2325          if(!n) {
2326             ::boost::container::uninitialized_move_alloc(this->m_holder.alloc(), pbeg, pend, d_first);
2327             break;
2328          }
2329          else if(pbeg == pend) {
2330             ::boost::container::uninitialized_move_alloc_n(this->m_holder.alloc(), first, n, d_first);
2331             break;
2332          }
2333          //maintain stability moving external values only if they are strictly less
2334          else if(comp(*first, *pbeg)) {
2335             allocator_traits_type::construct( this->m_holder.alloc(), d_first, *first );
2336             new_values_destroyer.increment_size(1u);
2337             ++first;
2338             --n;
2339             ++d_first;
2340          }
2341          else{
2342             allocator_traits_type::construct( this->m_holder.alloc(), d_first, boost::move(*pbeg) );
2343             new_values_destroyer.increment_size(1u);
2344             ++pbeg;
2345             ++d_first;
2346          }
2347       }
2348 
2349       //Nothrow operations
2350       pointer const old_p     = this->m_holder.start();
2351       size_type const old_cap = this->m_holder.capacity();
2352       boost::container::destroy_alloc_n(a, boost::movelib::to_raw_pointer(old_p), old_size);
2353       if (old_cap > 0) {
2354          this->m_holder.deallocate(old_p, old_cap);
2355       }
2356       this->m_holder.m_size = old_size + added;
2357       this->m_holder.start(new_storage);
2358       this->m_holder.capacity(new_cap);
2359       new_buffer_deallocator.release();
2360       new_values_destroyer.release();
2361    }
2362 
room_enough() const2363    BOOST_CONTAINER_FORCEINLINE bool room_enough() const
2364    {  return this->m_holder.m_size < this->m_holder.capacity();   }
2365 
back_ptr() const2366    BOOST_CONTAINER_FORCEINLINE pointer back_ptr() const
2367    {  return this->m_holder.start() + this->m_holder.m_size;  }
2368 
priv_index_of(pointer p) const2369    size_type priv_index_of(pointer p) const
2370    {
2371       BOOST_ASSERT(this->m_holder.start() <= p);
2372       BOOST_ASSERT(p <= (this->m_holder.start()+this->size()));
2373       return static_cast<size_type>(p - this->m_holder.start());
2374    }
2375 
2376    template<class OtherA>
priv_move_assign(BOOST_RV_REF_BEG vector<T,OtherA,Options> BOOST_RV_REF_END x,typename dtl::enable_if_c<dtl::is_version<typename real_allocator<T,OtherA>::type,0>::value>::type * =0)2377    void priv_move_assign(BOOST_RV_REF_BEG vector<T, OtherA, Options> BOOST_RV_REF_END x
2378       , typename dtl::enable_if_c
2379          < dtl::is_version<typename real_allocator<T, OtherA>::type, 0>::value >::type * = 0)
2380    {
2381       if(!dtl::is_same<typename real_allocator<T, OtherA>::type, allocator_type>::value &&
2382           this->capacity() < x.size()){
2383          alloc_holder_t::on_capacity_overflow();
2384       }
2385       T* const this_start  = this->priv_raw_begin();
2386       T* const other_start = x.priv_raw_begin();
2387       const size_type this_sz  = m_holder.m_size;
2388       const size_type other_sz = static_cast<size_type>(x.m_holder.m_size);
2389       boost::container::move_assign_range_alloc_n(this->m_holder.alloc(), other_start, other_sz, this_start, this_sz);
2390       this->m_holder.m_size = other_sz;
2391       //Not emptying the source container seems to be confusing for users as drop-in
2392       //replacement for non-static vectors, so clear it.
2393       x.clear();
2394    }
2395 
2396    template<class OtherA>
priv_move_assign(BOOST_RV_REF_BEG vector<T,OtherA,Options> BOOST_RV_REF_END x,typename dtl::disable_if_or<void,dtl::is_version<typename real_allocator<T,OtherA>::type,0>,dtl::is_different<typename real_allocator<T,OtherA>::type,allocator_type>>::type * =0)2397    void priv_move_assign(BOOST_RV_REF_BEG vector<T, OtherA, Options> BOOST_RV_REF_END x
2398       , typename dtl::disable_if_or
2399          < void
2400          , dtl::is_version<typename real_allocator<T, OtherA>::type, 0>
2401          , dtl::is_different<typename real_allocator<T, OtherA>::type, allocator_type>
2402          >::type * = 0)
2403    {
2404       //for move assignment, no aliasing (&x != this) is assumed.
2405       //x.size() == 0 is allowed for buggy std libraries.
2406       BOOST_ASSERT(this != &x || x.size() == 0);
2407       allocator_type &this_alloc = this->m_holder.alloc();
2408       allocator_type &x_alloc    = x.m_holder.alloc();
2409       const bool propagate_alloc = allocator_traits_type::propagate_on_container_move_assignment::value;
2410 
2411       //In this allocator move constructor the allocator maybe will be propagated -----------------------v
2412       const bool is_propagable_from_x = is_propagable_from(x_alloc, x.m_holder.start(), this_alloc, propagate_alloc);
2413 
2414       //Resources can be transferred if both allocators are
2415       //going to be equal after this function (either propagated or already equal)
2416       if(is_propagable_from_x){
2417          this->clear();
2418          if(BOOST_LIKELY(!!this->m_holder.m_start))
2419             this->m_holder.deallocate(this->m_holder.m_start, this->m_holder.m_capacity);
2420          this->m_holder.steal_resources(x.m_holder);
2421       }
2422       //Else do a one by one move. Also, clear the source as users find confusing
2423       //elements are still alive in the source container.
2424       else{
2425          this->assign( boost::make_move_iterator(boost::movelib::iterator_to_raw_pointer(x.begin()))
2426                      , boost::make_move_iterator(boost::movelib::iterator_to_raw_pointer(x.end()  ))
2427                      );
2428          x.clear();
2429       }
2430       //Move allocator if needed
2431       dtl::move_alloc(this_alloc, x_alloc, dtl::bool_<propagate_alloc>());
2432    }
2433 
2434    template<class OtherA>
priv_copy_assign(const vector<T,OtherA,Options> & x,typename dtl::enable_if_c<dtl::is_version<typename real_allocator<T,OtherA>::type,0>::value>::type * =0)2435    void priv_copy_assign(const vector<T, OtherA, Options> &x
2436       , typename dtl::enable_if_c
2437          < dtl::is_version<typename real_allocator<T, OtherA>::type, 0>::value >::type * = 0)
2438    {
2439       if(!dtl::is_same<typename real_allocator<T, OtherA>::type, allocator_type>::value &&
2440          this->capacity() < x.size()){
2441          alloc_holder_t::on_capacity_overflow();
2442       }
2443       T* const this_start  = this->priv_raw_begin();
2444       T* const other_start = x.priv_raw_begin();
2445       const size_type this_sz  = m_holder.m_size;
2446       const size_type other_sz = static_cast<size_type>(x.m_holder.m_size);
2447       boost::container::copy_assign_range_alloc_n(this->m_holder.alloc(), other_start, other_sz, this_start, this_sz);
2448       this->m_holder.m_size = other_sz;
2449    }
2450 
2451    template<class OtherA>
2452    typename dtl::disable_if_or
2453       < void
2454       , dtl::is_version<typename real_allocator<T, OtherA>::type, 0>
2455       , dtl::is_different<typename real_allocator<T, OtherA>::type, allocator_type>
2456       >::type
priv_copy_assign(const vector<T,OtherA,Options> & x)2457       priv_copy_assign(const vector<T, OtherA, Options> &x)
2458    {
2459       allocator_type &this_alloc     = this->m_holder.alloc();
2460       const allocator_type &x_alloc  = x.m_holder.alloc();
2461       dtl::bool_<allocator_traits_type::
2462          propagate_on_container_copy_assignment::value> flag;
2463       if(flag && this_alloc != x_alloc){
2464          this->clear();
2465          this->shrink_to_fit();
2466       }
2467       dtl::assign_alloc(this_alloc, x_alloc, flag);
2468       this->assign( x.priv_raw_begin(), x.priv_raw_end() );
2469    }
2470 
2471    template<class Vector>  //Template it to avoid it in explicit instantiations
priv_swap(Vector & x,dtl::true_type)2472    void priv_swap(Vector &x, dtl::true_type)   //version_0
2473    {  this->m_holder.deep_swap(x.m_holder);  }
2474 
2475    template<class Vector>  //Template it to avoid it in explicit instantiations
priv_swap(Vector & x,dtl::false_type)2476    void priv_swap(Vector &x, dtl::false_type)  //version_N
2477    {
2478       const bool propagate_alloc = allocator_traits_type::propagate_on_container_swap::value;
2479       if(are_swap_propagable( this->get_stored_allocator(), this->m_holder.start()
2480                             , x.get_stored_allocator(), x.m_holder.start(), propagate_alloc)){
2481          //Just swap internals
2482          this->m_holder.swap_resources(x.m_holder);
2483       }
2484       else{
2485          if (BOOST_UNLIKELY(&x == this))
2486             return;
2487 
2488          //Else swap element by element...
2489          bool const t_smaller = this->size() < x.size();
2490          vector &sml = t_smaller ? *this : x;
2491          vector &big = t_smaller ? x : *this;
2492 
2493          size_type const common_elements = sml.size();
2494          for(size_type i = 0; i != common_elements; ++i){
2495             boost::adl_move_swap(sml[i], big[i]);
2496          }
2497          //... and move-insert the remaining range
2498          sml.insert( sml.cend()
2499                    , boost::make_move_iterator(boost::movelib::iterator_to_raw_pointer(big.nth(common_elements)))
2500                    , boost::make_move_iterator(boost::movelib::iterator_to_raw_pointer(big.end()))
2501                    );
2502          //Destroy remaining elements
2503          big.erase(big.nth(common_elements), big.cend());
2504       }
2505       //And now swap the allocator
2506       dtl::swap_alloc(this->m_holder.alloc(), x.m_holder.alloc(), dtl::bool_<propagate_alloc>());
2507    }
2508 
priv_reserve_no_capacity(size_type,version_0)2509    void priv_reserve_no_capacity(size_type, version_0)
2510    {  alloc_holder_t::on_capacity_overflow();  }
2511 
priv_dummy_empty_proxy()2512    dtl::insert_range_proxy<allocator_type, boost::move_iterator<T*>, T*> priv_dummy_empty_proxy()
2513    {
2514       return dtl::insert_range_proxy<allocator_type, boost::move_iterator<T*>, T*>
2515          (::boost::make_move_iterator((T *)0));
2516    }
2517 
priv_reserve_no_capacity(size_type new_cap,version_1)2518    void priv_reserve_no_capacity(size_type new_cap, version_1)
2519    {
2520       //There is not enough memory, allocate a new buffer
2521       //Pass the hint so that allocators can take advantage of this.
2522       pointer const p = this->m_holder.allocate(new_cap);
2523       //We will reuse insert code, so create a dummy input iterator
2524       this->priv_forward_range_insert_new_allocation
2525          ( boost::movelib::to_raw_pointer(p), new_cap, this->priv_raw_end(), 0, this->priv_dummy_empty_proxy());
2526    }
2527 
priv_reserve_no_capacity(size_type new_cap,version_2)2528    void priv_reserve_no_capacity(size_type new_cap, version_2)
2529    {
2530       //There is not enough memory, allocate a new
2531       //buffer or expand the old one.
2532       bool same_buffer_start;
2533       size_type real_cap = 0;
2534       pointer reuse(this->m_holder.start());
2535       pointer const ret(this->m_holder.allocation_command(allocate_new | expand_fwd | expand_bwd, new_cap, real_cap = new_cap, reuse));
2536 
2537       //Check for forward expansion
2538       same_buffer_start = reuse && this->m_holder.start() == ret;
2539       if(same_buffer_start){
2540          #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
2541          ++this->num_expand_fwd;
2542          #endif
2543          this->m_holder.capacity(real_cap);
2544       }
2545       else{ //If there is no forward expansion, move objects, we will reuse insertion code
2546          T * const new_mem = boost::movelib::to_raw_pointer(ret);
2547          T * const ins_pos = this->priv_raw_end();
2548          if(reuse){   //Backwards (and possibly forward) expansion
2549             #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
2550             ++this->num_expand_bwd;
2551             #endif
2552             this->priv_forward_range_insert_expand_backwards
2553                ( new_mem , real_cap, ins_pos, 0, this->priv_dummy_empty_proxy());
2554          }
2555          else{ //New buffer
2556             #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
2557             ++this->num_alloc;
2558             #endif
2559             this->priv_forward_range_insert_new_allocation
2560                ( new_mem, real_cap, ins_pos, 0, this->priv_dummy_empty_proxy());
2561          }
2562       }
2563    }
2564 
priv_destroy_last(const bool moved=false)2565    void priv_destroy_last(const bool moved = false) BOOST_NOEXCEPT_OR_NOTHROW
2566    {
2567       (void)moved;
2568       const bool skip_destructor = value_traits::trivial_dctr || (value_traits::trivial_dctr_after_move && moved);
2569       if(!skip_destructor){
2570          value_type* const p = this->priv_raw_end() - 1;
2571          allocator_traits_type::destroy(this->get_stored_allocator(), p);
2572       }
2573       --this->m_holder.m_size;
2574    }
2575 
priv_destroy_last_n(const size_type n)2576    void priv_destroy_last_n(const size_type n) BOOST_NOEXCEPT_OR_NOTHROW
2577    {
2578       BOOST_ASSERT(n <= this->m_holder.m_size);
2579       if(!value_traits::trivial_dctr){
2580          T* const destroy_pos = this->priv_raw_begin() + (this->m_holder.m_size-n);
2581          boost::container::destroy_alloc_n(this->get_stored_allocator(), destroy_pos, n);
2582       }
2583       this->m_holder.m_size -= n;
2584    }
2585 
2586    template<class InpIt>
priv_uninitialized_construct_at_end(InpIt first,InpIt last)2587    void priv_uninitialized_construct_at_end(InpIt first, InpIt last)
2588    {
2589       T* const old_end_pos = this->priv_raw_end();
2590       T* const new_end_pos = boost::container::uninitialized_copy_alloc(this->m_holder.alloc(), first, last, old_end_pos);
2591       this->m_holder.m_size += new_end_pos - old_end_pos;
2592    }
2593 
priv_destroy_all()2594    void priv_destroy_all() BOOST_NOEXCEPT_OR_NOTHROW
2595    {
2596       boost::container::destroy_alloc_n
2597          (this->get_stored_allocator(), this->priv_raw_begin(), this->m_holder.m_size);
2598       this->m_holder.m_size = 0;
2599    }
2600 
2601    template<class U>
priv_insert(const const_iterator & p,BOOST_FWD_REF (U)x)2602    iterator priv_insert(const const_iterator &p, BOOST_FWD_REF(U) x)
2603    {
2604       BOOST_ASSERT(this->priv_in_range_or_end(p));
2605       return this->priv_forward_range_insert
2606          ( vector_iterator_get_ptr(p), 1, dtl::get_insert_value_proxy<T*, allocator_type>(::boost::forward<U>(x)));
2607    }
2608 
priv_single_insert_proxy(const T & x)2609    BOOST_CONTAINER_FORCEINLINE dtl::insert_copy_proxy<allocator_type, T*> priv_single_insert_proxy(const T &x)
2610    {  return dtl::insert_copy_proxy<allocator_type, T*> (x);  }
2611 
priv_single_insert_proxy(BOOST_RV_REF (T)x)2612    BOOST_CONTAINER_FORCEINLINE dtl::insert_move_proxy<allocator_type, T*> priv_single_insert_proxy(BOOST_RV_REF(T) x)
2613    {  return dtl::insert_move_proxy<allocator_type, T*> (x);  }
2614 
2615    template <class U>
priv_push_back(BOOST_FWD_REF (U)u)2616    void priv_push_back(BOOST_FWD_REF(U) u)
2617    {
2618       if (BOOST_LIKELY(this->room_enough())){
2619          //There is more memory, just construct a new object at the end
2620          allocator_traits_type::construct
2621             ( this->m_holder.alloc(), this->priv_raw_end(), ::boost::forward<U>(u) );
2622          ++this->m_holder.m_size;
2623       }
2624       else{
2625          this->priv_forward_range_insert_no_capacity
2626             ( this->back_ptr(), 1
2627             , this->priv_single_insert_proxy(::boost::forward<U>(u)), alloc_version());
2628       }
2629    }
2630 
priv_resize_proxy(const T & x)2631    BOOST_CONTAINER_FORCEINLINE dtl::insert_n_copies_proxy<allocator_type, T*> priv_resize_proxy(const T &x)
2632    {  return dtl::insert_n_copies_proxy<allocator_type, T*>(x);   }
2633 
priv_resize_proxy(default_init_t)2634    BOOST_CONTAINER_FORCEINLINE dtl::insert_default_initialized_n_proxy<allocator_type, T*> priv_resize_proxy(default_init_t)
2635    {  return dtl::insert_default_initialized_n_proxy<allocator_type, T*>();  }
2636 
priv_resize_proxy(value_init_t)2637    BOOST_CONTAINER_FORCEINLINE dtl::insert_value_initialized_n_proxy<allocator_type, T*> priv_resize_proxy(value_init_t)
2638    {  return dtl::insert_value_initialized_n_proxy<allocator_type, T*>(); }
2639 
2640    template <class U>
priv_resize(size_type new_size,const U & u)2641    void priv_resize(size_type new_size, const U& u)
2642    {
2643       const size_type sz = this->size();
2644       if (new_size < sz){
2645          //Destroy last elements
2646          this->priv_destroy_last_n(sz - new_size);
2647       }
2648       else{
2649          const size_type n = new_size - this->size();
2650          this->priv_forward_range_insert_at_end(n, this->priv_resize_proxy(u), alloc_version());
2651       }
2652    }
2653 
priv_shrink_to_fit(version_0)2654    BOOST_CONTAINER_FORCEINLINE void priv_shrink_to_fit(version_0) BOOST_NOEXCEPT_OR_NOTHROW
2655    {}
2656 
priv_shrink_to_fit(version_1)2657    void priv_shrink_to_fit(version_1)
2658    {
2659       const size_type cp = this->m_holder.capacity();
2660       if(cp){
2661          const size_type sz = this->size();
2662          if(!sz){
2663             if(BOOST_LIKELY(!!this->m_holder.m_start))
2664                this->m_holder.deallocate(this->m_holder.m_start, cp);
2665             this->m_holder.m_start     = pointer();
2666             this->m_holder.m_capacity  = 0;
2667          }
2668          else if(sz < cp){
2669             //Allocate a new buffer.
2670             //Pass the hint so that allocators can take advantage of this.
2671             pointer const p = this->m_holder.allocate(sz);
2672 
2673             //We will reuse insert code, so create a dummy input iterator
2674             #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
2675             ++this->num_alloc;
2676             #endif
2677             this->priv_forward_range_insert_new_allocation
2678                ( boost::movelib::to_raw_pointer(p), sz
2679                , this->priv_raw_begin(), 0, this->priv_dummy_empty_proxy());
2680          }
2681       }
2682    }
2683 
priv_shrink_to_fit(version_2)2684    void priv_shrink_to_fit(version_2) BOOST_NOEXCEPT_OR_NOTHROW
2685    {
2686       const size_type cp = this->m_holder.capacity();
2687       if(cp){
2688          const size_type sz = this->size();
2689          if(!sz){
2690             if(BOOST_LIKELY(!!this->m_holder.m_start))
2691                this->m_holder.deallocate(this->m_holder.m_start, cp);
2692             this->m_holder.m_start     = pointer();
2693             this->m_holder.m_capacity  = 0;
2694          }
2695          else{
2696             size_type received_size = sz;
2697             pointer reuse(this->m_holder.start());
2698             if(this->m_holder.allocation_command
2699                (shrink_in_place | nothrow_allocation, cp, received_size, reuse)){
2700                this->m_holder.capacity(received_size);
2701                #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
2702                ++this->num_shrink;
2703                #endif
2704             }
2705          }
2706       }
2707    }
2708 
2709    template <class InsertionProxy>
priv_forward_range_insert_no_capacity(const pointer & pos,const size_type,const InsertionProxy,version_0)2710    iterator priv_forward_range_insert_no_capacity
2711       (const pointer &pos, const size_type, const InsertionProxy , version_0)
2712    {
2713       alloc_holder_t::on_capacity_overflow();
2714       return iterator(pos);
2715    }
2716 
2717    template <class InsertionProxy>
priv_forward_range_insert_no_capacity(const pointer & pos,const size_type n,const InsertionProxy insert_range_proxy,version_1)2718    iterator priv_forward_range_insert_no_capacity
2719       (const pointer &pos, const size_type n, const InsertionProxy insert_range_proxy, version_1)
2720    {
2721       //Check if we have enough memory or try to expand current memory
2722       const size_type n_pos = pos - this->m_holder.start();
2723       T *const raw_pos = boost::movelib::to_raw_pointer(pos);
2724 
2725       const size_type new_cap = this->m_holder.template next_capacity<growth_factor_type>(n);
2726       //Pass the hint so that allocators can take advantage of this.
2727       T * const new_buf = boost::movelib::to_raw_pointer(this->m_holder.allocate(new_cap));
2728       #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
2729       ++this->num_alloc;
2730       #endif
2731       this->priv_forward_range_insert_new_allocation
2732          ( new_buf, new_cap, raw_pos, n, insert_range_proxy);
2733       return iterator(this->m_holder.start() + n_pos);
2734    }
2735 
2736    template <class InsertionProxy>
priv_forward_range_insert_no_capacity(const pointer & pos,const size_type n,const InsertionProxy insert_range_proxy,version_2)2737    iterator priv_forward_range_insert_no_capacity
2738       (const pointer &pos, const size_type n, const InsertionProxy insert_range_proxy, version_2)
2739    {
2740       //Check if we have enough memory or try to expand current memory
2741       T *const raw_pos = boost::movelib::to_raw_pointer(pos);
2742       const size_type n_pos = raw_pos - this->priv_raw_begin();
2743 
2744       //There is not enough memory, allocate a new
2745       //buffer or expand the old one.
2746       size_type real_cap = this->m_holder.template next_capacity<growth_factor_type>(n);
2747       pointer reuse(this->m_holder.start());
2748       pointer const ret (this->m_holder.allocation_command
2749          (allocate_new | expand_fwd | expand_bwd, this->m_holder.m_size + n, real_cap, reuse));
2750 
2751       //Buffer reallocated
2752       if(reuse){
2753          //Forward expansion, delay insertion
2754          if(this->m_holder.start() == ret){
2755             #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
2756             ++this->num_expand_fwd;
2757             #endif
2758             this->m_holder.capacity(real_cap);
2759             //Expand forward
2760             this->priv_forward_range_insert_expand_forward(raw_pos, n, insert_range_proxy);
2761          }
2762          //Backwards (and possibly forward) expansion
2763          else{
2764             #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
2765             ++this->num_expand_bwd;
2766             #endif
2767             this->priv_forward_range_insert_expand_backwards
2768                (boost::movelib::to_raw_pointer(ret), real_cap, raw_pos, n, insert_range_proxy);
2769          }
2770       }
2771       //New buffer
2772       else{
2773          #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
2774          ++this->num_alloc;
2775          #endif
2776          this->priv_forward_range_insert_new_allocation
2777             ( boost::movelib::to_raw_pointer(ret), real_cap, raw_pos, n, insert_range_proxy);
2778       }
2779 
2780       return iterator(this->m_holder.start() + n_pos);
2781    }
2782 
2783    template <class InsertionProxy>
priv_forward_range_insert(const pointer & pos,const size_type n,const InsertionProxy insert_range_proxy)2784    iterator priv_forward_range_insert
2785       (const pointer &pos, const size_type n, const InsertionProxy insert_range_proxy)
2786    {
2787       BOOST_ASSERT(this->m_holder.capacity() >= this->m_holder.m_size);
2788       //Check if we have enough memory or try to expand current memory
2789       const size_type remaining = this->m_holder.capacity() - this->m_holder.m_size;
2790 
2791       bool same_buffer_start = n <= remaining;
2792       if (!same_buffer_start){
2793          return priv_forward_range_insert_no_capacity(pos, n, insert_range_proxy, alloc_version());
2794       }
2795       else{
2796          //Expand forward
2797          T *const raw_pos = boost::movelib::to_raw_pointer(pos);
2798          const size_type n_pos = raw_pos - this->priv_raw_begin();
2799          this->priv_forward_range_insert_expand_forward(raw_pos, n, insert_range_proxy);
2800          return iterator(this->m_holder.start() + n_pos);
2801       }
2802    }
2803 
2804    template <class InsertionProxy>
priv_forward_range_insert_at_end(const size_type n,const InsertionProxy insert_range_proxy,version_0)2805    iterator priv_forward_range_insert_at_end
2806       (const size_type n, const InsertionProxy insert_range_proxy, version_0)
2807    {
2808       //Check if we have enough memory or try to expand current memory
2809       const size_type remaining = this->m_holder.capacity() - this->m_holder.m_size;
2810 
2811       if (n > remaining){
2812          //This will trigger an error
2813          alloc_holder_t::on_capacity_overflow();
2814       }
2815       this->priv_forward_range_insert_at_end_expand_forward(n, insert_range_proxy);
2816       return this->end();
2817    }
2818 
2819    template <class InsertionProxy, class AllocVersion>
priv_forward_range_insert_at_end(const size_type n,const InsertionProxy insert_range_proxy,AllocVersion)2820    BOOST_CONTAINER_FORCEINLINE iterator priv_forward_range_insert_at_end
2821       (const size_type n, const InsertionProxy insert_range_proxy, AllocVersion)
2822    {
2823       return this->priv_forward_range_insert(this->back_ptr(), n, insert_range_proxy);
2824    }
2825 
2826    //Takes the range pointed by [first_pos, last_pos) and shifts it to the right
2827    //by 'shift_count'. 'limit_pos' marks the end of constructed elements.
2828    //
2829    //Precondition: first_pos <= last_pos <= limit_pos
2830    //
2831    //The shift operation might cross limit_pos so elements to moved beyond limit_pos
2832    //are uninitialized_moved with an allocator. Other elements are moved.
2833    //
2834    //The shift operation might left uninitialized elements after limit_pos
2835    //and the number of uninitialized elements is returned by the function.
2836    //
2837    //Old situation:
2838    //       first_pos   last_pos         old_limit
2839    //             |       |                  |
2840    // ____________V_______V__________________V_____________
2841    //|   prefix   | range |     suffix       |raw_mem      ~
2842    //|____________|_______|__________________|_____________~
2843    //
2844    //New situation in Case A (hole_size == 0):
2845    // range is moved through move assignments
2846    //
2847    //       first_pos   last_pos         limit_pos
2848    //             |       |                  |
2849    // ____________V_______V__________________V_____________
2850    //|   prefix'  |       |  | range |suffix'|raw_mem      ~
2851    //|________________+______|___^___|_______|_____________~
2852    //                 |          |
2853    //                 |_>_>_>_>_>^
2854    //
2855    //
2856    //New situation in Case B (hole_size >= 0):
2857    // range is moved through uninitialized moves
2858    //
2859    //       first_pos   last_pos         limit_pos
2860    //             |       |                  |
2861    // ____________V_______V__________________V________________
2862    //|    prefix' |       |                  | [hole] | range |
2863    //|_______________________________________|________|___^___|
2864    //                 |                                   |
2865    //                 |_>_>_>_>_>_>_>_>_>_>_>_>_>_>_>_>_>_^
2866    //
2867    //New situation in Case C (hole_size == 0):
2868    // range is moved through move assignments and uninitialized moves
2869    //
2870    //       first_pos   last_pos         limit_pos
2871    //             |       |                  |
2872    // ____________V_______V__________________V___
2873    //|   prefix'  |       |              | range |
2874    //|___________________________________|___^___|
2875    //                 |                      |
2876    //                 |_>_>_>_>_>_>_>_>_>_>_>^
priv_insert_ordered_at_shift_range(size_type first_pos,size_type last_pos,size_type limit_pos,size_type shift_count)2877    size_type priv_insert_ordered_at_shift_range
2878       (size_type first_pos, size_type last_pos, size_type limit_pos, size_type shift_count)
2879    {
2880       BOOST_ASSERT(first_pos <= last_pos);
2881       BOOST_ASSERT(last_pos <= limit_pos);
2882       //
2883       T* const begin_ptr = this->priv_raw_begin();
2884       T* const first_ptr = begin_ptr + first_pos;
2885       T* const last_ptr  = begin_ptr + last_pos;
2886 
2887       size_type hole_size = 0;
2888       //Case A:
2889       if((last_pos + shift_count) <= limit_pos){
2890          //All move assigned
2891          boost::container::move_backward(first_ptr, last_ptr, last_ptr + shift_count);
2892       }
2893       //Case B:
2894       else if((first_pos + shift_count) >= limit_pos){
2895          //All uninitialized_moved
2896          ::boost::container::uninitialized_move_alloc
2897             (this->m_holder.alloc(), first_ptr, last_ptr, first_ptr + shift_count);
2898          hole_size = first_pos + shift_count - limit_pos;
2899       }
2900       //Case C:
2901       else{
2902          //Some uninitialized_moved
2903          T* const limit_ptr    = begin_ptr + limit_pos;
2904          T* const boundary_ptr = limit_ptr - shift_count;
2905          ::boost::container::uninitialized_move_alloc(this->m_holder.alloc(), boundary_ptr, last_ptr, limit_ptr);
2906          //The rest is move assigned
2907          boost::container::move_backward(first_ptr, boundary_ptr, limit_ptr);
2908       }
2909       return hole_size;
2910    }
2911 
2912    private:
priv_raw_begin() const2913    BOOST_CONTAINER_FORCEINLINE T *priv_raw_begin() const
2914    {  return boost::movelib::to_raw_pointer(m_holder.start());  }
2915 
priv_raw_end() const2916    BOOST_CONTAINER_FORCEINLINE T* priv_raw_end() const
2917    {  return this->priv_raw_begin() + this->m_holder.m_size;  }
2918 
2919    template <class InsertionProxy>
priv_forward_range_insert_at_end_expand_forward(const size_type n,InsertionProxy insert_range_proxy)2920    void priv_forward_range_insert_at_end_expand_forward(const size_type n, InsertionProxy insert_range_proxy)
2921    {
2922       T* const old_finish = this->priv_raw_end();
2923       insert_range_proxy.uninitialized_copy_n_and_update(this->m_holder.alloc(), old_finish, n);
2924       this->m_holder.m_size += n;
2925    }
2926 
2927    template <class InsertionProxy>
priv_forward_range_insert_expand_forward(T * const pos,const size_type n,InsertionProxy insert_range_proxy)2928    void priv_forward_range_insert_expand_forward(T* const pos, const size_type n, InsertionProxy insert_range_proxy)
2929    {
2930       //n can't be 0, because there is nothing to do in that case
2931       if(BOOST_UNLIKELY(!n)) return;
2932       //There is enough memory
2933       T* const old_finish = this->priv_raw_end();
2934       const size_type elems_after = old_finish - pos;
2935 
2936       if (!elems_after){
2937          insert_range_proxy.uninitialized_copy_n_and_update(this->m_holder.alloc(), old_finish, n);
2938          this->m_holder.m_size += n;
2939       }
2940       else if (elems_after >= n){
2941          //New elements can be just copied.
2942          //Move to uninitialized memory last objects
2943          ::boost::container::uninitialized_move_alloc
2944             (this->m_holder.alloc(), old_finish - n, old_finish, old_finish);
2945          this->m_holder.m_size += n;
2946          //Copy previous to last objects to the initialized end
2947          boost::container::move_backward(pos, old_finish - n, old_finish);
2948          //Insert new objects in the pos
2949          insert_range_proxy.copy_n_and_update(this->m_holder.alloc(), pos, n);
2950       }
2951       else {
2952          //The new elements don't fit in the [pos, end()) range.
2953 
2954          //Copy old [pos, end()) elements to the uninitialized memory (a gap is created)
2955          ::boost::container::uninitialized_move_alloc(this->m_holder.alloc(), pos, old_finish, pos + n);
2956          BOOST_TRY{
2957             //Copy first new elements in pos (gap is still there)
2958             insert_range_proxy.copy_n_and_update(this->m_holder.alloc(), pos, elems_after);
2959             //Copy to the beginning of the unallocated zone the last new elements (the gap is closed).
2960             insert_range_proxy.uninitialized_copy_n_and_update(this->m_holder.alloc(), old_finish, n - elems_after);
2961             this->m_holder.m_size += n;
2962          }
2963          BOOST_CATCH(...){
2964             boost::container::destroy_alloc_n(this->get_stored_allocator(), pos + n, elems_after);
2965             BOOST_RETHROW
2966          }
2967          BOOST_CATCH_END
2968       }
2969    }
2970 
2971    template <class InsertionProxy>
priv_forward_range_insert_new_allocation(T * const new_start,size_type new_cap,T * const pos,const size_type n,InsertionProxy insert_range_proxy)2972    void priv_forward_range_insert_new_allocation
2973       (T* const new_start, size_type new_cap, T* const pos, const size_type n, InsertionProxy insert_range_proxy)
2974    {
2975       //n can be zero, if we want to reallocate!
2976       T *new_finish = new_start;
2977       T *old_finish;
2978       //Anti-exception rollbacks
2979       typename value_traits::ArrayDeallocator new_buffer_deallocator(new_start, this->m_holder.alloc(), new_cap);
2980       typename value_traits::ArrayDestructor  new_values_destroyer(new_start, this->m_holder.alloc(), 0u);
2981 
2982       //Initialize with [begin(), pos) old buffer
2983       //the start of the new buffer
2984       T * const old_buffer = this->priv_raw_begin();
2985       if(old_buffer){
2986          new_finish = ::boost::container::uninitialized_move_alloc
2987             (this->m_holder.alloc(), this->priv_raw_begin(), pos, old_finish = new_finish);
2988          new_values_destroyer.increment_size(new_finish - old_finish);
2989       }
2990       //Initialize new objects, starting from previous point
2991       old_finish = new_finish;
2992       insert_range_proxy.uninitialized_copy_n_and_update(this->m_holder.alloc(), old_finish, n);
2993       new_finish += n;
2994       new_values_destroyer.increment_size(new_finish - old_finish);
2995       //Initialize from the rest of the old buffer,
2996       //starting from previous point
2997       if(old_buffer){
2998          new_finish = ::boost::container::uninitialized_move_alloc
2999             (this->m_holder.alloc(), pos, old_buffer + this->m_holder.m_size, new_finish);
3000          //Destroy and deallocate old elements
3001          //If there is allocated memory, destroy and deallocate
3002          if(!value_traits::trivial_dctr_after_move)
3003             boost::container::destroy_alloc_n(this->get_stored_allocator(), old_buffer, this->m_holder.m_size);
3004          this->m_holder.deallocate(this->m_holder.start(), this->m_holder.capacity());
3005       }
3006       this->m_holder.start(new_start);
3007       this->m_holder.m_size = size_type(new_finish - new_start);
3008       this->m_holder.capacity(new_cap);
3009       //All construction successful, disable rollbacks
3010       new_values_destroyer.release();
3011       new_buffer_deallocator.release();
3012    }
3013 
3014    template <class InsertionProxy>
priv_forward_range_insert_expand_backwards(T * const new_start,const size_type new_capacity,T * const pos,const size_type n,InsertionProxy insert_range_proxy)3015    void priv_forward_range_insert_expand_backwards
3016          (T* const new_start, const size_type new_capacity,
3017           T* const pos, const size_type n, InsertionProxy insert_range_proxy)
3018    {
3019       //n can be zero to just expand capacity
3020       //Backup old data
3021       T* const old_start  = this->priv_raw_begin();
3022       const size_type old_size = this->m_holder.m_size;
3023       T* const old_finish = old_start + old_size;
3024 
3025       //We can have 8 possibilities:
3026       const size_type elemsbefore = static_cast<size_type>(pos - old_start);
3027       const size_type s_before    = static_cast<size_type>(old_start - new_start);
3028       const size_type before_plus_new = elemsbefore + n;
3029 
3030       //Update the vector buffer information to a safe state
3031       this->m_holder.start(new_start);
3032       this->m_holder.capacity(new_capacity);
3033       this->m_holder.m_size = 0;
3034 
3035       //If anything goes wrong, this object will destroy
3036       //all the old objects to fulfill previous vector state
3037       typename value_traits::ArrayDestructor old_values_destroyer(old_start, this->m_holder.alloc(), old_size);
3038       //Check if s_before is big enough to hold the beginning of old data + new data
3039       if(s_before >= before_plus_new){
3040          //Copy first old values before pos, after that the new objects
3041          T *const new_elem_pos =
3042             ::boost::container::uninitialized_move_alloc(this->m_holder.alloc(), old_start, pos, new_start);
3043          this->m_holder.m_size = elemsbefore;
3044          insert_range_proxy.uninitialized_copy_n_and_update(this->m_holder.alloc(), new_elem_pos, n);
3045          this->m_holder.m_size = before_plus_new;
3046          const size_type new_size = old_size + n;
3047          //Check if s_before is so big that even copying the old data + new data
3048          //there is a gap between the new data and the old data
3049          if(s_before >= new_size){
3050             //Old situation:
3051             // _________________________________________________________
3052             //|            raw_mem                | old_begin | old_end |
3053             //| __________________________________|___________|_________|
3054             //
3055             //New situation:
3056             // _________________________________________________________
3057             //| old_begin |    new   | old_end |         raw_mem        |
3058             //|___________|__________|_________|________________________|
3059             //
3060             //Now initialize the rest of memory with the last old values
3061             if(before_plus_new != new_size){ //Special case to avoid operations in back insertion
3062                ::boost::container::uninitialized_move_alloc
3063                   (this->m_holder.alloc(), pos, old_finish, new_start + before_plus_new);
3064                //All new elements correctly constructed, avoid new element destruction
3065                this->m_holder.m_size = new_size;
3066             }
3067             //Old values destroyed automatically with "old_values_destroyer"
3068             //when "old_values_destroyer" goes out of scope unless the have trivial
3069             //destructor after move.
3070             if(value_traits::trivial_dctr_after_move)
3071                old_values_destroyer.release();
3072          }
3073          //s_before is so big that divides old_end
3074          else{
3075             //Old situation:
3076             // __________________________________________________
3077             //|            raw_mem         | old_begin | old_end |
3078             //| ___________________________|___________|_________|
3079             //
3080             //New situation:
3081             // __________________________________________________
3082             //| old_begin |   new    | old_end |  raw_mem        |
3083             //|___________|__________|_________|_________________|
3084             //
3085             //Now initialize the rest of memory with the last old values
3086             //All new elements correctly constructed, avoid new element destruction
3087             const size_type raw_gap = s_before - before_plus_new;
3088             if(!value_traits::trivial_dctr){
3089                //Now initialize the rest of s_before memory with the
3090                //first of elements after new values
3091                ::boost::container::uninitialized_move_alloc_n
3092                   (this->m_holder.alloc(), pos, raw_gap, new_start + before_plus_new);
3093                //Now we have a contiguous buffer so program trailing element destruction
3094                //and update size to the final size.
3095                old_values_destroyer.shrink_forward(new_size-s_before);
3096                this->m_holder.m_size = new_size;
3097                //Now move remaining last objects in the old buffer begin
3098                T * const remaining_pos = pos + raw_gap;
3099                if(remaining_pos != old_start){  //Make sure data has to be moved
3100                   ::boost::container::move(remaining_pos, old_finish, old_start);
3101                }
3102                //Once moved, avoid calling the destructors if trivial after move
3103                if(value_traits::trivial_dctr_after_move){
3104                   old_values_destroyer.release();
3105                }
3106             }
3107             else{ //If trivial destructor, we can uninitialized copy + copy in a single uninitialized copy
3108                ::boost::container::uninitialized_move_alloc_n
3109                   (this->m_holder.alloc(), pos, static_cast<size_type>(old_finish - pos), new_start + before_plus_new);
3110                this->m_holder.m_size = new_size;
3111                old_values_destroyer.release();
3112             }
3113          }
3114       }
3115       else{
3116          //Check if we have to do the insertion in two phases
3117          //since maybe s_before is not big enough and
3118          //the buffer was expanded both sides
3119          //
3120          //Old situation:
3121          // _________________________________________________
3122          //| raw_mem | old_begin + old_end |  raw_mem        |
3123          //|_________|_____________________|_________________|
3124          //
3125          //New situation with do_after:
3126          // _________________________________________________
3127          //|     old_begin + new + old_end     |  raw_mem    |
3128          //|___________________________________|_____________|
3129          //
3130          //New without do_after:
3131          // _________________________________________________
3132          //| old_begin + new + old_end  |  raw_mem           |
3133          //|____________________________|____________________|
3134          //
3135          const bool do_after = n > s_before;
3136 
3137          //Now we can have two situations: the raw_mem of the
3138          //beginning divides the old_begin, or the new elements:
3139          if (s_before <= elemsbefore) {
3140             //The raw memory divides the old_begin group:
3141             //
3142             //If we need two phase construction (do_after)
3143             //new group is divided in new = new_beg + new_end groups
3144             //In this phase only new_beg will be inserted
3145             //
3146             //Old situation:
3147             // _________________________________________________
3148             //| raw_mem | old_begin | old_end |  raw_mem        |
3149             //|_________|___________|_________|_________________|
3150             //
3151             //New situation with do_after(1):
3152             //This is not definitive situation, the second phase
3153             //will include
3154             // _________________________________________________
3155             //| old_begin | new_beg | old_end |  raw_mem        |
3156             //|___________|_________|_________|_________________|
3157             //
3158             //New situation without do_after:
3159             // _________________________________________________
3160             //| old_begin | new | old_end |  raw_mem            |
3161             //|___________|_____|_________|_____________________|
3162             //
3163             //Copy the first part of old_begin to raw_mem
3164             ::boost::container::uninitialized_move_alloc_n
3165                (this->m_holder.alloc(), old_start, s_before, new_start);
3166             //The buffer is all constructed until old_end,
3167             //so program trailing destruction and assign final size
3168             //if !do_after, s_before+n otherwise.
3169             size_type new_1st_range;
3170             if(do_after){
3171                new_1st_range = s_before;
3172                //release destroyer and update size
3173                old_values_destroyer.release();
3174             }
3175             else{
3176                new_1st_range = n;
3177                if(value_traits::trivial_dctr_after_move)
3178                   old_values_destroyer.release();
3179                else{
3180                   old_values_destroyer.shrink_forward(old_size - (s_before - n));
3181                }
3182             }
3183             this->m_holder.m_size = old_size + new_1st_range;
3184             //Now copy the second part of old_begin overwriting itself
3185             T *const next = ::boost::container::move(old_start + s_before, pos, old_start);
3186             //Now copy the new_beg elements
3187             insert_range_proxy.copy_n_and_update(this->m_holder.alloc(), next, new_1st_range);
3188 
3189             //If there is no after work and the last old part needs to be moved to front, do it
3190             if(!do_after && (n != s_before)){
3191                //Now displace old_end elements
3192                ::boost::container::move(pos, old_finish, next + new_1st_range);
3193             }
3194          }
3195          else {
3196             //If we have to expand both sides,
3197             //we will play if the first new values so
3198             //calculate the upper bound of new values
3199 
3200             //The raw memory divides the new elements
3201             //
3202             //If we need two phase construction (do_after)
3203             //new group is divided in new = new_beg + new_end groups
3204             //In this phase only new_beg will be inserted
3205             //
3206             //Old situation:
3207             // _______________________________________________________
3208             //|   raw_mem     | old_begin | old_end |  raw_mem        |
3209             //|_______________|___________|_________|_________________|
3210             //
3211             //New situation with do_after():
3212             // ____________________________________________________
3213             //| old_begin |    new_beg    | old_end |  raw_mem     |
3214             //|___________|_______________|_________|______________|
3215             //
3216             //New situation without do_after:
3217             // ______________________________________________________
3218             //| old_begin | new | old_end |  raw_mem                 |
3219             //|___________|_____|_________|__________________________|
3220             //
3221             //First copy whole old_begin and part of new to raw_mem
3222             T * const new_pos = ::boost::container::uninitialized_move_alloc
3223                (this->m_holder.alloc(), old_start, pos, new_start);
3224             this->m_holder.m_size = elemsbefore;
3225             const size_type mid_n = s_before - elemsbefore;
3226             insert_range_proxy.uninitialized_copy_n_and_update(this->m_holder.alloc(), new_pos, mid_n);
3227             //The buffer is all constructed until old_end,
3228             //release destroyer
3229             this->m_holder.m_size = old_size + s_before;
3230             old_values_destroyer.release();
3231 
3232             if(do_after){
3233                //Copy new_beg part
3234                insert_range_proxy.copy_n_and_update(this->m_holder.alloc(), old_start, elemsbefore);
3235             }
3236             else{
3237                //Copy all new elements
3238                const size_type rest_new = n - mid_n;
3239                insert_range_proxy.copy_n_and_update(this->m_holder.alloc(), old_start, rest_new);
3240                T* const move_start = old_start + rest_new;
3241                //Displace old_end, but make sure data has to be moved
3242                T* const move_end = move_start != pos ? ::boost::container::move(pos, old_finish, move_start)
3243                                                      : old_finish;
3244                //Destroy remaining moved elements from old_end except if they
3245                //have trivial destructor after being moved
3246                size_type n_destroy = s_before - n;
3247                if(!value_traits::trivial_dctr_after_move)
3248                   boost::container::destroy_alloc_n(this->get_stored_allocator(), move_end, n_destroy);
3249                this->m_holder.m_size -= n_destroy;
3250             }
3251          }
3252 
3253          //This is only executed if two phase construction is needed
3254          if(do_after){
3255             //The raw memory divides the new elements
3256             //
3257             //Old situation:
3258             // ______________________________________________________
3259             //|   raw_mem    | old_begin |  old_end   |  raw_mem     |
3260             //|______________|___________|____________|______________|
3261             //
3262             //New situation with do_after(1):
3263             // _______________________________________________________
3264             //| old_begin   +   new_beg  | new_end |old_end | raw_mem |
3265             //|__________________________|_________|________|_________|
3266             //
3267             //New situation with do_after(2):
3268             // ______________________________________________________
3269             //| old_begin      +       new            | old_end |raw |
3270             //|_______________________________________|_________|____|
3271             //
3272             const size_type n_after    = n - s_before;
3273             const size_type elemsafter = old_size - elemsbefore;
3274 
3275             //We can have two situations:
3276             if (elemsafter >= n_after){
3277                //The raw_mem from end will divide displaced old_end
3278                //
3279                //Old situation:
3280                // ______________________________________________________
3281                //|   raw_mem    | old_begin |  old_end   |  raw_mem     |
3282                //|______________|___________|____________|______________|
3283                //
3284                //New situation with do_after(1):
3285                // _______________________________________________________
3286                //| old_begin   +   new_beg  | new_end |old_end | raw_mem |
3287                //|__________________________|_________|________|_________|
3288                //
3289                //First copy the part of old_end raw_mem
3290                T* finish_n = old_finish - n_after;
3291                ::boost::container::uninitialized_move_alloc
3292                   (this->m_holder.alloc(), finish_n, old_finish, old_finish);
3293                this->m_holder.m_size += n_after;
3294                //Displace the rest of old_end to the new position
3295                boost::container::move_backward(pos, finish_n, old_finish);
3296                //Now overwrite with new_end
3297                //The new_end part is [first + (n - n_after), last)
3298                insert_range_proxy.copy_n_and_update(this->m_holder.alloc(), pos, n_after);
3299             }
3300             else {
3301                //The raw_mem from end will divide new_end part
3302                //
3303                //Old situation:
3304                // _____________________________________________________________
3305                //|   raw_mem    | old_begin |  old_end   |  raw_mem            |
3306                //|______________|___________|____________|_____________________|
3307                //
3308                //New situation with do_after(2):
3309                // _____________________________________________________________
3310                //| old_begin   +   new_beg  |     new_end   |old_end | raw_mem |
3311                //|__________________________|_______________|________|_________|
3312                //
3313 
3314                const size_type mid_last_dist = n_after - elemsafter;
3315                //First initialize data in raw memory
3316 
3317                //Copy to the old_end part to the uninitialized zone leaving a gap.
3318                ::boost::container::uninitialized_move_alloc
3319                   (this->m_holder.alloc(), pos, old_finish, old_finish + mid_last_dist);
3320 
3321                typename value_traits::ArrayDestructor old_end_destroyer
3322                   (old_finish + mid_last_dist, this->m_holder.alloc(), old_finish - pos);
3323 
3324                //Copy the first part to the already constructed old_end zone
3325                insert_range_proxy.copy_n_and_update(this->m_holder.alloc(), pos, elemsafter);
3326                //Copy the rest to the uninitialized zone filling the gap
3327                insert_range_proxy.uninitialized_copy_n_and_update(this->m_holder.alloc(), old_finish, mid_last_dist);
3328                this->m_holder.m_size += n_after;
3329                old_end_destroyer.release();
3330             }
3331          }
3332       }
3333    }
3334 
priv_throw_if_out_of_range(size_type n) const3335    void priv_throw_if_out_of_range(size_type n) const
3336    {
3337       //If n is out of range, throw an out_of_range exception
3338       if (n >= this->size()){
3339          throw_out_of_range("vector::at out of range");
3340       }
3341    }
3342 
priv_in_range(const_iterator pos) const3343    BOOST_CONTAINER_FORCEINLINE bool priv_in_range(const_iterator pos) const
3344    {
3345       return (this->begin() <= pos) && (pos < this->end());
3346    }
3347 
priv_in_range_or_end(const_iterator pos) const3348    BOOST_CONTAINER_FORCEINLINE bool priv_in_range_or_end(const_iterator pos) const
3349    {
3350       return (this->begin() <= pos) && (pos <= this->end());
3351    }
3352 
3353    #ifdef BOOST_CONTAINER_VECTOR_ALLOC_STATS
3354    public:
3355    unsigned int num_expand_fwd;
3356    unsigned int num_expand_bwd;
3357    unsigned int num_shrink;
3358    unsigned int num_alloc;
reset_alloc_stats()3359    void reset_alloc_stats()
3360    {  num_expand_fwd = num_expand_bwd = num_alloc = 0, num_shrink = 0;   }
3361    #endif
3362    #endif   //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
3363 };
3364 
3365 #ifndef BOOST_CONTAINER_NO_CXX17_CTAD
3366 
3367 template <typename InputIterator>
3368 vector(InputIterator, InputIterator) ->
3369    vector<typename iterator_traits<InputIterator>::value_type>;
3370 
3371 template <typename InputIterator, typename Allocator>
3372 vector(InputIterator, InputIterator, Allocator const&) ->
3373    vector<typename iterator_traits<InputIterator>::value_type, Allocator>;
3374 
3375 #endif
3376 
3377 
3378 }} //namespace boost::container
3379 
3380 #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
3381 
3382 namespace boost {
3383 
3384 //!has_trivial_destructor_after_move<> == true_type
3385 //!specialization for optimizations
3386 template <class T, class Allocator, class Options>
3387 struct has_trivial_destructor_after_move<boost::container::vector<T, Allocator, Options> >
3388 {
3389    typedef typename boost::container::vector<T, Allocator, Options>::allocator_type allocator_type;
3390    typedef typename ::boost::container::allocator_traits<allocator_type>::pointer pointer;
3391    static const bool value = ::boost::has_trivial_destructor_after_move<allocator_type>::value &&
3392                              ::boost::has_trivial_destructor_after_move<pointer>::value;
3393 };
3394 
3395 }
3396 
3397 #endif   //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
3398 
3399 #include <boost/container/detail/config_end.hpp>
3400 
3401 #endif //   #ifndef  BOOST_CONTAINER_CONTAINER_VECTOR_HPP
3402