]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/boost/container/devector.hpp
update ceph source to reef 18.1.2
[ceph.git] / ceph / src / boost / boost / container / devector.hpp
CommitLineData
20effc67
TL
1//////////////////////////////////////////////////////////////////////////////
2//
3// (C) Copyright Benedek Thaler 2015-2016
4// (C) Copyright Ion Gaztanaga 2019-2020. Distributed under the Boost
5// Software License, Version 1.0. (See accompanying file
6// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7//
8// See http://www.boost.org/libs/container for documentation.
9//
10//////////////////////////////////////////////////////////////////////////////
11
12#ifndef BOOST_CONTAINER_DEVECTOR_HPP
13#define BOOST_CONTAINER_DEVECTOR_HPP
14
15#include <boost/container/detail/config_begin.hpp>
16#include <boost/container/detail/workaround.hpp>
17
18//#include <algorithm>
19#include <cstring> // memcpy
20
21#include <boost/assert.hpp>
22#include <boost/aligned_storage.hpp>
23
24#include <boost/container/detail/copy_move_algo.hpp>
25#include <boost/container/new_allocator.hpp> //new_allocator
26#include <boost/container/allocator_traits.hpp> //allocator_traits
27#include <boost/container/detail/algorithm.hpp> //equal()
28#include <boost/container/throw_exception.hpp>
29#include <boost/container/options.hpp>
30
31#include <boost/container/detail/guards_dended.hpp>
32#include <boost/container/detail/iterator.hpp>
33#include <boost/container/detail/iterators.hpp>
34#include <boost/container/detail/destroyers.hpp>
35#include <boost/container/detail/min_max.hpp>
36#include <boost/container/detail/next_capacity.hpp>
37#include <boost/container/detail/alloc_helpers.hpp>
38
39// move
40#if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
41#include <boost/move/detail/fwd_macros.hpp>
42#endif
43#include <boost/move/detail/move_helpers.hpp>
44#include <boost/move/adl_move_swap.hpp>
45#include <boost/move/iterator.hpp>
46#include <boost/move/traits.hpp>
47#include <boost/move/utility_core.hpp>
48#include <boost/move/detail/to_raw_pointer.hpp>
49#include <boost/move/algo/detail/merge.hpp>
1e59de90 50#include <boost/move/detail/force_ptr.hpp>
20effc67
TL
51
52#include <boost/type_traits/is_nothrow_move_constructible.hpp>
53
54//std
55#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
56#include <initializer_list> //for std::initializer_list
57#endif
58
59namespace boost {
60namespace container {
61
62#if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
63
64struct growth_factor_60;
65
66template<class Options, class AllocatorSizeType>
67struct get_devector_opt
68{
69 typedef devector_opt< typename default_if_void<typename Options::growth_factor_type, growth_factor_60>::type
70 , typename default_if_void<typename Options::stored_size_type, AllocatorSizeType>::type
71 > type;
72};
73
74template<class AllocatorSizeType>
75struct get_devector_opt<void, AllocatorSizeType>
76{
77 typedef vector_opt<growth_factor_60, AllocatorSizeType> type;
78};
79
80#endif //#if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
81
82struct reserve_only_tag_t {};
83//struct unsafe_uninitialized_tag_t {};
84
85/**
86 * A vector-like sequence container providing front and back operations
87 * (e.g: `push_front`/`pop_front`/`push_back`/`pop_back`) with amortized constant complexity
88 * and unsafe methods geared towards additional performance.
89 *
90 * Models the [SequenceContainer], [ReversibleContainer], and [AllocatorAwareContainer] concepts.
91 *
92 * **Requires**:
93 * - `T` shall be [MoveInsertable] into the devector.
94 * - `T` shall be [Erasable] from any `devector<T, allocator_type, GP>`.
95 * - `GrowthFactor`, and `Allocator` must model the concepts with the same names or be void.
96 *
97 * **Definition**: `T` is `NothrowConstructible` if it's either nothrow move constructible or
98 * nothrow copy constructible.
99 *
100 * **Definition**: `T` is `NothrowAssignable` if it's either nothrow move assignable or
101 * nothrow copy assignable.
102 *
103 * **Exceptions**: The exception specifications assume `T` is nothrow [Destructible].
104 *
105 * Most methods providing the strong exception guarantee assume `T` either has a move
106 * constructor marked noexcept or is [CopyInsertable] into the devector. If it isn't true,
107 * and the move constructor throws, the guarantee is waived and the effects are unspecified.
108 *
109 * In addition to the exceptions specified in the **Throws** clause, the following operations
110 * of `T` can throw when any of the specified concept is required:
111 * - [DefaultInsertable][]: Default constructor
112 * - [MoveInsertable][]: Move constructor
113 * - [CopyInsertable][]: Copy constructor
114 * - [DefaultConstructible][]: Default constructor
115 * - [EmplaceConstructible][]: Constructor selected by the given arguments
116 * - [MoveAssignable][]: Move assignment operator
117 * - [CopyAssignable][]: Copy assignment operator
118 *
119 * Furthermore, not `noexcept` methods throws whatever the allocator throws
120 * if memory allocation fails. Such methods also throw `length_error` if the capacity
121 * exceeds `max_size()`.
122 *
123 * **Remark**: If a method invalidates some iterators, it also invalidates references
124 * and pointers to the elements pointed by the invalidated iterators.
125 *
126 * **Policies**:
127 *
128 * @ref devector_growth_policy models the `GrowthFactor` concept.
129 *
130 * [SequenceContainer]: http://en.cppreference.com/w/cpp/concept/SequenceContainer
131 * [ReversibleContainer]: http://en.cppreference.com/w/cpp/concept/ReversibleContainer
132 * [AllocatorAwareContainer]: http://en.cppreference.com/w/cpp/concept/AllocatorAwareContainer
133 * [DefaultInsertable]: http://en.cppreference.com/w/cpp/concept/DefaultInsertable
134 * [MoveInsertable]: http://en.cppreference.com/w/cpp/concept/MoveInsertable
135 * [CopyInsertable]: http://en.cppreference.com/w/cpp/concept/CopyInsertable
136 * [Erasable]: http://en.cppreference.com/w/cpp/concept/Erasable
137 * [DefaultConstructible]: http://en.cppreference.com/w/cpp/concept/DefaultConstructible
138 * [Destructible]: http://en.cppreference.com/w/cpp/concept/Destructible
139 * [EmplaceConstructible]: http://en.cppreference.com/w/cpp/concept/EmplaceConstructible
140 * [MoveAssignable]: http://en.cppreference.com/w/cpp/concept/MoveAssignable
141 * [CopyAssignable]: http://en.cppreference.com/w/cpp/concept/CopyAssignable
142 */
143template < typename T, class A BOOST_CONTAINER_DOCONLY(= void), class Options BOOST_CONTAINER_DOCONLY(= void)>
144class devector
145{
146 #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
147 typedef boost::container::allocator_traits
148 <typename real_allocator<T, A>::type> allocator_traits_type;
149 typedef typename allocator_traits_type::size_type alloc_size_type;
150 typedef typename get_devector_opt<Options, alloc_size_type>::type options_type;
151 typedef typename options_type::growth_factor_type growth_factor_type;
152 typedef typename options_type::stored_size_type stored_size_type;
153
154 #endif // ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
155
156 public:
157 // Standard Interface Types:
158 typedef T value_type;
159 typedef BOOST_CONTAINER_IMPDEF
160 (typename real_allocator<T BOOST_MOVE_I A>::type) allocator_type;
161 typedef allocator_type stored_allocator_type;
162 typedef typename allocator_traits<allocator_type>::pointer pointer;
163 typedef typename allocator_traits<allocator_type>::const_pointer const_pointer;
164 typedef typename allocator_traits<allocator_type>::reference reference;
165 typedef typename allocator_traits<allocator_type>::const_reference const_reference;
166 typedef typename allocator_traits<allocator_type>::size_type size_type;
167 typedef typename allocator_traits<allocator_type>::difference_type difference_type;
168 typedef pointer iterator;
169 typedef const_pointer const_iterator;
170 typedef BOOST_CONTAINER_IMPDEF
171 (boost::container::reverse_iterator<iterator>) reverse_iterator;
172 typedef BOOST_CONTAINER_IMPDEF
173 (boost::container::reverse_iterator<const_iterator>) const_reverse_iterator;
174
175 #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
176 private:
177 BOOST_COPYABLE_AND_MOVABLE(devector)
178
179 // Guard to deallocate buffer on exception
180 typedef typename detail::allocation_guard<allocator_type> allocation_guard;
181
182 // Random access pseudo iterator always yielding to the same result
1e59de90 183 typedef constant_iterator<T> cvalue_iterator;
20effc67
TL
184
185 #endif // ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
186
187 // Standard Interface
188 public:
189 // construct/copy/destroy
190
191 /**
192 * **Effects**: Constructs an empty devector.
193 *
194 * **Postcondition**: `empty() && front_free_capacity() == 0
195 * && back_free_capacity() == 0`.
196 *
197 * **Complexity**: Constant.
198 */
199 devector() BOOST_NOEXCEPT
200 : m_()
201 {}
202
203 /**
204 * **Effects**: Constructs an empty devector, using the specified allocator.
205 *
206 * **Postcondition**: `empty() && front_free_capacity() == 0
207 * && back_free_capacity() == 0`.
208 *
209 * **Complexity**: Constant.
210 */
211 explicit devector(const allocator_type& allocator) BOOST_NOEXCEPT
212 : m_(allocator)
213 {}
214
215 /**
216 * **Effects**: Constructs an empty devector, using the specified allocator
217 * and reserves `n` slots as if `reserve(n)` was called.
218 *
219 * **Postcondition**: `empty() && front_free_capacity() == 0
220 * && back_free_capacity() >= n`.
221 *
222 * **Exceptions**: Strong exception guarantee.
223 *
224 * **Complexity**: Constant.
225 */
226 devector(size_type n, reserve_only_tag_t, const allocator_type& allocator = allocator_type())
1e59de90 227 : m_(allocator, 0u, 0u, n)
20effc67
TL
228 {}
229
230 /**
231 * **Effects**: Constructs an empty devector, using the specified allocator
232 * and reserves `front_cap + back_cap` slots as if `reserve_front(front_cap)` and
233 * `reserve_back(back_cap)` was called.
234 *
235 * **Postcondition**: `empty() && front_free_capacity() == front_cap
236 * && back_free_capacity() >= back_cap`.
237 *
238 * **Exceptions**: Strong exception guarantee.
239 *
240 * **Complexity**: Constant.
241 */
242 devector(size_type front_cap, size_type back_cap, reserve_only_tag_t, const allocator_type& allocator = allocator_type())
1e59de90 243 : m_( allocator, front_cap, back_cap, front_cap + back_cap)
20effc67
TL
244 {}
245
246 /**
247 * [DefaultInsertable]: http://en.cppreference.com/w/cpp/concept/DefaultInsertable
248 *
249 * **Effects**: Constructs a devector with `n` default-inserted elements using the specified allocator.
250 *
251 * **Requires**: `T` shall be [DefaultInsertable] into `*this`.
252 *
253 * **Postcondition**: `size() == n && front_free_capacity() == 0`.
254 *
255 * **Exceptions**: Strong exception guarantee.
256 *
257 * **Complexity**: Linear in `n`.
258 */
259 explicit devector(size_type n, const allocator_type& allocator = allocator_type())
1e59de90 260 : m_(allocator, 0u, n, n)
20effc67
TL
261 {
262 // Cannot use construct_from_range/constant_iterator and copy_range,
263 // because we are not allowed to default construct T
264 allocation_guard buffer_guard(m_.buffer, m_.capacity, get_allocator_ref());
265 detail::construction_guard<allocator_type> copy_guard(m_.buffer, get_allocator_ref());
266
267 for (size_type i = 0; i < n; ++i)
268 {
269 this->alloc_construct(m_.buffer + i);
270 copy_guard.extend();
271 }
272
273 copy_guard.release();
274 buffer_guard.release();
275
276 BOOST_ASSERT(invariants_ok());
277 }
278
279 /**
280 * [CopyInsertable]: http://en.cppreference.com/w/cpp/concept/CopyInsertable
281 *
282 * **Effects**: Constructs a devector with `n` copies of `value`, using the specified allocator.
283 *
284 * **Requires**: `T` shall be [CopyInsertable] into `*this`.
285 *
286 * **Postcondition**: `size() == n && front_free_capacity() == 0`.
287 *
288 * **Exceptions**: Strong exception guarantee.
289 *
290 * **Complexity**: Linear in `n`.
291 */
292 devector(size_type n, const T& value, const allocator_type& allocator = allocator_type())
293 : m_(allocator, n ? allocate(n): pointer(), 0u, n, n)
294 {
295 construct_from_range(cvalue_iterator(value, n), cvalue_iterator());
296 BOOST_ASSERT(invariants_ok());
297 }
298
299 /**
300 * **Effects**: Constructs a devector equal to the range `[first,last)`, using the specified allocator.
301 *
302 * **Requires**: `T` shall be [EmplaceConstructible] into `*this` from `*first`. If the specified
303 * iterator does not meet the forward iterator requirements, `T` shall also be [MoveInsertable]
304 * into `*this`.
305 *
306 * **Postcondition**: `size() == boost::container::iterator_distance(first, last)
307 *
308 * **Exceptions**: Strong exception guarantee.
309 *
310 * **Complexity**: Makes only `N` calls to the copy constructor of `T` (where `N` is the distance between `first`
311 * and `last`), at most one allocation and no reallocations if iterators first and last are of forward,
312 * bidirectional, or random access categories. It makes `O(N)` calls to the copy constructor of `T`
313 * and `O(log(N)) reallocations if they are just input iterators.
314 *
315 * **Remarks**: Each iterator in the range `[first,last)` shall be dereferenced exactly once,
316 * unless an exception is thrown.
317 *
318 * [EmplaceConstructible]: http://en.cppreference.com/w/cpp/concept/EmplaceConstructible
319 * [MoveInsertable]: http://en.cppreference.com/w/cpp/concept/MoveInsertable
320 */
321 template <class InputIterator>
322 devector(InputIterator first, InputIterator last, const allocator_type& allocator = allocator_type()
323 //Input iterators
324 BOOST_CONTAINER_DOCIGN(BOOST_MOVE_I typename dtl::disable_if_or
325 < void
326 BOOST_MOVE_I dtl::is_convertible<InputIterator BOOST_MOVE_I size_type>
327 BOOST_MOVE_I dtl::is_not_input_iterator<InputIterator>
328 >::type * = 0)
329 )
330 : m_(allocator, pointer(), 0u, 0u, 0u)
331 {
332 while (first != last) {
333 this->emplace_back(*first++);
334 }
335
336 BOOST_ASSERT(invariants_ok());
337 }
338
339 #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
340
341 template <class ForwardIterator>
342 devector(ForwardIterator first, ForwardIterator last, const allocator_type& allocator = allocator_type()
343 //Other iterators
344 BOOST_CONTAINER_DOCIGN(BOOST_MOVE_I typename dtl::disable_if_or
345 < void
346 BOOST_MOVE_I dtl::is_convertible<ForwardIterator BOOST_MOVE_I size_type>
347 BOOST_MOVE_I dtl::is_input_iterator<ForwardIterator>
348 >::type * = 0)
349 )
1e59de90 350 : m_(allocator)
20effc67 351 {
1e59de90 352 const size_type n = boost::container::iterator_udistance(first, last);
20effc67
TL
353 m_.buffer = n ? allocate(n) : pointer();
354 m_.front_idx = 0u;
1e59de90 355 //this->allocate(n) will take care of overflows
20effc67
TL
356 m_.set_back_idx(n);
357 m_.set_capacity(n);
1e59de90
TL
358 //construct_from_range releases memory on failure
359 this->construct_from_range(first, last);
20effc67
TL
360 BOOST_ASSERT(invariants_ok());
361 }
362
363 #endif // ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
364
365 /**
366 * [CopyInsertable]: http://en.cppreference.com/w/cpp/concept/CopyInsertable
367 *
368 * **Effects**: Copy constructs a devector.
369 *
370 * **Requires**: `T` shall be [CopyInsertable] into `*this`.
371 *
372 * **Postcondition**: `this->size() == x.size() && front_free_capacity() == 0`.
373 *
374 * **Exceptions**: Strong exception guarantee.
375 *
376 * **Complexity**: Linear in the size of `x`.
377 */
378 devector(const devector& x)
1e59de90 379 : m_( allocator_traits_type::select_on_container_copy_construction(x.get_allocator_ref()))
20effc67
TL
380 {
381 const size_type n = x.size();
382 m_.buffer = n ? allocate(n) : pointer();
383 m_.front_idx = 0u;
384 //this->allocate(n) will take care of overflows
385 m_.set_back_idx(n);
386 m_.set_capacity(n);
387 this->construct_from_range(x.begin(), x.end());
388 BOOST_ASSERT(invariants_ok());
389 }
390
391 /**
392 * [CopyInsertable]: http://en.cppreference.com/w/cpp/concept/CopyInsertable
393 *
394 * **Effects**: Copy constructs a devector, using the specified allocator.
395 *
396 * **Requires**: `T` shall be [CopyInsertable] into `*this`.
397 *
398 * **Postcondition**: `this->size() == x.size() && front_free_capacity() == 0`.
399 *
400 * **Exceptions**: Strong exception guarantee.
401 *
402 * **Complexity**: Linear in the size of `x`.
403 */
404 devector(const devector& x, const allocator_type& allocator)
405 : m_(allocator, pointer(), 0u, 0u, 0u)
406 {
407 const size_type n = x.size();
408 m_.buffer = n ? this->allocate(n) : pointer();
409 m_.front_idx = 0u;
410 //this->allocate(n) will take care of overflows
411 m_.set_back_idx(n);
412 m_.set_capacity(n);
413 this->construct_from_range(x.begin(), x.end());
414 BOOST_ASSERT(invariants_ok());
415 }
416
417 /**
418 * **Effects**: Moves `rhs`'s resources to `*this`.
419 *
420 * **Throws**: Nothing.
421 *
422 * **Postcondition**: `rhs` is left in an unspecified but valid state.
423 *
424 * **Exceptions**: Strong exception guarantee if not `noexcept`.
425 *
426 * **Complexity**: Constant.
427 */
428 devector(BOOST_RV_REF(devector) rhs) BOOST_NOEXCEPT_OR_NOTHROW
429 : m_(::boost::move(rhs.get_allocator_ref()), rhs.m_.buffer, rhs.m_.front_idx, rhs.m_.back_idx, rhs.capacity())
430 {
431 // buffer is already acquired, reset rhs
432 rhs.m_.capacity = 0u;
433 rhs.m_.buffer = pointer();
434 rhs.m_.front_idx = 0;
435 rhs.m_.back_idx = 0;
436 BOOST_ASSERT( invariants_ok());
437 BOOST_ASSERT(rhs.invariants_ok());
438 }
439
440 /**
441 * **Effects**: Moves `rhs`'s resources to `*this`, using the specified allocator.
442 *
443 * **Throws**: If allocation or T's move constructor throws.
444 *
445 * **Postcondition**: `rhs` is left in an unspecified but valid state.
446 *
447 * **Exceptions**: Strong exception guarantee if not `noexcept`.
448 *
449 * **Complexity**: Linear if allocator != rhs.get_allocator(), otherwise constant.
450 */
451 devector(BOOST_RV_REF(devector) rhs, const allocator_type& allocator)
452 : m_(allocator, rhs.m_.buffer, rhs.m_.front_idx, rhs.m_.back_idx, rhs.capacity())
453 {
454 // TODO should move elems-by-elems if the two allocators differ
455 // buffer is already acquired, reset rhs
456 rhs.m_.capacity = 0u;
457 rhs.m_.buffer = pointer();
458 rhs.m_.front_idx = 0;
459 rhs.m_.back_idx = 0;
460 BOOST_ASSERT( invariants_ok());
461 BOOST_ASSERT(rhs.invariants_ok());
462 }
463
464 #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
465 /**
466 * **Equivalent to**: `devector(il.begin(), il.end())` or `devector(il.begin(), il.end(), allocator)`.
467 */
468 devector(const std::initializer_list<T>& il, const allocator_type& allocator = allocator_type())
1e59de90
TL
469 : m_(allocator)
470 {
471 const size_type n = il.size();
472 m_.buffer = n ? allocate(n) : pointer();
473 m_.front_idx = 0u;
474 //this->allocate(n) will take care of overflows
475 m_.set_back_idx(n);
476 m_.set_capacity(n);
477 //construct_from_range releases memory on failure
478 this->construct_from_range(il.begin(), il.end());
479 BOOST_ASSERT(invariants_ok());
480 }
20effc67
TL
481 #endif
482
483 /**
484 * **Effects**: Destroys the devector. All stored values are destroyed and
485 * used memory, if any, deallocated.
486 *
487 * **Complexity**: Linear in the size of `*this`.
488 */
489 ~devector() BOOST_NOEXCEPT
490 {
491 destroy_elements(m_.buffer + m_.front_idx, m_.buffer + m_.back_idx);
492 deallocate_buffer();
493 }
494
495 /**
496 * **Effects**: Copies elements of `x` to `*this`. Previously
497 * held elements get copy assigned to or destroyed.
498 *
499 * **Requires**: `T` shall be [CopyInsertable] into `*this`.
500 *
501 * **Postcondition**: `this->size() == x.size()`, the elements of
502 * `*this` are copies of elements in `x` in the same order.
503 *
504 * **Returns**: `*this`.
505 *
506 * **Exceptions**: Strong exception guarantee if `T` is `NothrowConstructible`
507 * and the allocator is allowed to be propagated
508 * ([propagate_on_container_copy_assignment] is true),
509 * Basic exception guarantee otherwise.
510 *
511 * **Complexity**: Linear in the size of `x` and `*this`.
512 *
513 * [CopyInsertable]: http://en.cppreference.com/w/cpp/concept/CopyInsertable
514 * [propagate_on_container_copy_assignment]: http://en.cppreference.com/w/cpp/memory/allocator_traits
515 */
516
517 BOOST_CONTAINER_FORCEINLINE devector& operator=(BOOST_COPY_ASSIGN_REF(devector) rhs)
518 {
519 const devector &x = rhs;
520 if (this == &x) { return *this; } // skip self
521
522 BOOST_IF_CONSTEXPR(allocator_traits_type::propagate_on_container_copy_assignment::value)
523 {
524 allocator_type &this_alloc = this->get_allocator_ref();
525 const allocator_type &other_alloc = x.get_allocator_ref();
526 if (this_alloc != other_alloc)
527 {
528 // new allocator cannot free existing storage
529 this->clear();
530 this->deallocate_buffer();
531 m_.capacity = 0u;
532 m_.buffer = pointer();
533 }
534
535 this_alloc = other_alloc;
536 }
537
538 size_type n = x.size();
539 if (capacity() >= n)
540 {
541 this->overwrite_buffer(x.begin(), x.end());
542 }
543 else
544 {
545 this->allocate_and_copy_range(x.begin(), x.end());
546 }
547
548 BOOST_ASSERT(invariants_ok());
549
550 return *this;
551 }
552
553 /**
554 * [MoveInsertable]: http://en.cppreference.com/w/cpp/concept/MoveInsertable
555 *
556 * **Effects**: Moves elements of `x` to `*this`. Previously
557 * held elements get move/copy assigned to or destroyed.
558 *
559 * **Requires**: `T` shall be [MoveInsertable] into `*this`.
560 *
561 * **Postcondition**: `x` is left in an unspecified but valid state.
562 *
563 * **Returns**: `*this`.
564 *
565 * **Exceptions**: Basic exception guarantee if not `noexcept`.
566 *
567 * **Complexity**: Constant if allocator_traits_type::
568 * propagate_on_container_move_assignment is true or
569 * this->get>allocator() == x.get_allocator(). Linear otherwise.
570 */
571 devector& operator=(BOOST_RV_REF(devector) x)
572 BOOST_NOEXCEPT_IF(allocator_traits_type::propagate_on_container_move_assignment::value
573 || allocator_traits_type::is_always_equal::value)
574 {
575 BOOST_CONSTEXPR_OR_CONST bool copy_alloc = allocator_traits_type::propagate_on_container_move_assignment::value;
576
577 BOOST_IF_CONSTEXPR (copy_alloc || get_allocator_ref() == x.get_allocator_ref())
578 {
579 this->clear();
580 this->deallocate_buffer();
581
582 if (copy_alloc)
583 {
584 this->get_allocator_ref() = boost::move(x.get_allocator_ref());
585 }
586
587 m_.capacity = x.m_.capacity;
588 m_.buffer = x.m_.buffer;
589 m_.front_idx = x.m_.front_idx;
590 m_.back_idx = x.m_.back_idx;
591
592 // leave x in valid state
593 x.m_.capacity = 0u;
594 x.m_.buffer = pointer();
595 x.m_.back_idx = x.m_.front_idx = 0;
596 }
597 else
598 {
599 // if the allocator shouldn't be copied and they do not compare equal
600 // we can't steal memory.
601
602 move_iterator<iterator> xbegin = boost::make_move_iterator(x.begin());
603 move_iterator<iterator> xend = boost::make_move_iterator(x.end());
604
605 if (copy_alloc)
606 {
607 get_allocator_ref() = boost::move(x.get_allocator_ref());
608 }
609
610 if (capacity() >= x.size())
611 {
612 overwrite_buffer(xbegin, xend);
613 }
614 else
615 {
616 allocate_and_copy_range(xbegin, xend);
617 }
618 }
619
620 BOOST_ASSERT(invariants_ok());
621
622 return *this;
623 }
624
625 #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
626 /**
627 * **Effects**: Copies elements of `il` to `*this`. Previously
628 * held elements get copy assigned to or destroyed.
629 *
630 * **Requires**: `T` shall be [CopyInsertable] into `*this` and [CopyAssignable].
631 *
632 * **Postcondition**: `this->size() == il.size()`, the elements of
633 * `*this` are copies of elements in `il` in the same order.
634 *
635 * **Exceptions**: Strong exception guarantee if `T` is nothrow copy assignable
636 * from `T` and `NothrowConstructible`, Basic exception guarantee otherwise.
637 *
638 * **Returns**: `*this`.
639 *
640 * **Complexity**: Linear in the size of `il` and `*this`.
641 *
642 * [CopyInsertable]: http://en.cppreference.com/w/cpp/concept/CopyInsertable
643 * [CopyAssignable]: http://en.cppreference.com/w/cpp/concept/CopyAssignable
644 */
645 devector& operator=(std::initializer_list<T> il)
646 {
647 assign(il.begin(), il.end());
648 return *this;
649 }
650 #endif
651
652 /**
653 * **Effects**: Replaces elements of `*this` with a copy of `[first,last)`.
654 * Previously held elements get copy assigned to or destroyed.
655 *
656 * **Requires**: `T` shall be [EmplaceConstructible] from `*first`. If the specified iterator
657 * does not meet the forward iterator requirements, `T` shall be also [MoveInsertable] into `*this`.
658 *
659 * **Precondition**: `first` and `last` are not iterators into `*this`.
660 *
661 * **Postcondition**: `size() == N`, where `N` is the distance between `first` and `last`.
662 *
663 * **Exceptions**: Strong exception guarantee if `T` is nothrow copy assignable
664 * from `*first` and `NothrowConstructible`, Basic exception guarantee otherwise.
665 *
666 * **Complexity**: Linear in the distance between `first` and `last`.
667 * Makes a single reallocation at most if the iterators `first` and `last`
668 * are of forward, bidirectional, or random access categories. It makes
669 * `O(log(N))` reallocations if they are just input iterators.
670 *
671 * **Remarks**: Each iterator in the range `[first,last)` shall be dereferenced exactly once,
672 * unless an exception is thrown.
673 *
674 * [EmplaceConstructible]: http://en.cppreference.com/w/cpp/concept/EmplaceConstructible
675 * [MoveInsertable]: http://en.cppreference.com/w/cpp/concept/MoveInsertable
676 */
677 template <class InputIterator>
678 void assign(InputIterator first, InputIterator last
679 //Input iterators
680 BOOST_CONTAINER_DOCIGN(BOOST_MOVE_I typename dtl::disable_if_or
681 < void
682 BOOST_MOVE_I dtl::is_convertible<InputIterator BOOST_MOVE_I size_type>
683 BOOST_MOVE_I dtl::is_not_input_iterator<InputIterator>
684 >::type * = 0)
685 )
686 {
687 first = overwrite_buffer_impl(first, last, dtl::false_());
688 while (first != last)
689 {
690 this->emplace_back(*first++);
691 }
692 }
693
694 #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
695
696 template <class ForwardIterator>
697 void assign(ForwardIterator first, ForwardIterator last
698 //Other iterators
699 BOOST_CONTAINER_DOCIGN(BOOST_MOVE_I typename dtl::disable_if_or
700 < void
701 BOOST_MOVE_I dtl::is_convertible<ForwardIterator BOOST_MOVE_I size_type>
702 BOOST_MOVE_I dtl::is_input_iterator<ForwardIterator>
703 >::type * = 0)
704 )
705 {
1e59de90 706 const size_type n = boost::container::iterator_udistance(first, last);
20effc67
TL
707
708 if (capacity() >= n)
709 {
710 overwrite_buffer(first, last);
711 }
712 else
713 {
714 allocate_and_copy_range(first, last);
715 }
716
717 BOOST_ASSERT(invariants_ok());
718 }
719
720 #endif // ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
721
722 /**
723 * **Effects**: Replaces elements of `*this` with `n` copies of `u`.
724 * Previously held elements get copy assigned to or destroyed.
725 *
726 * **Requires**: `T` shall be [CopyInsertable] into `*this` and
727 * [CopyAssignable].
728 *
729 * **Precondition**: `u` is not a reference into `*this`.
730 *
731 * **Postcondition**: `size() == n` and the elements of
732 * `*this` are copies of `u`.
733 *
734 * **Exceptions**: Strong exception guarantee if `T` is nothrow copy assignable
735 * from `u` and `NothrowConstructible`, Basic exception guarantee otherwise.
736 *
737 * **Complexity**: Linear in `n` and the size of `*this`.
738 *
739 * [CopyInsertable]: http://en.cppreference.com/w/cpp/concept/CopyInsertable
740 * [CopyAssignable]: http://en.cppreference.com/w/cpp/concept/CopyAssignable
741 */
742 void assign(size_type n, const T& u)
743 {
744 cvalue_iterator first(u, n);
745 cvalue_iterator last;
746
747 assign(first, last);
748 }
749
750 #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
751 /** **Equivalent to**: `assign(il.begin(), il.end())`. */
752 void assign(std::initializer_list<T> il)
753 {
754 assign(il.begin(), il.end());
755 }
756 #endif
757
758 /**
759 * **Returns**: A copy of the allocator associated with the container.
760 *
761 * **Complexity**: Constant.
762 */
1e59de90
TL
763 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
764 allocator_type get_allocator() const BOOST_NOEXCEPT
20effc67
TL
765 {
766 return static_cast<const allocator_type&>(m_);
767 }
768
1e59de90
TL
769 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
770 const allocator_type &get_stored_allocator() const BOOST_NOEXCEPT
20effc67
TL
771 {
772 return static_cast<const allocator_type&>(m_);
773 }
774
1e59de90
TL
775 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
776 allocator_type &get_stored_allocator() BOOST_NOEXCEPT
20effc67
TL
777 {
778 return static_cast<allocator_type&>(m_);
779 }
780
781 // iterators
782
783 /**
784 * **Returns**: A iterator pointing to the first element in the devector,
785 * or the past the end iterator if the devector is empty.
786 *
787 * **Complexity**: Constant.
788 */
1e59de90
TL
789 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
790 iterator begin() BOOST_NOEXCEPT
20effc67
TL
791 {
792 return m_.buffer + m_.front_idx;
793 }
794
795 /**
796 * **Returns**: A constant iterator pointing to the first element in the devector,
797 * or the past the end iterator if the devector is empty.
798 *
799 * **Complexity**: Constant.
800 */
1e59de90
TL
801 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
802 const_iterator begin() const BOOST_NOEXCEPT
20effc67
TL
803 {
804 return m_.buffer + m_.front_idx;
805 }
806
807 /**
808 * **Returns**: An iterator pointing past the last element of the container.
809 *
810 * **Complexity**: Constant.
811 */
1e59de90
TL
812 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
813 iterator end() BOOST_NOEXCEPT
20effc67
TL
814 {
815 return m_.buffer + m_.back_idx;
816 }
817
818 /**
819 * **Returns**: A constant iterator pointing past the last element of the container.
820 *
821 * **Complexity**: Constant.
822 */
1e59de90
TL
823 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
824 const_iterator end() const BOOST_NOEXCEPT
20effc67
TL
825 {
826 return m_.buffer + m_.back_idx;
827 }
828
829 /**
830 * **Returns**: A reverse iterator pointing to the first element in the reversed devector,
831 * or the reverse past the end iterator if the devector is empty.
832 *
833 * **Complexity**: Constant.
834 */
1e59de90
TL
835 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
836 reverse_iterator rbegin() BOOST_NOEXCEPT
20effc67
TL
837 {
838 return reverse_iterator(m_.buffer + m_.back_idx);
839 }
840
841 /**
842 * **Returns**: A constant reverse iterator
843 * pointing to the first element in the reversed devector,
844 * or the reverse past the end iterator if the devector is empty.
845 *
846 * **Complexity**: Constant.
847 */
1e59de90
TL
848 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
849 const_reverse_iterator rbegin() const BOOST_NOEXCEPT
20effc67
TL
850 {
851 return const_reverse_iterator(m_.buffer + m_.back_idx);
852 }
853
854 /**
855 * **Returns**: A reverse iterator pointing past the last element in the
856 * reversed container, or to the beginning of the reversed container if it's empty.
857 *
858 * **Complexity**: Constant.
859 */
1e59de90
TL
860 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
861 reverse_iterator rend() BOOST_NOEXCEPT
20effc67
TL
862 {
863 return reverse_iterator(m_.buffer + m_.front_idx);
864 }
865
866 /**
867 * **Returns**: A constant reverse iterator pointing past the last element in the
868 * reversed container, or to the beginning of the reversed container if it's empty.
869 *
870 * **Complexity**: Constant.
871 */
1e59de90
TL
872 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
873 const_reverse_iterator rend() const BOOST_NOEXCEPT
20effc67
TL
874 {
875 return const_reverse_iterator(m_.buffer + m_.front_idx);
876 }
877
878 /**
879 * **Returns**: A constant iterator pointing to the first element in the devector,
880 * or the past the end iterator if the devector is empty.
881 *
882 * **Complexity**: Constant.
883 */
1e59de90
TL
884 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
885 const_iterator cbegin() const BOOST_NOEXCEPT
20effc67
TL
886 {
887 return m_.buffer + m_.front_idx;
888 }
889
890 /**
891 * **Returns**: A constant iterator pointing past the last element of the container.
892 *
893 * **Complexity**: Constant.
894 */
895 const_iterator cend() const BOOST_NOEXCEPT
896 {
897 return m_.buffer + m_.back_idx;
898 }
899
900 /**
901 * **Returns**: A constant reverse iterator
902 * pointing to the first element in the reversed devector,
903 * or the reverse past the end iterator if the devector is empty.
904 *
905 * **Complexity**: Constant.
906 */
1e59de90
TL
907 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
908 const_reverse_iterator crbegin() const BOOST_NOEXCEPT
20effc67
TL
909 {
910 return const_reverse_iterator(m_.buffer + m_.back_idx);
911 }
912
913 /**
914 * **Returns**: A constant reverse iterator pointing past the last element in the
915 * reversed container, or to the beginning of the reversed container if it's empty.
916 *
917 * **Complexity**: Constant.
918 */
1e59de90
TL
919 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
920 const_reverse_iterator crend() const BOOST_NOEXCEPT
20effc67
TL
921 {
922 return const_reverse_iterator(m_.buffer + m_.front_idx);
923 }
924
925 // capacity
926
927 /**
928 * **Returns**: True, if `size() == 0`, false otherwise.
929 *
930 * **Complexity**: Constant.
931 */
1e59de90
TL
932 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
933 bool empty() const BOOST_NOEXCEPT
20effc67
TL
934 {
935 return m_.front_idx == m_.back_idx;
936 }
937
938 /**
939 * **Returns**: The number of elements the devector contains.
940 *
941 * **Complexity**: Constant.
942 */
1e59de90
TL
943 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
944 size_type size() const BOOST_NOEXCEPT
20effc67 945 {
1e59de90 946 return size_type(m_.back_idx - m_.front_idx);
20effc67
TL
947 }
948
949 /**
950 * **Returns**: The maximum number of elements the devector could possibly hold.
951 *
952 * **Complexity**: Constant.
953 */
1e59de90
TL
954 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
955 size_type max_size() const BOOST_NOEXCEPT
20effc67
TL
956 {
957 size_type alloc_max = allocator_traits_type::max_size(get_allocator_ref());
958 size_type size_type_max = (size_type)-1;
959 return (alloc_max <= size_type_max) ? size_type(alloc_max) : size_type_max;
960 }
961
962 /**
963 * **Returns**: The total number of elements that the devector can hold without requiring reallocation.
964 *
965 * **Complexity**: Constant.
966 */
1e59de90
TL
967 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
968 size_type capacity() const BOOST_NOEXCEPT
20effc67
TL
969 {
970 return m_.capacity;
971 }
972
973 /**
974 * **Returns**: The total number of elements that can be pushed to the front of the
975 * devector without requiring reallocation.
976 *
977 * **Complexity**: Constant.
978 */
1e59de90
TL
979 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
980 size_type front_free_capacity() const BOOST_NOEXCEPT
20effc67
TL
981 {
982 return m_.front_idx;
983 }
984
985 /**
986 * **Returns**: The total number of elements that can be pushed to the back of the
987 * devector without requiring reallocation.
988 *
989 * **Complexity**: Constant.
990 */
1e59de90
TL
991 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
992 size_type back_free_capacity() const BOOST_NOEXCEPT
20effc67 993 {
1e59de90 994 return size_type(m_.capacity - m_.back_idx);
20effc67
TL
995 }
996
997 /** **Equivalent to**: `resize_back(sz)` */
998 void resize(size_type sz) { resize_back(sz); }
999
1000 /** **Equivalent to**: `resize_back(sz, c)` */
1001 void resize(size_type sz, const T& c) { resize_back(sz, c); }
1002
1003 /**
1004 * **Effects**: If `sz` is greater than the size of `*this`,
1005 * additional value-initialized elements are inserted
1006 * to the front. Invalidates iterators if reallocation is needed.
1007 * If `sz` is smaller than than the size of `*this`,
1008 * elements are popped from the front.
1009 *
1010 * **Requires**: T shall be [MoveInsertable] into *this and [DefaultConstructible].
1011 *
1012 * **Postcondition**: `sz == size()`.
1013 *
1014 * **Exceptions**: Strong exception guarantee.
1015 *
1016 * **Complexity**: Linear in the size of `*this` and `sz`.
1017 *
1018 * [MoveInsertable]: http://en.cppreference.com/w/cpp/concept/MoveInsertable
1019 * [DefaultConstructible]: http://en.cppreference.com/w/cpp/concept/DefaultConstructible
1020 */
1021 void resize_front(size_type sz)
1022 {
1023 resize_front_impl(sz);
1024 BOOST_ASSERT(invariants_ok());
1025 }
1026
1027 /**
1028 * [CopyInsertable]: http://en.cppreference.com/w/cpp/concept/CopyInsertable
1029 *
1030 * **Effects**: If `sz` is greater than the size of `*this`,
1031 * copies of `c` are inserted to the front.
1032 * Invalidates iterators if reallocation is needed.
1033 * If `sz` is smaller than than the size of `*this`,
1034 * elements are popped from the front.
1035 *
1036 * **Postcondition**: `sz == size()`.
1037 *
1038 * **Requires**: `T` shall be [CopyInsertable] into `*this`.
1039 *
1040 * **Exceptions**: Strong exception guarantee.
1041 *
1042 * **Complexity**: Linear in the size of `*this` and `sz`.
1043 */
1044 void resize_front(size_type sz, const T& c)
1045 {
1046 resize_front_impl(sz, c);
1047 BOOST_ASSERT(invariants_ok());
1048 }
1049
1050 /**
1051 * **Effects**: If `sz` is greater than the size of `*this`,
1052 * additional value-initialized elements are inserted
1053 * to the back. Invalidates iterators if reallocation is needed.
1054 * If `sz` is smaller than than the size of `*this`,
1055 * elements are popped from the back.
1056 *
1057 * **Requires**: T shall be [MoveInsertable] into *this and [DefaultConstructible].
1058 *
1059 * **Postcondition**: `sz == size()`.
1060 *
1061 * **Exceptions**: Strong exception guarantee.
1062 *
1063 * **Complexity**: Linear in the size of `*this` and `sz`.
1064 *
1065 * [MoveInsertable]: http://en.cppreference.com/w/cpp/concept/MoveInsertable
1066 * [DefaultConstructible]: http://en.cppreference.com/w/cpp/concept/DefaultConstructible
1067 */
1068 void resize_back(size_type sz)
1069 {
1070 resize_back_impl(sz);
1071 BOOST_ASSERT(invariants_ok());
1072 }
1073
1074 /**
1075 * [CopyInsertable]: http://en.cppreference.com/w/cpp/concept/CopyInsertable
1076 *
1077 * **Effects**: If `sz` is greater than the size of `*this`,
1078 * copies of `c` are inserted to the back.
1079 * If `sz` is smaller than than the size of `*this`,
1080 * elements are popped from the back.
1081 *
1082 * **Postcondition**: `sz == size()`.
1083 *
1084 * **Requires**: `T` shall be [CopyInsertable] into `*this`.
1085 *
1086 * **Exceptions**: Strong exception guarantee.
1087 *
1088 * **Complexity**: Linear in the size of `*this` and `sz`.
1089 */
1090 void resize_back(size_type sz, const T& c)
1091 {
1092 resize_back_impl(sz, c);
1093 BOOST_ASSERT(invariants_ok());
1094 }
1095
1096 // unsafe uninitialized resize methods
1097
1098 /**
1099 * **Unsafe method**, use with care.
1100 *
1101 * **Effects**: Changes the size of the devector without properly
1102 * initializing the extra or destroying the superfluous elements.
1103 * If `n < size()`, elements are removed from the front without
1104 * getting destroyed; if `n > size()`, uninitialized elements are added
1105 * before the first element at the front.
1106 * Invalidates iterators if reallocation is needed.
1107 *
1108 * **Postcondition**: `size() == n`.
1109 *
1110 * **Exceptions**: Strong exception guarantee.
1111 *
1112 * **Complexity**: Linear in `size()` if `capacity() < n`, constant otherwise.
1113 *
1114 * **Remarks**: The devector does not keep track of initialization of the elements:
1115 * Elements without a trivial destructor must be manually destroyed before shrinking,
1116 * elements without a trivial constructor must be initialized after growing.
1117 */
1118/*
1119 void unsafe_uninitialized_resize_front(size_type n)
1120 {
1121 if (n > size())
1122 {
1123 unsafe_uninitialized_grow_front(n);
1124 }
1125 else
1126 {
1127 unsafe_uninitialized_shrink_front(n);
1128 }
1129 }
1130*/
1131 /**
1132 * **Unsafe method**, use with care.
1133 *
1134 * **Effects**: Changes the size of the devector without properly
1135 * initializing the extra or destroying the superfluous elements.
1136 * If `n < size()`, elements are removed from the back without
1137 * getting destroyed; if `n > size()`, uninitialized elements are added
1138 * after the last element at the back.
1139 * Invalidates iterators if reallocation is needed.
1140 *
1141 * **Postcondition**: `size() == n`.
1142 *
1143 * **Exceptions**: Strong exception guarantee.
1144 *
1145 * **Complexity**: Linear in `size()` if `capacity() < n`, constant otherwise.
1146 *
1147 * **Remarks**: The devector does not keep track of initialization of the elements:
1148 * Elements without a trivial destructor must be manually destroyed before shrinking,
1149 * elements without a trivial constructor must be initialized after growing.
1150 */
1151/*
1152 void unsafe_uninitialized_resize_back(size_type n)
1153 {
1154 if (n > size())
1155 {
1156 unsafe_uninitialized_grow_back(n);
1157 }
1158 else
1159 {
1160 unsafe_uninitialized_shrink_back(n);
1161 }
1162 }
1163*/
1164 // reserve promise:
1165 // after reserve_[front,back](n), n - size() push_[front,back] will not allocate
1166
1167 /** **Equivalent to**: `reserve_back(new_capacity)` */
1168 void reserve(size_type new_capacity) { reserve_back(new_capacity); }
1169
1170 /**
1171 * [MoveInsertable]: http://en.cppreference.com/w/cpp/concept/MoveInsertable
1172 *
1173 * **Effects**: Ensures that `n` elements can be pushed to the front
1174 * without requiring reallocation, where `n` is `new_capacity - size()`,
1175 * if `n` is positive. Otherwise, there are no effects.
1176 * Invalidates iterators if reallocation is needed.
1177 *
1178 * **Requires**: `T` shall be [MoveInsertable] into `*this`.
1179 *
1180 * **Complexity**: Linear in the size of *this.
1181 *
1182 * **Exceptions**: Strong exception guarantee.
1183 *
1184 * **Throws**: `length_error` if `new_capacity > max_size()`.
1185 */
1186 void reserve_front(size_type new_capacity)
1187 {
1188 if (front_capacity() >= new_capacity) { return; }
1189
1190 reallocate_at(new_capacity + back_free_capacity(), new_capacity - size());
1191
1192 BOOST_ASSERT(invariants_ok());
1193 }
1194
1195 /**
1196 * [MoveInsertable]: http://en.cppreference.com/w/cpp/concept/MoveInsertable
1197 *
1198 * **Effects**: Ensures that `n` elements can be pushed to the back
1199 * without requiring reallocation, where `n` is `new_capacity - size()`,
1200 * if `n` is positive. Otherwise, there are no effects.
1201 * Invalidates iterators if reallocation is needed.
1202 *
1203 * **Requires**: `T` shall be [MoveInsertable] into `*this`.
1204 *
1205 * **Complexity**: Linear in the size of *this.
1206 *
1207 * **Exceptions**: Strong exception guarantee.
1208 *
1209 * **Throws**: length_error if `new_capacity > max_size()`.
1210 */
1211 void reserve_back(size_type new_capacity)
1212 {
1213 if (back_capacity() >= new_capacity) { return; }
1214
1215 reallocate_at(new_capacity + front_free_capacity(), m_.front_idx);
1216
1217 BOOST_ASSERT(invariants_ok());
1218 }
1219
1220
1221 /**
1222 * [MoveInsertable]: http://en.cppreference.com/w/cpp/concept/MoveInsertable
1223 *
1224 * **Effects**: Reduces `capacity()` to `size()`. Invalidates iterators.
1225 *
1226 * **Requires**: `T` shall be [MoveInsertable] into `*this`.
1227 *
1228 * **Exceptions**: Strong exception guarantee.
1229 *
1230 * **Complexity**: Linear in the size of *this.
1231 */
1232 void shrink_to_fit()
1233 {
1234 if(this->front_capacity() || this->back_capacity())
1235 this->reallocate_at(size(), 0);
1236 }
1237
1238 // element access:
1239
1240 /**
1241 * **Returns**: A reference to the `n`th element in the devector.
1242 *
1243 * **Precondition**: `n < size()`.
1244 *
1245 * **Complexity**: Constant.
1246 */
1e59de90
TL
1247 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
1248 reference operator[](size_type n) BOOST_NOEXCEPT
20effc67
TL
1249 {
1250 BOOST_ASSERT(n < size());
20effc67
TL
1251 return *(begin() + n);
1252 }
1253
1254 /**
1255 * **Returns**: A constant reference to the `n`th element in the devector.
1256 *
1257 * **Precondition**: `n < size()`.
1258 *
1259 * **Complexity**: Constant.
1260 */
1e59de90
TL
1261 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
1262 const_reference operator[](size_type n) const BOOST_NOEXCEPT
20effc67
TL
1263 {
1264 BOOST_ASSERT(n < size());
1265
1266 return *(begin() + n);
1267 }
1268
1269 /**
1270 * **Returns**: A reference to the `n`th element in the devector.
1271 *
1e59de90 1272 * **Throws**: `out_of_range`, if `n >= size()`.
20effc67
TL
1273 *
1274 * **Complexity**: Constant.
1275 */
1e59de90
TL
1276 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
1277 reference at(size_type n)
20effc67
TL
1278 {
1279 if (size() <= n)
1280 throw_out_of_range("devector::at out of range");
1281 return (*this)[n];
1282 }
1283
1284 /**
1285 * **Returns**: A constant reference to the `n`th element in the devector.
1286 *
1e59de90 1287 * **Throws**: `out_of_range`, if `n >= size()`.
20effc67
TL
1288 *
1289 * **Complexity**: Constant.
1290 */
1e59de90
TL
1291 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
1292 const_reference at(size_type n) const
20effc67
TL
1293 {
1294 if (size() <= n)
1295 throw_out_of_range("devector::at out of range");
1296 return (*this)[n];
1297 }
1298
1299 /**
1300 * **Returns**: A reference to the first element in the devector.
1301 *
1302 * **Precondition**: `!empty()`.
1303 *
1304 * **Complexity**: Constant.
1305 */
1e59de90
TL
1306 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
1307 reference front() BOOST_NOEXCEPT
20effc67
TL
1308 {
1309 BOOST_ASSERT(!empty());
1310
1311 return *(m_.buffer + m_.front_idx);
1312 }
1313
1314 /**
1315 * **Returns**: A constant reference to the first element in the devector.
1316 *
1317 * **Precondition**: `!empty()`.
1318 *
1319 * **Complexity**: Constant.
1320 */
1e59de90
TL
1321 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
1322 const_reference front() const BOOST_NOEXCEPT
20effc67
TL
1323 {
1324 BOOST_ASSERT(!empty());
1325
1326 return *(m_.buffer + m_.front_idx);
1327 }
1328
1329 /**
1330 * **Returns**: A reference to the last element in the devector.
1331 *
1332 * **Precondition**: `!empty()`.
1333 *
1334 * **Complexity**: Constant.
1335 */
1e59de90
TL
1336 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
1337 reference back() BOOST_NOEXCEPT
20effc67
TL
1338 {
1339 BOOST_ASSERT(!empty());
1340
1341 return *(m_.buffer + m_.back_idx -1);
1342 }
1343
1344 /**
1345 * **Returns**: A constant reference to the last element in the devector.
1346 *
1347 * **Precondition**: `!empty()`.
1348 *
1349 * **Complexity**: Constant.
1350 */
1e59de90
TL
1351 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
1352 const_reference back() const BOOST_NOEXCEPT
20effc67
TL
1353 {
1354 BOOST_ASSERT(!empty());
1355
1356 return *(m_.buffer + m_.back_idx -1);
1357 }
1358
1359 /**
1360 * **Returns**: A pointer to the underlying array serving as element storage.
1361 * The range `[data(); data() + size())` is always valid. For a non-empty devector,
1362 * `data() == &front()`.
1363 *
1364 * **Complexity**: Constant.
1365 */
1e59de90
TL
1366 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
1367 T* data() BOOST_NOEXCEPT
20effc67
TL
1368 {
1369 return boost::movelib::to_raw_pointer(m_.buffer) + m_.front_idx;
1370 }
1371
1372 /**
1373 * **Returns**: A constant pointer to the underlying array serving as element storage.
1374 * The range `[data(); data() + size())` is always valid. For a non-empty devector,
1375 * `data() == &front()`.
1376 *
1377 * **Complexity**: Constant.
1378 */
1e59de90
TL
1379 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
1380 const T* data() const BOOST_NOEXCEPT
20effc67
TL
1381 {
1382 return boost::movelib::to_raw_pointer(m_.buffer) + m_.front_idx;
1383 }
1384
1385 // modifiers:
1386
1387 /**
1388 * **Effects**: Pushes a new element to the front of the devector.
1389 * The element is constructed in-place, using the perfect forwarded `args`
1390 * as constructor arguments. Invalidates iterators if reallocation is needed.
1391 * (`front_free_capacity() == 0`)
1392 *
1393 * **Requires**: `T` shall be [EmplaceConstructible] from `args` and [MoveInsertable] into `*this`.
1394 *
1395 * **Exceptions**: Strong exception guarantee.
1396 *
1397 * **Complexity**: Amortized constant in the size of `*this`.
1398 * (Constant, if `front_free_capacity() > 0`)
1399 *
1400 * [EmplaceConstructible]: http://en.cppreference.com/w/cpp/concept/EmplaceConstructible
1401 * [MoveInsertable]: http://en.cppreference.com/w/cpp/concept/MoveInsertable
1402 */
1403 #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
1404 template <class... Args>
1405 void emplace_front(Args&&... args)
1406 {
1407 if (front_free_capacity()) // fast path
1408 {
1409 this->alloc_construct(m_.buffer + m_.front_idx - 1, boost::forward<Args>(args)...);
1410 --m_.front_idx;
1411 }
1412 else
1413 {
1414 this->emplace_reallocating_slow_path(true, 0, boost::forward<Args>(args)...);
1415 }
1416
1417 BOOST_ASSERT(invariants_ok());
1418 }
1419
1420 #else //!defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
1421
1422 #define BOOST_CONTAINER_DEVECTOR_EMPLACE_FRONT(N) \
1423 BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
1424 BOOST_CONTAINER_FORCEINLINE void emplace_front(BOOST_MOVE_UREF##N)\
1425 {\
1426 if (front_free_capacity())\
1427 {\
1428 this->alloc_construct(m_.buffer + m_.front_idx - 1 BOOST_MOVE_I##N BOOST_MOVE_FWD##N);\
1429 --m_.front_idx;\
1430 }\
1431 else\
1432 {\
1433 this->emplace_reallocating_slow_path(true, 0 BOOST_MOVE_I##N BOOST_MOVE_FWD##N);\
1434 }\
1435 \
1436 BOOST_ASSERT(invariants_ok());\
1437 }\
1438 //
1439 BOOST_MOVE_ITERATE_0TO9(BOOST_CONTAINER_DEVECTOR_EMPLACE_FRONT)
1440 #undef BOOST_CONTAINER_DEVECTOR_EMPLACE_FRONT
1441
1442 #endif
1443
1444 #if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
1445 /**
1446 * [CopyInsertable]: http://en.cppreference.com/w/cpp/concept/CopyInsertable
1447 *
1448 * **Effects**: Pushes the copy of `x` to the front of the devector.
1449 * Invalidates iterators if reallocation is needed.
1450 * (`front_free_capacity() == 0`)
1451 *
1452 * **Requires**: `T` shall be [CopyInsertable] into `*this`.
1453 *
1454 * **Exceptions**: Strong exception guarantee.
1455 *
1456 * **Complexity**: Amortized constant in the size of `*this`.
1457 * (Constant, if `front_free_capacity() > 0`)
1458 */
1459 void push_front(const T& x);
1460
1461 /**
1462 * [MoveInsertable]: http://en.cppreference.com/w/cpp/concept/MoveInsertable
1463 *
1464 * **Effects**: Move constructs a new element at the front of the devector using `x`.
1465 * Invalidates iterators if reallocation is needed.
1466 * (`front_free_capacity() == 0`)
1467 *
1468 * **Requires**: `T` shall be [MoveInsertable] into `*this`.
1469 *
1470 * **Exceptions**: Strong exception guarantee, not regarding the state of `x`.
1471 *
1472 * **Complexity**: Amortized constant in the size of `*this`.
1473 * (Constant, if `front_free_capacity() > 0`)
1474 */
1475 void push_front(T&& x);
1476
1477 #else
1478 BOOST_MOVE_CONVERSION_AWARE_CATCH(push_front, T, void, priv_push_front)
1479 #endif
1480
1481 /**
1482 * **Effects**: Removes the first element of `*this`.
1483 *
1484 * **Precondition**: `!empty()`.
1485 *
1486 * **Postcondition**: `front_free_capacity()` is incremented by 1.
1487 *
1488 * **Complexity**: Constant.
1489 */
1490 void pop_front() BOOST_NOEXCEPT
1491 {
1492 BOOST_ASSERT(! empty());
1493 allocator_traits_type::destroy(get_allocator_ref(), m_.buffer + m_.front_idx);
1494 ++m_.front_idx;
1495 BOOST_ASSERT(invariants_ok());
1496 }
1497
1498 /**
1499 * **Effects**: Pushes a new element to the back of the devector.
1500 * The element is constructed in-place, using the perfect forwarded `args`
1501 * as constructor arguments. Invalidates iterators if reallocation is needed.
1502 * (`back_free_capacity() == 0`)
1503 *
1504 * **Requires**: `T` shall be [EmplaceConstructible] from `args` and [MoveInsertable] into `*this`,
1505 * and [MoveAssignable].
1506 *
1507 * **Exceptions**: Strong exception guarantee.
1508 *
1509 * **Complexity**: Amortized constant in the size of `*this`.
1510 * (Constant, if `back_free_capacity() > 0`)
1511 *
1512 * [EmplaceConstructible]: http://en.cppreference.com/w/cpp/concept/EmplaceConstructible
1513 * [MoveInsertable]: http://en.cppreference.com/w/cpp/concept/MoveInsertable
1514 * [MoveAssignable]: http://en.cppreference.com/w/cpp/concept/MoveAssignable
1515 */
1516 #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
1517 template <class... Args>
1518 BOOST_CONTAINER_FORCEINLINE void emplace_back(Args&&... args)
1519 {
1520 if (this->back_free_capacity()){
1521 this->alloc_construct(m_.buffer + m_.back_idx, boost::forward<Args>(args)...);
1522 ++m_.back_idx;
1523 }
1524 else {
1525 this->emplace_reallocating_slow_path(false, size(), boost::forward<Args>(args)...);
1526 }
1527 BOOST_ASSERT(invariants_ok());
1528 }
1529
1530 #else //!defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
1531
1532 #define BOOST_CONTAINER_DEVECTOR_EMPLACE_BACK(N) \
1533 BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
1534 BOOST_CONTAINER_FORCEINLINE void emplace_back(BOOST_MOVE_UREF##N)\
1535 {\
1536 if (this->back_free_capacity()){\
1537 this->alloc_construct(m_.buffer + m_.back_idx BOOST_MOVE_I##N BOOST_MOVE_FWD##N);\
1538 ++m_.back_idx;\
1539 }\
1540 else {\
1541 this->emplace_reallocating_slow_path(false, size() BOOST_MOVE_I##N BOOST_MOVE_FWD##N);\
1542 }\
1543 BOOST_ASSERT(invariants_ok());\
1544 }\
1545 //
1546 BOOST_MOVE_ITERATE_0TO9(BOOST_CONTAINER_DEVECTOR_EMPLACE_BACK)
1547 #undef BOOST_CONTAINER_DEVECTOR_EMPLACE_BACK
1548
1549 #endif //!defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
1550
1551
1552 #if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
1553 /**
1554 * [CopyInsertable]: http://en.cppreference.com/w/cpp/concept/CopyInsertable
1555 *
1556 * **Effects**: Pushes the copy of `x` to the back of the devector.
1557 * Invalidates iterators if reallocation is needed.
1558 * (`back_free_capacity() == 0`)
1559 *
1560 * **Requires**: `T` shall be [CopyInsertable] into `*this`.
1561 *
1562 * **Exceptions**: Strong exception guarantee.
1563 *
1564 * **Complexity**: Amortized constant in the size of `*this`.
1565 * (Constant, if `back_free_capacity() > 0`)
1566 */
1567 void push_back(const T& x);
1568
1569 /**
1570 * [MoveInsertable]: http://en.cppreference.com/w/cpp/concept/MoveInsertable
1571 *
1572 * **Effects**: Move constructs a new element at the back of the devector using `x`.
1573 * Invalidates iterators if reallocation is needed.
1574 * (`back_free_capacity() == 0`)
1575 *
1576 * **Requires**: `T` shall be [MoveInsertable] into `*this`.
1577 *
1578 * **Exceptions**: Strong exception guarantee, not regarding the state of `x`.
1579 *
1580 * **Complexity**: Amortized constant in the size of `*this`.
1581 * (Constant, if `back_free_capacity() > 0`)
1582 */
1583 void push_back(T&& x);
1584
1585 #else
1586 BOOST_MOVE_CONVERSION_AWARE_CATCH(push_back, T, void, priv_push_back)
1587 #endif
1588
1589 /**
1590 * **Effects**: Removes the last element of `*this`.
1591 *
1592 * **Precondition**: `!empty()`.
1593 *
1594 * **Postcondition**: `back_free_capacity()` is incremented by 1.
1595 *
1596 * **Complexity**: Constant.
1597 */
1598 void pop_back() BOOST_NOEXCEPT
1599 {
1600 BOOST_ASSERT(! empty());
1601 --m_.back_idx;
1602 allocator_traits_type::destroy(get_allocator_ref(), m_.buffer + m_.back_idx);
1603 BOOST_ASSERT(invariants_ok());
1604 }
1605
1606 /**
1607 * **Effects**: Constructs a new element before the element pointed by `position`.
1608 * The element is constructed in-place, using the perfect forwarded `args`
1609 * as constructor arguments. Invalidates iterators if reallocation is needed.
1610 *
1611 * **Requires**: `T` shall be [EmplaceConstructible], and [MoveInsertable] into `*this`,
1612 * and [MoveAssignable].
1613 *
1614 * **Returns**: Iterator pointing to the newly constructed element.
1615 *
1616 * **Exceptions**: Strong exception guarantee if `T` is `NothrowConstructible`
1617 * and `NothrowAssignable`, Basic exception guarantee otherwise.
1618 *
1619 * **Complexity**: Linear in the size of `*this`.
1620 *
1621 * [EmplaceConstructible]: http://en.cppreference.com/w/cpp/concept/EmplaceConstructible
1622 * [MoveInsertable]: http://en.cppreference.com/w/cpp/concept/MoveInsertable
1623 * [MoveAssignable]: http://en.cppreference.com/w/cpp/concept/MoveAssignable
1624 */
1625 #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
1626 template <class... Args>
1627 iterator emplace(const_iterator position, Args&&... args)
1628 {
1629 BOOST_ASSERT(position >= begin());
1630 BOOST_ASSERT(position <= end());
1631
1632 if (position == end() && back_free_capacity()) // fast path
1633 {
1634 this->alloc_construct(m_.buffer + m_.back_idx, boost::forward<Args>(args)...);
1635 ++m_.back_idx;
1636 return end() - 1;
1637 }
1638 else if (position == begin() && front_free_capacity()) // secondary fast path
1639 {
1640 this->alloc_construct(m_.buffer + (m_.front_idx - 1), boost::forward<Args>(args)...);
1641 --m_.front_idx;
1642 return begin();
1643 }
1644 else
1645 {
1e59de90 1646 size_type new_elem_index = size_type(position - begin());
20effc67
TL
1647 return this->emplace_slow_path(new_elem_index, boost::forward<Args>(args)...);
1648 }
1649 }
1650
1651 #else //!defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
1652
1653 #define BOOST_CONTAINER_DEVECTOR_EMPLACE(N) \
1654 BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
1655 iterator emplace(const_iterator position BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\
1656 {\
1657 BOOST_ASSERT(position >= begin());\
1658 BOOST_ASSERT(position <= end());\
1659 \
1660 if (position == end() && back_free_capacity()){\
1661 this->alloc_construct(m_.buffer + m_.back_idx BOOST_MOVE_I##N BOOST_MOVE_FWD##N);\
1662 ++m_.back_idx;\
1663 return end() - 1;\
1664 }\
1665 else if (position == begin() && front_free_capacity()){\
1666 this->alloc_construct(m_.buffer + m_.front_idx - 1 BOOST_MOVE_I##N BOOST_MOVE_FWD##N);\
1667 --m_.front_idx;\
1668 return begin();\
1669 }\
1670 else{\
1e59de90 1671 size_type new_elem_index = size_type(position - begin());\
20effc67
TL
1672 return this->emplace_slow_path(new_elem_index BOOST_MOVE_I##N BOOST_MOVE_FWD##N);\
1673 }\
1674 }\
1675 //
1676 BOOST_MOVE_ITERATE_0TO9(BOOST_CONTAINER_DEVECTOR_EMPLACE)
1677 #undef BOOST_CONTAINER_DEVECTOR_EMPLACE
1678
1679 #endif //!defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
1680
1681
1682 #if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
1683 /**
1684 * **Effects**: Copy constructs a new element before the element pointed by `position`,
1685 * using `x` as constructor argument. Invalidates iterators if reallocation is needed.
1686 *
1687 * **Requires**: `T` shall be [CopyInsertable] into `*this` and and [CopyAssignable].
1688 *
1689 * **Returns**: Iterator pointing to the newly constructed element.
1690 *
1691 * **Exceptions**: Strong exception guarantee if `T` is `NothrowConstructible`
1692 * and `NothrowAssignable`, Basic exception guarantee otherwise.
1693 *
1694 * **Complexity**: Linear in the size of `*this`.
1695 *
1696 * [CopyInsertable]: http://en.cppreference.com/w/cpp/concept/CopyInsertable
1697 * [CopyAssignable]: http://en.cppreference.com/w/cpp/concept/CopyAssignable
1698 */
1699 iterator insert(const_iterator position, const T &x);
1700
1701 /**
1702 * **Effects**: Move constructs a new element before the element pointed by `position`,
1703 * using `x` as constructor argument. Invalidates iterators if reallocation is needed.
1704 *
1705 * **Requires**: `T` shall be [MoveInsertable] into `*this` and and [CopyAssignable].
1706 *
1707 * **Returns**: Iterator pointing to the newly constructed element.
1708 *
1709 * **Exceptions**: Strong exception guarantee if `T` is `NothrowConstructible`
1710 * and `NothrowAssignable` (not regarding the state of `x`),
1711 * Basic exception guarantee otherwise.
1712 *
1713 * **Complexity**: Linear in the size of `*this`.
1714 *
1715 * [MoveInsertable]: http://en.cppreference.com/w/cpp/concept/MoveInsertable
1716 * [CopyAssignable]: http://en.cppreference.com/w/cpp/concept/CopyAssignable
1717 */
1718 iterator insert(const_iterator position, T &&x);
1719 #else
1720 BOOST_MOVE_CONVERSION_AWARE_CATCH_1ARG(insert, T, iterator, priv_insert, const_iterator, const_iterator)
1721 #endif
1722
1723 /**
1724 * **Effects**: Copy constructs `n` elements before the element pointed by `position`,
1725 * using `x` as constructor argument. Invalidates iterators if reallocation is needed.
1726 *
1727 * **Requires**: `T` shall be [CopyInsertable] into `*this` and and [CopyAssignable].
1728 *
1729 * **Returns**: Iterator pointing to the first inserted element, or `position`, if `n` is zero.
1730 *
1731 * **Exceptions**: Strong exception guarantee if `T` is `NothrowConstructible`
1732 * and `NothrowAssignable`, Basic exception guarantee otherwise.
1733 *
1734 * **Complexity**: Linear in the size of `*this` and `n`.
1735 *
1736 * [CopyInsertable]: http://en.cppreference.com/w/cpp/concept/CopyInsertable
1737 * [CopyAssignable]: http://en.cppreference.com/w/cpp/concept/CopyAssignable
1738 */
1739 iterator insert(const_iterator position, size_type n, const T& x)
1740 {
1741 cvalue_iterator first(x, n);
1742 cvalue_iterator last = first + n;
1743 return insert_range(position, first, last);
1744 }
1745
1746 /**
1747 * **Effects**: Copy constructs elements before the element pointed by position
1748 * using each element in the rage pointed by `first` and `last` as constructor arguments.
1749 * Invalidates iterators if reallocation is needed.
1750 *
1751 * **Requires**: `T` shall be [EmplaceConstructible] into `*this` from `*first`. If the specified iterator
1752 * does not meet the forward iterator requirements, `T` shall also be [MoveInsertable] into `*this`
1753 * and [MoveAssignable].
1754 *
1755 * **Precondition**: `first` and `last` are not iterators into `*this`.
1756 *
1757 * **Returns**: Iterator pointing to the first inserted element, or `position`, if `first == last`.
1758 *
1759 * **Complexity**: Linear in the size of `*this` and `N` (where `N` is the distance between `first` and `last`).
1760 * Makes only `N` calls to the constructor of `T` and no reallocations if iterators `first` and `last`
1761 * are of forward, bidirectional, or random access categories. It makes 2N calls to the copy constructor of `T`
1762 * and allocates memory twice at most if they are just input iterators.
1763 *
1764 * **Exceptions**: Strong exception guarantee if `T` is `NothrowConstructible`
1765 * and `NothrowAssignable`, Basic exception guarantee otherwise.
1766 *
1767 * **Remarks**: Each iterator in the range `[first,last)` shall be dereferenced exactly once,
1768 * unless an exception is thrown.
1769 *
1770 * [EmplaceConstructible]: http://en.cppreference.com/w/cpp/concept/EmplaceConstructible
1771 * [MoveInsertable]: http://en.cppreference.com/w/cpp/concept/MoveInsertable
1772 * [MoveAssignable]: http://en.cppreference.com/w/cpp/concept/MoveAssignable
1773 */
1774 template <class InputIterator>
1775 iterator insert(const_iterator position, InputIterator first, InputIterator last
1776 //Input iterators
1777 BOOST_CONTAINER_DOCIGN(BOOST_MOVE_I typename dtl::disable_if_or
1778 < void
1779 BOOST_MOVE_I dtl::is_convertible<InputIterator BOOST_MOVE_I size_type>
1780 BOOST_MOVE_I dtl::is_not_input_iterator<InputIterator>
1781 >::type * = 0)
1782 )
1783 {
1784 if (position == end())
1785 {
1786 size_type insert_index = size();
1787
1788 for (; first != last; ++first)
1789 {
1790 this->emplace_back(*first);
1791 }
1792
1793 return begin() + insert_index;
1794 }
1795 else
1796 {
1797 const size_type insert_index = static_cast<size_type>(position - this->cbegin());
1798 const size_type old_size = static_cast<size_type>(this->size());
1799
1800 for (; first != last; ++first) {
1801 this->emplace_back(*first);
1802 }
1803 iterator rit (this->begin() + insert_index);
1804 boost::movelib::rotate_gcd(rit, this->begin() + old_size, this->begin() + this->size());
1805 return rit;
1806 }
1807 }
1808
1809 #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
1810
1811 template <class ForwardIterator>
1812 iterator insert(const_iterator position, ForwardIterator first, ForwardIterator last
1813 //Other iterators
1814 BOOST_CONTAINER_DOCIGN(BOOST_MOVE_I typename dtl::disable_if_or
1815 < void
1816 BOOST_MOVE_I dtl::is_convertible<ForwardIterator BOOST_MOVE_I size_type>
1817 BOOST_MOVE_I dtl::is_input_iterator<ForwardIterator>
1818 >::type * = 0)
1819 )
1820 {
1821 return insert_range(position, first, last);
1822 }
1823
1824 #endif // ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
1825
1826 #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
1827 /** **Equivalent to**: `insert(position, il.begin(), il.end())` */
1828 iterator insert(const_iterator position, std::initializer_list<T> il)
1829 {
1830 return insert_range(position, il.begin(), il.end());
1831 }
1832 #endif
1833
1834 /**
1835 * [MoveAssignable]: http://en.cppreference.com/w/cpp/concept/MoveAssignable
1836 *
1837 * **Effects**: Destroys the element pointed by `position` and removes it from the devector.
1838 * Invalidates iterators.
1839 *
1840 * **Requires**: `T` shall be [MoveAssignable].
1841 *
1842 * **Precondition**: `position` must be in the range of `[begin(), end())`.
1843 *
1844 * **Returns**: Iterator pointing to the element immediately following the erased element
1845 * prior to its erasure. If no such element exists, `end()` is returned.
1846 *
1847 * **Exceptions**: Strong exception guarantee if `T` is `NothrowAssignable`,
1848 * Basic exception guarantee otherwise.
1849 *
1850 * **Complexity**: Linear in half the size of `*this`.
1851 */
1852 iterator erase(const_iterator position)
1853 {
1854 return erase(position, position + 1);
1855 }
1856
1857 /**
1858 * [MoveAssignable]: http://en.cppreference.com/w/cpp/concept/MoveAssignable
1859 *
1860 * **Effects**: Destroys the range `[first,last)` and removes it from the devector.
1861 * Invalidates iterators.
1862 *
1863 * **Requires**: `T` shall be [MoveAssignable].
1864 *
1865 * **Precondition**: `[first,last)` must be in the range of `[begin(), end())`.
1866 *
1867 * **Returns**: Iterator pointing to the element pointed to by `last` prior to any elements
1868 * being erased. If no such element exists, `end()` is returned.
1869 *
1870 * **Exceptions**: Strong exception guarantee if `T` is `NothrowAssignable`,
1871 * Basic exception guarantee otherwise.
1872 *
1873 * **Complexity**: Linear in half the size of `*this`
1874 * plus the distance between `first` and `last`.
1875 */
1876 iterator erase(const_iterator first, const_iterator last)
1877 {
1878 iterator nc_first = begin() + (first - begin());
1879 iterator nc_last = begin() + (last - begin());
1880 return erase(nc_first, nc_last);
1881 }
1882
1883 /**
1884 * [MoveAssignable]: http://en.cppreference.com/w/cpp/concept/MoveAssignable
1885 *
1886 * **Effects**: Destroys the range `[first,last)` and removes it from the devector.
1887 * Invalidates iterators.
1888 *
1889 * **Requires**: `T` shall be [MoveAssignable].
1890 *
1891 * **Precondition**: `[first,last)` must be in the range of `[begin(), end())`.
1892 *
1893 * **Returns**: Iterator pointing to the element pointed to by `last` prior to any elements
1894 * being erased. If no such element exists, `end()` is returned.
1895 *
1896 * **Exceptions**: Strong exception guarantee if `T` is `NothrowAssignable`,
1897 * Basic exception guarantee otherwise.
1898 *
1899 * **Complexity**: Linear in half the size of `*this`.
1900 */
1901 iterator erase(iterator first, iterator last)
1902 {
1e59de90
TL
1903 size_type front_distance = size_type(last - begin());
1904 size_type back_distance = size_type(end() - first);
1905 size_type n = boost::container::iterator_udistance(first, last);
20effc67
TL
1906
1907 if (front_distance < back_distance)
1908 {
1909 // move n to the right
1910 boost::container::move_backward(begin(), first, last);
1911
1912 for (iterator i = begin(); i != begin() + n; ++i)
1913 {
1914 allocator_traits_type::destroy(get_allocator_ref(), i);
1915 }
1916 //n is always less than max stored_size_type
1917 m_.set_front_idx(m_.front_idx + n);
1918
1919 BOOST_ASSERT(invariants_ok());
1920 return last;
1921 }
1922 else {
1923 // move n to the left
1924 boost::container::move(last, end(), first);
1925
1926 for (iterator i = end() - n; i != end(); ++i)
1927 {
1928 allocator_traits_type::destroy(get_allocator_ref(), i);
1929 }
1930 //n is always less than max stored_size_type
1931 m_.set_back_idx(m_.back_idx - n);
1932
1933 BOOST_ASSERT(invariants_ok());
1934 return first;
1935 }
1936 }
1937
1938 /**
1939 * [MoveInsertable]: http://en.cppreference.com/w/cpp/concept/MoveInsertable
1940 *
1941 * **Effects**: exchanges the contents of `*this` and `b`.
1942 *
1943 * **Requires**: instances of `T` must be swappable by unqualified call of `swap`
1944 * and `T` must be [MoveInsertable] into `*this`.
1945 *
1946 * **Precondition**: The allocators should allow propagation or should compare equal.
1947 *
1948 * **Exceptions**: Basic exceptions guarantee if not `noexcept`.
1949 *
1950 * **Complexity**: Constant.
1951 */
1952 void swap(devector& b)
1953 BOOST_NOEXCEPT_IF( allocator_traits_type::propagate_on_container_swap::value
1954 || allocator_traits_type::is_always_equal::value)
1955 {
1956 BOOST_CONSTEXPR_OR_CONST bool propagate_alloc = allocator_traits_type::propagate_on_container_swap::value;
1957 BOOST_ASSERT(propagate_alloc || get_allocator_ref() == b.get_allocator_ref()); // else it's undefined behavior
1958
1959 swap_big_big(*this, b);
1960
1961 // swap indices
1962 boost::adl_move_swap(m_.front_idx, b.m_.front_idx);
1963 boost::adl_move_swap(m_.back_idx, b.m_.back_idx);
1964
1965 //And now swap the allocator
1966 dtl::swap_alloc(this->get_allocator_ref(), b.get_allocator_ref(), dtl::bool_<propagate_alloc>());
1967
1968 BOOST_ASSERT( invariants_ok());
1969 BOOST_ASSERT(b.invariants_ok());
1970 }
1971
1972 /**
1973 * **Effects**: Destroys all elements in the devector.
1974 * Invalidates all references, pointers and iterators to the
1975 * elements of the devector.
1976 *
1977 * **Postcondition**: `empty() && front_free_capacity() == 0
1978 * && back_free_capacity() == old capacity`.
1979 *
1980 * **Complexity**: Linear in the size of `*this`.
1981 *
1982 * **Remarks**: Does not free memory.
1983 */
1984 void clear() BOOST_NOEXCEPT
1985 {
1986 destroy_elements(begin(), end());
1987 m_.front_idx = m_.back_idx = 0;
1988 }
1989
1e59de90
TL
1990 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
1991 friend bool operator==(const devector& x, const devector& y)
20effc67
TL
1992 { return x.size() == y.size() && ::boost::container::algo_equal(x.begin(), x.end(), y.begin()); }
1993
1e59de90
TL
1994 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
1995 friend bool operator!=(const devector& x, const devector& y)
20effc67
TL
1996 { return !(x == y); }
1997
1e59de90
TL
1998 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
1999 friend bool operator< (const devector& x, const devector& y)
20effc67
TL
2000 { return boost::container::algo_lexicographical_compare(x.begin(), x.end(), y.begin(), y.end()); }
2001
1e59de90
TL
2002 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
2003 friend bool operator>(const devector& x, const devector& y)
20effc67
TL
2004 { return y < x; }
2005
1e59de90
TL
2006 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
2007 friend bool operator<=(const devector& x, const devector& y)
20effc67
TL
2008 { return !(y < x); }
2009
1e59de90
TL
2010 BOOST_CONTAINER_ATTRIBUTE_NODISCARD BOOST_CONTAINER_FORCEINLINE
2011 friend bool operator>=(const devector& x, const devector& y)
20effc67
TL
2012 { return !(x < y); }
2013
2014 BOOST_CONTAINER_FORCEINLINE friend void swap(devector& x, devector& y)
1e59de90
TL
2015 BOOST_NOEXCEPT_IF( allocator_traits_type::propagate_on_container_swap::value
2016 || allocator_traits_type::is_always_equal::value)
20effc67
TL
2017 { x.swap(y); }
2018
2019 private:
2020 #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
2021
1e59de90 2022 BOOST_CONTAINER_FORCEINLINE T* raw_begin() BOOST_NOEXCEPT
20effc67
TL
2023 { return boost::movelib::to_raw_pointer(m_.buffer) + m_.front_idx; }
2024
1e59de90 2025 BOOST_CONTAINER_FORCEINLINE T* raw_end() BOOST_NOEXCEPT
20effc67
TL
2026 { return boost::movelib::to_raw_pointer(m_.buffer) + m_.back_idx; }
2027
2028
2029 template <class U>
2030 BOOST_CONTAINER_FORCEINLINE void priv_push_front(BOOST_FWD_REF(U) u)
2031 {
2032 this->emplace_front(boost::forward<U>(u));
2033 }
2034
2035 template <class U>
2036 BOOST_CONTAINER_FORCEINLINE void priv_push_back(BOOST_FWD_REF(U) u)
2037 {
2038 this->emplace_back(boost::forward<U>(u));
2039 }
2040
2041 template <class U>
2042 BOOST_CONTAINER_FORCEINLINE iterator priv_insert(const_iterator pos, BOOST_FWD_REF(U) u)
2043 {
2044 return this->emplace(pos, boost::forward<U>(u));
2045 }
2046
2047 // allocator_type wrappers
2048
2049 BOOST_CONTAINER_FORCEINLINE allocator_type& get_allocator_ref() BOOST_NOEXCEPT
2050 {
2051 return static_cast<allocator_type&>(m_);
2052 }
2053
2054 BOOST_CONTAINER_FORCEINLINE const allocator_type& get_allocator_ref() const BOOST_NOEXCEPT
2055 {
2056 return static_cast<const allocator_type&>(m_);
2057 }
2058
2059 pointer allocate(size_type capacity)
2060 {
1e59de90 2061 pointer const p = impl::do_allocate(get_allocator_ref(), capacity);
20effc67
TL
2062 #ifdef BOOST_CONTAINER_DEVECTOR_ALLOC_STATS
2063 ++m_.capacity_alloc_count;
2064 #endif // BOOST_CONTAINER_DEVECTOR_ALLOC_STATS
1e59de90 2065 return p;
20effc67
TL
2066 }
2067
2068 void destroy_elements(pointer begin, pointer end)
2069 {
2070 for (; begin != end; ++begin)
2071 {
2072 allocator_traits_type::destroy(get_allocator_ref(), begin);
2073 }
2074 }
2075
2076 void deallocate_buffer()
2077 {
2078 if (m_.buffer)
2079 {
1e59de90 2080 allocator_traits_type::deallocate(get_allocator_ref(), m_.buffer, m_.capacity);
20effc67
TL
2081 }
2082 }
2083
2084 #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
2085 template <typename... Args>
2086 BOOST_CONTAINER_FORCEINLINE void alloc_construct(pointer dst, Args&&... args)
2087 {
2088 allocator_traits_type::construct(
2089 get_allocator_ref(),
2090 dst,
2091 boost::forward<Args>(args)...
2092 );
2093 }
2094
2095 template <typename... Args>
2096 void construct_n(pointer buffer, size_type n, Args&&... args)
2097 {
2098 detail::construction_guard<allocator_type> ctr_guard(buffer, get_allocator_ref());
2099 guarded_construct_n(buffer, n, ctr_guard, boost::forward<Args>(args)...);
2100 ctr_guard.release();
2101 }
2102
2103 template <typename... Args>
2104 void guarded_construct_n(pointer buffer, size_type n, detail::construction_guard<allocator_type>& ctr_guard, Args&&... args)
2105 {
2106 for (size_type i = 0; i < n; ++i) {
2107 this->alloc_construct(buffer + i, boost::forward<Args>(args)...);
2108 ctr_guard.extend();
2109 }
2110 }
2111
2112 #else //!defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
2113
2114 #define BOOST_CONTAINER_DEVECTOR_ALLOC_CONSTRUCT(N) \
2115 BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
2116 BOOST_CONTAINER_FORCEINLINE void alloc_construct(pointer dst BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\
2117 {\
2118 allocator_traits_type::construct(\
2119 get_allocator_ref(), dst BOOST_MOVE_I##N BOOST_MOVE_FWD##N );\
2120 }\
2121 \
2122 BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
2123 void construct_n(pointer buffer, size_type n BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\
2124 {\
2125 detail::construction_guard<allocator_type> ctr_guard(buffer, get_allocator_ref());\
2126 guarded_construct_n(buffer, n, ctr_guard BOOST_MOVE_I##N BOOST_MOVE_FWD##N);\
2127 ctr_guard.release();\
2128 }\
2129 \
2130 BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
2131 void guarded_construct_n(pointer buffer, size_type n, detail::construction_guard<allocator_type>& ctr_guard BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\
2132 {\
2133 for (size_type i = 0; i < n; ++i) {\
2134 this->alloc_construct(buffer + i BOOST_MOVE_I##N BOOST_MOVE_FWD##N);\
2135 ctr_guard.extend();\
2136 }\
2137 }
2138 //
2139 BOOST_MOVE_ITERATE_0TO9(BOOST_CONTAINER_DEVECTOR_ALLOC_CONSTRUCT)
2140 #undef BOOST_CONTAINER_DEVECTOR_ALLOC_CONSTRUCT
2141
2142 #endif //!defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
2143
1e59de90 2144 BOOST_CONTAINER_FORCEINLINE size_type front_capacity() const
20effc67
TL
2145 {
2146 return m_.back_idx;
2147 }
2148
1e59de90 2149 BOOST_CONTAINER_FORCEINLINE size_type back_capacity() const
20effc67 2150 {
1e59de90 2151 return size_type(m_.capacity - m_.front_idx);
20effc67
TL
2152 }
2153
2154 size_type calculate_new_capacity(size_type requested_capacity)
2155 {
2156 size_type max = allocator_traits_type::max_size(this->get_allocator_ref());
2157 (clamp_by_stored_size_type)(max, stored_size_type());
2158 const size_type remaining_additional_cap = max - size_type(m_.capacity);
2159 const size_type min_additional_cap = requested_capacity - size_type(m_.capacity);
2160 if ( remaining_additional_cap < min_additional_cap )
2161 boost::container::throw_length_error("devector: get_next_capacity, max size exceeded");
2162
2163 return growth_factor_type()( size_type(m_.capacity), min_additional_cap, max);
2164 }
2165
2166 void buffer_move_or_copy(pointer dst)
2167 {
2168 detail::construction_guard<allocator_type> guard(dst, get_allocator_ref());
2169
2170 buffer_move_or_copy(dst, guard);
2171
2172 guard.release();
2173 }
2174
2175 void buffer_move_or_copy(pointer dst, detail::construction_guard<allocator_type>& guard)
2176 {
2177 opt_move_or_copy(begin(), end(), dst, guard);
2178
2179 destroy_elements(data(), data() + size());
2180 deallocate_buffer();
2181 }
2182
2183 void opt_move_or_copy(pointer begin, pointer end, pointer dst)
2184 {
2185 typedef typename dtl::if_c
2186 < boost::move_detail::is_nothrow_copy_constructible<T>::value || boost::is_nothrow_move_constructible<T>::value
2187 , detail::null_construction_guard
2188 , detail::construction_guard<allocator_type>
2189 >::type guard_t;
2190
2191 guard_t guard(dst, get_allocator_ref());
2192
2193 opt_move_or_copy(begin, end, dst, guard);
2194
2195 guard.release();
2196 }
2197
2198 template <typename Guard>
2199 void opt_move_or_copy(pointer begin, pointer end, pointer dst, Guard& guard)
2200 {
2201 // if trivial copy and default allocator, memcpy
2202 boost::container::uninitialized_move_alloc(get_allocator_ref(), begin, end, dst);
2203 guard.extend();
2204 }
2205
2206 template <typename Iterator>
2207 void opt_copy(Iterator begin, Iterator end, pointer dst)
2208 {
2209 typedef typename dtl::if_c
2210 < boost::move_detail::is_nothrow_copy_constructible<T>::value
2211 , detail::null_construction_guard
2212 , detail::construction_guard<allocator_type>
2213 >::type guard_t;
2214
2215 guard_t guard(dst, get_allocator_ref());
2216
2217 opt_copy(begin, end, dst, guard);
2218
2219 guard.release();
2220 }
2221
2222 template <typename Iterator, typename Guard>
2223 void opt_copy(Iterator begin, Iterator end, pointer dst, Guard& guard)
2224 {
2225 while (begin != end)
2226 {
2227 this->alloc_construct(dst++, *begin++);
2228 guard.extend();
2229 }
2230 }
2231
2232 template <typename Guard>
2233 void opt_copy(const_pointer begin, const_pointer end, pointer dst, Guard& guard)
2234 {
2235 // if trivial copy and default allocator, memcpy
2236 boost::container::uninitialized_copy_alloc(get_allocator_ref(), begin, end, dst);
2237 guard.extend();
2238 }
2239
2240 #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
2241
2242 template <typename... Args>
2243 void resize_front_impl(size_type sz , Args&&... args)
2244 {
2245 if (sz > size())
2246 {
2247 const size_type n = sz - size();
2248
2249 if (sz <= front_capacity())
2250 {
2251 construct_n(m_.buffer + m_.front_idx - n, n, boost::forward<Args>(args)...);
2252 m_.set_front_idx(m_.front_idx - n);
2253 }
2254 else
2255 {
2256 resize_front_slow_path(sz, n, boost::forward<Args>(args)...);
2257 }
2258 }
2259 else {
2260 while (this->size() > sz)
2261 {
2262 this->pop_front();
2263 }
2264 }
2265 }
2266
2267 template <typename... Args>
2268 void resize_front_slow_path(size_type sz, size_type n, Args&&... args)
2269 {
2270 const size_type new_capacity = calculate_new_capacity(sz + back_free_capacity());
2271 pointer new_buffer = allocate(new_capacity);
2272 allocation_guard new_buffer_guard(new_buffer, new_capacity, get_allocator_ref());
2273
2274 const size_type new_old_elem_index = new_capacity - size();
2275 const size_type new_elem_index = new_old_elem_index - n;
2276
2277 detail::construction_guard<allocator_type> guard(new_buffer + new_elem_index, get_allocator_ref());
2278 guarded_construct_n(new_buffer + new_elem_index, n, guard, boost::forward<Args>(args)...);
2279
2280 buffer_move_or_copy(new_buffer + new_old_elem_index, guard);
2281
2282 guard.release();
2283 new_buffer_guard.release();
2284
2285 m_.buffer = new_buffer;
2286 m_.set_capacity(new_capacity);
2287 m_.set_back_idx(new_old_elem_index + m_.back_idx - m_.front_idx);
2288 m_.set_front_idx(new_elem_index);
2289 }
2290
2291 template <typename... Args>
2292 void resize_back_impl(size_type sz, Args&&... args)
2293 {
2294 if (sz > size())
2295 {
2296 const size_type n = sz - size();
2297
2298 if (sz <= back_capacity())
2299 {
2300 construct_n(m_.buffer + m_.back_idx, n, boost::forward<Args>(args)...);
2301 m_.set_back_idx(m_.back_idx + n);
2302 }
2303 else
2304 {
2305 resize_back_slow_path(sz, n, boost::forward<Args>(args)...);
2306 }
2307 }
2308 else
2309 {
2310 while (size() > sz)
2311 {
2312 pop_back();
2313 }
2314 }
2315 }
2316
2317 template <typename... Args>
2318 void resize_back_slow_path(size_type sz, size_type n, Args&&... args)
2319 {
2320 const size_type new_capacity = calculate_new_capacity(sz + front_free_capacity());
2321 pointer new_buffer = allocate(new_capacity);
2322 allocation_guard new_buffer_guard(new_buffer, new_capacity, get_allocator_ref());
2323
2324 detail::construction_guard<allocator_type> guard(new_buffer + m_.back_idx, get_allocator_ref());
2325 guarded_construct_n(new_buffer + m_.back_idx, n, guard, boost::forward<Args>(args)...);
2326
2327 buffer_move_or_copy(new_buffer + m_.front_idx);
2328
2329 guard.release();
2330 new_buffer_guard.release();
2331
2332 m_.buffer = new_buffer;
2333 m_.set_capacity(new_capacity);
2334 m_.set_back_idx(m_.back_idx + n);
2335 }
2336
2337 template <typename... Args>
2338 iterator emplace_slow_path(size_type new_elem_index, Args&&... args)
2339 {
2340 pointer position = begin() + new_elem_index;
2341
2342 // prefer moving front to access memory forward if there are less elems to move
2343 bool prefer_move_front = new_elem_index <= size()/2;
2344
2345 if (front_free_capacity() && (!back_free_capacity() || prefer_move_front))
2346 {
2347 BOOST_ASSERT(size() >= 1);
2348
2349 // move things closer to the front a bit
2350
2351 // avoid invalidating any reference in args later
2352 T tmp(boost::forward<Args>(args)...);
2353
2354 // construct at front - 1 from front (no guard)
2355 this->alloc_construct(begin() - 1, boost::move(*begin()));
2356
2357 // move front half left
2358 boost::move(begin() + 1, position, begin());
2359 --m_.front_idx;
2360
2361 // move assign new elem before pos
2362 --position;
2363 *position = boost::move(tmp);
2364
2365 return position;
2366 }
2367 else if (back_free_capacity()) {
2368 BOOST_ASSERT(size() >= 1);
2369
2370 // move things closer to the end a bit
2371
2372 // avoid invalidating any reference in args later
2373 T tmp(boost::forward<Args>(args)...);
2374
2375 // construct at back + 1 from back (no guard)
2376 this->alloc_construct(end(), boost::move(back()));
2377
2378 // move back half right
2379 boost::container::move_backward(position, end() - 1, end());
2380 ++m_.back_idx;
2381
2382 // move assign new elem to pos
2383 *position = boost::move(tmp);
2384
2385 return position;
2386 }
2387 else
2388 {
2389 return emplace_reallocating_slow_path(prefer_move_front, new_elem_index, boost::forward<Args>(args)...);
2390 }
2391 }
2392
2393 template <typename... Args>
2394 pointer emplace_reallocating_slow_path(bool make_front_free, size_type new_elem_index, Args&&... args)
2395 {
2396 // reallocate
2397 size_type new_capacity = calculate_new_capacity(capacity() + 1);
2398 pointer new_buffer = allocate(new_capacity);
2399
2400 // guard allocation
2401 allocation_guard new_buffer_guard(new_buffer, new_capacity, get_allocator_ref());
2402
2403 size_type new_front_index = (make_front_free)
2404 ? new_capacity - back_free_capacity() - size() - 1
2405 : m_.front_idx;
2406
2407 iterator new_begin = new_buffer + new_front_index;
2408 iterator new_position = new_begin + new_elem_index;
2409 iterator old_position = begin() + new_elem_index;
2410
2411 // construct new element (and guard it)
2412 this->alloc_construct(new_position, boost::forward<Args>(args)...);
2413
2414 detail::construction_guard<allocator_type> second_half_guard(new_position, get_allocator_ref());
2415 second_half_guard.extend();
2416
2417 // move front-pos (possibly guarded)
2418 detail::construction_guard<allocator_type> first_half_guard(new_begin, get_allocator_ref());
2419 opt_move_or_copy(begin(), old_position, new_begin, first_half_guard);
2420
2421 // move pos+1-end (possibly guarded)
2422 opt_move_or_copy(old_position, end(), new_position + 1, second_half_guard);
2423
2424 // cleanup
2425 destroy_elements(begin(), end());
2426 deallocate_buffer();
2427
2428 // release alloc and other guards
2429 second_half_guard.release();
2430 first_half_guard.release();
2431 new_buffer_guard.release();
2432
2433 // rebind members
2434 m_.set_capacity(new_capacity);
2435 m_.buffer = new_buffer;
2436 m_.set_back_idx(new_front_index + size() + 1);
2437 m_.set_front_idx(new_front_index);
2438
2439 return new_position;
2440 }
2441
2442 #else //!defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
2443
2444 #define BOOST_CONTAINER_DEVECTOR_SLOW_PATH(N) \
2445 BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
2446 void resize_front_impl(size_type sz BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\
2447 {\
2448 if (sz > size())\
2449 {\
2450 const size_type n = sz - size();\
2451 if (sz <= front_capacity()){\
2452 construct_n(m_.buffer + m_.front_idx - n, n BOOST_MOVE_I##N BOOST_MOVE_FWD##N);\
2453 m_.set_front_idx(m_.front_idx - n);\
2454 }\
2455 else\
2456 {\
2457 resize_front_slow_path(sz, n BOOST_MOVE_I##N BOOST_MOVE_FWD##N);\
2458 }\
2459 }\
2460 else {\
2461 while (this->size() > sz)\
2462 {\
2463 this->pop_front();\
2464 }\
2465 }\
2466 }\
2467 \
2468 BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
2469 void resize_front_slow_path(size_type sz, size_type n BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\
2470 {\
2471 const size_type new_capacity = calculate_new_capacity(sz + back_free_capacity());\
2472 pointer new_buffer = allocate(new_capacity);\
2473 allocation_guard new_buffer_guard(new_buffer, new_capacity, get_allocator_ref());\
2474 \
2475 const size_type new_old_elem_index = new_capacity - size();\
2476 const size_type new_elem_index = new_old_elem_index - n;\
2477 \
2478 detail::construction_guard<allocator_type> guard(new_buffer + new_elem_index, get_allocator_ref());\
2479 guarded_construct_n(new_buffer + new_elem_index, n, guard BOOST_MOVE_I##N BOOST_MOVE_FWD##N);\
2480 \
2481 buffer_move_or_copy(new_buffer + new_old_elem_index, guard);\
2482 \
2483 guard.release();\
2484 new_buffer_guard.release();\
2485 m_.buffer = new_buffer;\
2486 m_.set_capacity(new_capacity);\
2487 m_.set_back_idx(new_old_elem_index + m_.back_idx - m_.front_idx);\
2488 m_.set_front_idx(new_elem_index);\
2489 }\
2490 \
2491 BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
2492 void resize_back_impl(size_type sz BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\
2493 {\
2494 if (sz > size())\
2495 {\
2496 const size_type n = sz - size();\
2497 \
2498 if (sz <= back_capacity())\
2499 {\
2500 construct_n(m_.buffer + m_.back_idx, n BOOST_MOVE_I##N BOOST_MOVE_FWD##N);\
2501 m_.set_back_idx(m_.back_idx + n);\
2502 }\
2503 else\
2504 {\
2505 resize_back_slow_path(sz, n BOOST_MOVE_I##N BOOST_MOVE_FWD##N);\
2506 }\
2507 }\
2508 else\
2509 {\
2510 while (size() > sz)\
2511 {\
2512 pop_back();\
2513 }\
2514 }\
2515 }\
2516 \
2517 BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
2518 void resize_back_slow_path(size_type sz, size_type n BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\
2519 {\
2520 const size_type new_capacity = calculate_new_capacity(sz + front_free_capacity());\
2521 pointer new_buffer = allocate(new_capacity);\
2522 allocation_guard new_buffer_guard(new_buffer, new_capacity, get_allocator_ref());\
2523 \
2524 detail::construction_guard<allocator_type> guard(new_buffer + m_.back_idx, get_allocator_ref());\
2525 guarded_construct_n(new_buffer + m_.back_idx, n, guard BOOST_MOVE_I##N BOOST_MOVE_FWD##N);\
2526 \
2527 buffer_move_or_copy(new_buffer + m_.front_idx);\
2528 \
2529 guard.release();\
2530 new_buffer_guard.release();\
2531 \
2532 m_.buffer = new_buffer;\
2533 m_.set_capacity(new_capacity);\
2534 m_.set_back_idx(m_.back_idx + n);\
2535 }\
2536 \
2537 BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
2538 iterator emplace_slow_path(size_type new_elem_index BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\
2539 {\
2540 pointer position = begin() + new_elem_index;\
2541 \
2542 bool prefer_move_front = new_elem_index <= size()/2;\
2543 \
2544 if (front_free_capacity() && (!back_free_capacity() || prefer_move_front))\
2545 {\
2546 BOOST_ASSERT(size() >= 1);\
2547 typename dtl::aligned_storage<sizeof(T), dtl::alignment_of<T>::value>::type v;\
1e59de90 2548 T *vp = move_detail::force_ptr<T *>(v.data);\
20effc67
TL
2549 allocator_traits_type::construct(get_stored_allocator(), vp BOOST_MOVE_I##N BOOST_MOVE_FWD##N);\
2550 T &tmp = *vp;\
2551 dtl::value_destructor<allocator_type> on_exit(get_stored_allocator(), tmp); (void)on_exit;\
2552 \
2553 this->alloc_construct(begin() - 1, boost::move(*begin()));\
2554 boost::move(begin() + 1, position, begin());\
2555 --m_.front_idx;\
2556 --position;\
2557 *position = boost::move(tmp);\
2558 return position;\
2559 }\
2560 else if (back_free_capacity()) {\
2561 BOOST_ASSERT(size() >= 1);\
2562 typename dtl::aligned_storage<sizeof(T), dtl::alignment_of<T>::value>::type v;\
1e59de90 2563 T *vp = move_detail::force_ptr<T *>(v.data);\
20effc67
TL
2564 allocator_traits_type::construct(get_stored_allocator(), vp BOOST_MOVE_I##N BOOST_MOVE_FWD##N);\
2565 T &tmp = *vp;\
2566 dtl::value_destructor<allocator_type> on_exit(get_stored_allocator(), tmp); (void)on_exit;\
2567 this->alloc_construct(end(), boost::move(back()));\
2568 boost::container::move_backward(position, end() - 1, end());\
2569 ++m_.back_idx;\
2570 *position = boost::move(tmp);\
2571 return position;\
2572 }\
2573 else {\
2574 return emplace_reallocating_slow_path(prefer_move_front, new_elem_index BOOST_MOVE_I##N BOOST_MOVE_FWD##N);\
2575 }\
2576 }\
2577 \
2578 BOOST_MOVE_TMPL_LT##N BOOST_MOVE_CLASS##N BOOST_MOVE_GT##N \
2579 pointer emplace_reallocating_slow_path(bool make_front_free, size_type new_elem_index BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\
2580 {\
2581 size_type new_capacity = calculate_new_capacity(capacity() + 1);\
2582 pointer new_buffer = allocate(new_capacity);\
2583 allocation_guard new_buffer_guard(new_buffer, new_capacity, get_allocator_ref());\
2584 size_type new_front_index = (make_front_free)\
2585 ? new_capacity - back_free_capacity() - size() - 1\
2586 : m_.front_idx;\
2587 iterator new_begin = new_buffer + new_front_index;\
2588 iterator new_position = new_begin + new_elem_index;\
2589 iterator old_position = begin() + new_elem_index;\
2590 this->alloc_construct(new_position BOOST_MOVE_I##N BOOST_MOVE_FWD##N);\
2591 detail::construction_guard<allocator_type> second_half_guard(new_position, get_allocator_ref());\
2592 second_half_guard.extend();\
2593 detail::construction_guard<allocator_type> first_half_guard(new_begin, get_allocator_ref());\
2594 opt_move_or_copy(begin(), old_position, new_begin, first_half_guard);\
2595 opt_move_or_copy(old_position, end(), new_position + 1, second_half_guard);\
2596 destroy_elements(begin(), end());\
2597 deallocate_buffer();\
2598 second_half_guard.release();\
2599 first_half_guard.release();\
2600 new_buffer_guard.release();\
2601 m_.set_capacity(new_capacity);\
2602 m_.buffer = new_buffer;\
2603 m_.set_back_idx(new_front_index + size() + 1);\
2604 m_.set_front_idx(new_front_index);\
2605 return new_position;\
2606 }\
2607 //
2608 BOOST_MOVE_ITERATE_0TO9(BOOST_CONTAINER_DEVECTOR_SLOW_PATH)
2609 #undef BOOST_CONTAINER_DEVECTOR_SLOW_PATH
2610
2611 #endif //!defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
2612/*
2613 void unsafe_uninitialized_grow_front(size_type n)
2614 {
2615 BOOST_ASSERT(n >= size());
2616
2617 size_type need = n - size();
2618
2619 if (need > front_free_capacity())
2620 {
2621 reallocate_at(n + back_free_capacity(), need);
2622 }
2623
2624 m_.set_front_idx(m_.front_idx - need);
2625 }
2626
2627 void unsafe_uninitialized_shrink_front(size_type n)
2628 {
2629 BOOST_ASSERT(n <= size());
2630
2631 size_type doesnt_need = size() - n;
2632 m_.set_front_idx(m_.front_idx + doesnt_need);
2633 }
2634
2635 void unsafe_uninitialized_grow_back(size_type n)
2636 {
2637 BOOST_ASSERT(n >= size());
2638
2639 size_type need = n - size();
2640
2641 if (need > back_free_capacity())
2642 {
2643 reallocate_at(n + front_free_capacity(), front_free_capacity());
2644 }
2645
2646 m_.set_back_idx(m_.back_idx + need);
2647 }
2648
2649 void unsafe_uninitialized_shrink_back(size_type n)
2650 {
2651 BOOST_ASSERT(n <= size());
2652
2653 size_type doesnt_need = size() - n;
2654 m_.set_back_idx(m_.back_idx - doesnt_need);
2655 }
2656*/
2657
2658 void reallocate_at(size_type new_capacity, size_type buffer_offset)
2659 {
2660 pointer new_buffer = allocate(new_capacity);
2661 allocation_guard new_buffer_guard(new_buffer, new_capacity, get_allocator_ref());
2662
2663 buffer_move_or_copy(new_buffer + buffer_offset);
2664
2665 new_buffer_guard.release();
2666
2667 m_.buffer = new_buffer;
2668 //Safe cast, allocate() will handle stored_size_type overflow
2669 m_.set_capacity(new_capacity);
1e59de90 2670 m_.set_back_idx(size_type(m_.back_idx - m_.front_idx) + buffer_offset);
20effc67
TL
2671 m_.set_front_idx(buffer_offset);
2672
2673 BOOST_ASSERT(invariants_ok());
2674 }
2675
2676 template <typename ForwardIterator>
2677 iterator insert_range(const_iterator position, ForwardIterator first, ForwardIterator last)
2678 {
1e59de90 2679 size_type n = boost::container::iterator_udistance(first, last);
20effc67
TL
2680
2681 if (position == end() && back_free_capacity() >= n) {// fast path
2682 iterator r(this->end());
2683 boost::container::uninitialized_copy_alloc(get_allocator_ref(), first, last, this->raw_end());
2684 m_.set_back_idx(m_.back_idx + n);
2685 return r;
2686 }
2687 else if (position == begin() && front_free_capacity() >= n) { // secondary fast path
2688 boost::container::uninitialized_copy_alloc(get_allocator_ref(), first, last, this->raw_begin() - n);
2689 m_.set_front_idx(m_.front_idx - n);
2690 return begin();
2691 }
2692 else {
2693 return insert_range_slow_path(position, first, last);
2694 }
2695 }
2696
2697 template <typename ForwardIterator>
2698 iterator insert_range_slow_path(const_iterator position, ForwardIterator first, ForwardIterator last)
2699 {
1e59de90
TL
2700 size_type n = boost::container::iterator_udistance(first, last);
2701 size_type index = size_type(position - begin());
20effc67
TL
2702
2703 if (front_free_capacity() + back_free_capacity() >= n) {
2704 // if we move enough, it can be done without reallocation
2705
2706 iterator middle = begin() + index;
2707 n -= insert_range_slow_path_near_front(middle, first, n);
2708
2709 if (n) {
2710 insert_range_slow_path_near_back(middle, first, n);
2711 }
2712
2713 BOOST_ASSERT(first == last);
2714 return begin() + index;
2715 }
2716 else {
2717 const bool prefer_move_front = 2 * index <= size();
2718 return insert_range_reallocating_slow_path(prefer_move_front, index, first, n);
2719 }
2720 }
2721
2722 template <typename Iterator>
2723 size_type insert_range_slow_path_near_front(iterator position, Iterator& first, size_type n)
2724 {
2725 size_type n_front = dtl::min_value(front_free_capacity(), n);
2726 iterator new_begin = begin() - n_front;
2727 iterator ctr_pos = new_begin;
2728 detail::construction_guard<allocator_type> ctr_guard(ctr_pos, get_allocator_ref());
2729
2730 while (ctr_pos != begin()) {
2731 this->alloc_construct(ctr_pos++, *(first++));
2732 ctr_guard.extend();
2733 }
2734
2735 boost::movelib::rotate_gcd(new_begin, ctr_pos, position);
2736 m_.set_front_idx(m_.front_idx - n_front);
2737
2738 ctr_guard.release();
2739
2740 BOOST_ASSERT(invariants_ok());
2741
2742 return n_front;
2743 }
2744
2745 template <typename Iterator>
2746 size_type insert_range_slow_path_near_back(iterator position, Iterator& first, size_type n)
2747 {
2748 const size_type n_back = dtl::min_value(back_free_capacity(), n);
2749 iterator ctr_pos = end();
2750
2751 detail::construction_guard<allocator_type> ctr_guard(ctr_pos, get_allocator_ref());
2752
2753 for (size_type i = 0; i < n_back; ++i) {
2754 this->alloc_construct(ctr_pos++, *first++);
2755 ctr_guard.extend();
2756 }
2757
2758 boost::movelib::rotate_gcd(position, end(), ctr_pos);
2759 m_.set_back_idx(m_.back_idx + n_back);
2760
2761 ctr_guard.release();
2762
2763 BOOST_ASSERT(invariants_ok());
2764
2765 return n_back;
2766 }
2767
2768 template <typename Iterator>
2769 iterator insert_range_reallocating_slow_path
2770 (bool make_front_free, size_type new_elem_index, Iterator elems, size_type n)
2771 {
2772 // reallocate
2773 const size_type new_capacity = calculate_new_capacity(capacity() + n);
2774 pointer new_buffer = allocate(new_capacity);
2775
2776 // guard allocation
2777 allocation_guard new_buffer_guard(new_buffer, new_capacity, get_allocator_ref());
2778
2779 const size_type new_front_index = (make_front_free)
2780 ? new_capacity - back_free_capacity() - size() - n
2781 : m_.front_idx;
2782
2783 const iterator new_begin = new_buffer + new_front_index;
2784 const iterator new_position = new_begin + new_elem_index;
2785 const iterator old_position = begin() + new_elem_index;
2786
2787 // construct new element (and guard it)
2788 iterator second_half_position = new_position;
2789 detail::construction_guard<allocator_type> second_half_guard(second_half_position, get_allocator_ref());
2790
2791 for (size_type i = 0; i < n; ++i) {
2792 this->alloc_construct(second_half_position++, *(elems++));
2793 second_half_guard.extend();
2794 }
2795
2796 // move front-pos (possibly guarded)
2797 detail::construction_guard<allocator_type> first_half_guard(new_begin, get_allocator_ref());
2798 opt_move_or_copy(begin(), old_position, new_begin, first_half_guard);
2799
2800 // move pos+1-end (possibly guarded)
2801 opt_move_or_copy(old_position, end(), second_half_position, second_half_guard);
2802
2803 // cleanup
2804 destroy_elements(begin(), end());
2805 deallocate_buffer();
2806
2807 // release alloc and other guards
2808 second_half_guard.release();
2809 first_half_guard.release();
2810 new_buffer_guard.release();
2811
2812 // rebind members
2813 m_.set_capacity(new_capacity);
2814 m_.buffer = new_buffer;
2815 m_.set_back_idx(new_front_index + size() + n);
2816 m_.set_front_idx(new_front_index);
2817
2818 return new_position;
2819 }
2820
2821 template <typename Iterator>
2822 void construct_from_range(Iterator begin, Iterator end)
2823 {
2824 allocation_guard buffer_guard(m_.buffer, m_.capacity, get_allocator_ref());
2825 opt_copy(begin, end, m_.buffer);
2826
2827 buffer_guard.release();
2828 }
2829
2830 template <typename ForwardIterator>
2831 void allocate_and_copy_range(ForwardIterator first, ForwardIterator last)
2832 {
1e59de90 2833 size_type n = boost::container::iterator_udistance(first, last);
20effc67
TL
2834
2835 pointer new_buffer = n ? allocate(n) : pointer();
2836 allocation_guard new_buffer_guard(new_buffer, n, get_allocator_ref());
2837
2838 opt_copy(first, last, new_buffer);
2839
2840 destroy_elements(begin(), end());
2841 deallocate_buffer();
2842
2843 m_.set_capacity(n);
2844 m_.buffer = new_buffer;
2845 m_.front_idx = 0;
2846 m_.set_back_idx(n);
2847
2848 new_buffer_guard.release();
2849 }
2850
2851 static void swap_big_big(devector& a, devector& b) BOOST_NOEXCEPT
2852 {
2853 boost::adl_move_swap(a.m_.capacity, b.m_.capacity);
2854 boost::adl_move_swap(a.m_.buffer, b.m_.buffer);
2855 }
2856
2857 template <typename ForwardIterator>
2858 void overwrite_buffer_impl(ForwardIterator first, ForwardIterator last, dtl::true_)
2859 {
1e59de90 2860 const size_type n = boost::container::iterator_udistance(first, last);
20effc67
TL
2861
2862 BOOST_ASSERT(capacity() >= n);
2863 boost::container::uninitialized_copy_alloc_n
2864 ( get_allocator_ref(), boost::movelib::iterator_to_raw_pointer(first)
2865 , n, boost::movelib::iterator_to_raw_pointer(m_.buffer));
2866 m_.front_idx = 0;
2867 m_.set_back_idx(n);
2868 }
2869
2870 template <typename InputIterator>
2871 InputIterator overwrite_buffer_impl(InputIterator first, InputIterator last, dtl::false_)
2872 {
2873 pointer pos = m_.buffer;
2874 detail::construction_guard<allocator_type> front_guard(pos, get_allocator_ref());
2875
2876 while (first != last && pos != begin()) {
2877 this->alloc_construct(pos++, *first++);
2878 front_guard.extend();
2879 }
2880
2881 while (first != last && pos != end()) {
2882 *pos++ = *first++;
2883 }
2884
2885 detail::construction_guard<allocator_type> back_guard(pos, get_allocator_ref());
2886
2887 iterator capacity_end = m_.buffer + capacity();
2888 while (first != last && pos != capacity_end) {
2889 this->alloc_construct(pos++, *first++);
2890 back_guard.extend();
2891 }
2892
2893 pointer destroy_after = dtl::min_value(dtl::max_value(begin(), pos), end());
2894 destroy_elements(destroy_after, end());
2895
2896 front_guard.release();
2897 back_guard.release();
2898
2899 m_.front_idx = 0;
1e59de90 2900 m_.set_back_idx(size_type(pos - begin()));
20effc67
TL
2901 return first;
2902 }
2903
2904 template <typename ForwardIterator>
2905 BOOST_CONTAINER_FORCEINLINE void overwrite_buffer(ForwardIterator first, ForwardIterator last)
2906 {
2907 this->overwrite_buffer_impl(first, last,
2908 dtl::bool_<dtl::is_trivially_destructible<T>::value>());
2909 }
2910
2911 bool invariants_ok()
2912 {
2913 return (!m_.capacity || m_.buffer)
2914 && m_.front_idx <= m_.back_idx
2915 && m_.back_idx <= m_.capacity;
2916 }
2917
2918 struct impl : allocator_type
2919 {
1e59de90
TL
2920 private:
2921 impl(const impl &i);
2922
2923 public:
2924 allocator_type &get_al()
2925 { return *this; }
2926
2927 static pointer do_allocate(allocator_type &a, size_type cap)
2928 {
2929 if (cap) {
2930 //First detect overflow on smaller stored_size_types
2931 if (cap > stored_size_type(-1)){
2932 boost::container::throw_length_error("get_next_capacity, allocator's max size reached");
2933 }
2934 return allocator_traits_type::allocate(a, cap);
2935 }
2936 else {
2937 return pointer();
2938 }
2939 }
2940
20effc67
TL
2941 impl()
2942 : allocator_type(), buffer(), front_idx(), back_idx(), capacity()
2943 #ifdef BOOST_CONTAINER_DEVECTOR_ALLOC_STATS
1e59de90 2944 , capacity_alloc_count(0)
20effc67
TL
2945 #endif
2946 {}
2947
2948 explicit impl(const allocator_type &a)
2949 : allocator_type(a), buffer(), front_idx(), back_idx(), capacity()
2950 #ifdef BOOST_CONTAINER_DEVECTOR_ALLOC_STATS
1e59de90
TL
2951 , capacity_alloc_count(0)
2952 #endif
2953 {}
2954
2955 impl(const allocator_type &a, size_type f, size_type b, size_type c)
2956 : allocator_type(a), buffer(do_allocate(get_al(), c))
2957 //static cast sizes, as the allocation function will take care of overflows
2958 , front_idx(static_cast<stored_size_type>(f))
2959 , back_idx(static_cast<stored_size_type>(b))
2960 , capacity(static_cast<stored_size_type>(c))
2961 #ifdef BOOST_CONTAINER_DEVECTOR_ALLOC_STATS
2962 , capacity_alloc_count(size_type(buffer != pointer()))
20effc67
TL
2963 #endif
2964 {}
2965
2966 impl(const allocator_type &a, pointer p, size_type f, size_type b, size_type c)
2967 : allocator_type(a), buffer(p)
2968 //static cast sizes, as the allocation function will take care of overflows
2969 , front_idx(static_cast<stored_size_type>(f))
2970 , back_idx(static_cast<stored_size_type>(b))
2971 , capacity(static_cast<stored_size_type>(c))
2972 #ifdef BOOST_CONTAINER_DEVECTOR_ALLOC_STATS
1e59de90 2973 , capacity_alloc_count(0)
20effc67
TL
2974 #endif
2975 {}
2976
2977 impl(BOOST_RV_REF(allocator_type) a, pointer p, size_type f, size_type b, size_type c)
2978 : allocator_type(boost::move(a)), buffer(p)
2979 //static cast sizes, as the allocation function will take care of overflows
2980 , front_idx(static_cast<stored_size_type>(f))
2981 , back_idx(static_cast<stored_size_type>(b))
2982 , capacity(static_cast<stored_size_type>(c))
2983 #ifdef BOOST_CONTAINER_DEVECTOR_ALLOC_STATS
1e59de90 2984 , capacity_alloc_count(0)
20effc67
TL
2985 #endif
2986 {}
2987
2988 void set_back_idx(size_type bi)
2989 { back_idx = static_cast<stored_size_type>(bi);}
2990
2991 void set_front_idx(size_type fi)
2992 { front_idx = static_cast<stored_size_type>(fi);}
2993
2994 void set_capacity(size_type c)
2995 { capacity = static_cast<stored_size_type>(c);}
2996
2997 pointer buffer;
2998 stored_size_type front_idx;
2999 stored_size_type back_idx;
3000 stored_size_type capacity;
3001 #ifdef BOOST_CONTAINER_DEVECTOR_ALLOC_STATS
3002 size_type capacity_alloc_count;
3003 #endif
3004 } m_;
3005
3006
3007 #ifdef BOOST_CONTAINER_DEVECTOR_ALLOC_STATS
3008 public:
3009 void reset_alloc_stats()
3010 {
3011 m_.capacity_alloc_count = 0;
3012 }
3013
3014 size_type get_alloc_count() const
3015 {
3016 return m_.capacity_alloc_count;
3017 }
3018
3019 #endif // ifdef BOOST_CONTAINER_DEVECTOR_ALLOC_STATS
3020
3021 #endif // ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
3022};
3023
3024}} // namespace boost::container
3025
3026#include <boost/container/detail/config_end.hpp>
3027
3028#endif // BOOST_CONTAINER_DEVECTOR_HPP