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