File Coverage

/usr/local/lib/perl5/site_perl/5.26.1/XS/libboost/mini.x/i/boost/container/vector.hpp
Criterion Covered Total %
statement 0 16 0.0
branch 0 8 0.0
condition n/a
subroutine n/a
pod n/a
total 0 24 0.0


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