BDE 4.39.x Production Release
Loading...
Searching...
No Matches
bslstl_deque.h
Go to the documentation of this file.
1/// @file bslstl_deque.h
2///
3/// The content of this file has been pre-processed for Doxygen.
4///
5
6
7// bslstl_deque.h -*-C++-*-
8#ifndef INCLUDED_BSLSTL_DEQUE
9#define INCLUDED_BSLSTL_DEQUE
10
11#include <bsls_ident.h>
12BSLS_IDENT("$Id: $")
13
14/// @defgroup bslstl_deque bslstl_deque
15/// @brief Provide an STL-compliant deque class.
16/// @addtogroup bsl
17/// @{
18/// @addtogroup bslstl
19/// @{
20/// @addtogroup bslstl_deque
21/// @{
22///
23/// <h1> Outline </h1>
24/// * <a href="#bslstl_deque-purpose"> Purpose</a>
25/// * <a href="#bslstl_deque-classes"> Classes </a>
26/// * <a href="#bslstl_deque-canonical-header"> Canonical Header </a>
27/// * <a href="#bslstl_deque-description"> Description </a>
28/// * <a href="#bslstl_deque-requirements-on-value_type"> Requirements on VALUE_TYPE </a>
29/// * <a href="#bslstl_deque-glossary"> Glossary </a>
30/// * <a href="#bslstl_deque-memory-allocation"> Memory Allocation </a>
31/// * <a href="#bslstl_deque-bslma-style-allocators"> bslma-Style Allocators </a>
32/// * <a href="#bslstl_deque-operations"> Operations </a>
33/// * <a href="#bslstl_deque-exceptional-behavior"> Exceptional Behavior </a>
34/// * <a href="#bslstl_deque-usage"> Usage </a>
35/// * <a href="#bslstl_deque-example-1-using-a-deque-to-implement-a-laundry-queue"> Example 1: Using a deque to Implement a Laundry Queue </a>
36///
37/// # Purpose {#bslstl_deque-purpose}
38/// Provide an STL-compliant deque class.
39///
40/// # Classes {#bslstl_deque-classes}
41///
42/// - bsl::deque: STL-compliant deque template
43///
44/// # Canonical Header {#bslstl_deque-canonical-header}
45/// bsl_deque.h
46///
47/// @see bslstl_vector
48///
49/// # Description {#bslstl_deque-description}
50/// This component defines a single class template, `bsl::deque`,
51/// implementing the standard sequential container, `std::deque`, holding a
52/// dynamic sequence of values of a template parameter type.
53///
54/// An instantiation of `deque` is an allocator-aware, value-semantic type
55/// whose salient attributes are its size (number of contained elements) and the
56/// (ordered) sequence of values the deque contains. If `deque` is instantiated
57/// with a value type that is not value-semantic, then the deque will not retain
58/// all of its value-semantic qualities. In particular, if a value type cannot
59/// be tested for equality, then a `deque` containing elements of that type
60/// cannot be tested for equality. It is even possible to instantiate `deque`
61/// with a value type that does not have a copy-constructor, in which case the
62/// `deque` will not be copyable.
63///
64/// A deque meets the requirements of a sequential container with random access
65/// iterators in section [deque] of the C++ standard. The `deque` implemented
66/// here adheres to the C++11 standard when compiled with a C++11 compiler, and
67/// makes the best approximation when compiled with a C++03 compiler. In
68/// particular, for C++03 we emulate move semantics, but limit forwarding (in
69/// `emplace`) to `const` lvalues, and make no effort to emulate `noexcept` or
70/// initializer-lists.
71///
72/// ## Requirements on VALUE_TYPE {#bslstl_deque-requirements-on-value_type}
73///
74///
75/// A `deque` is a fully Value-Semantic Type (see @ref bsldoc_glossary ) only if
76/// the supplied `VALUE_TYPE` template parameter is fully value-semantic. It is
77/// possible to instantiate a `deque` with a `VALUE_TYPE` parameter that does
78/// not have a full set of value-semantic operations, but then some methods of
79/// the container may not be instantiable. The following terminology, adopted
80/// from the C++11 standard, is used in the function documentation of `deque`
81/// to describe a function's requirements for the `VALUE_TYPE` template
82/// parameter. These terms are also defined in section [17.6.3.1] of the C++11
83/// standard. Note that, in the context of a `deque` instantiation, the
84/// requirements apply specifically to the deque's entry type, `value_type`,
85/// which is an alias for `VALUE_TYPE`.
86///
87/// ## Glossary {#bslstl_deque-glossary}
88///
89///
90/// @code
91/// Legend
92/// ------
93/// 'X' - denotes an allocator-aware container type (e.g., 'deque')
94/// 'T' - 'value_type' associated with 'X'
95/// 'A' - type of the allocator used by 'X'
96/// 'm' - lvalue of type 'A' (allocator)
97/// 'p', - address ('T *') of uninitialized storage for a 'T' within an 'X'
98/// 'rv' - rvalue of type (non-'const') 'T'
99/// 'v' - rvalue or lvalue of type (possibly 'const') 'T'
100/// 'args' - 0 or more arguments
101/// @endcode
102/// The following terms are used to more precisely specify the requirements on
103/// template parameter types in function-level documentation.
104///
105/// *default-insertable*: `T` has a default constructor. More precisely, `T`
106/// is `default-insertable` into `X` means that the following expression is
107/// well-formed:
108/// `allocator_traits<A>::construct(m, p)`
109///
110/// *move-insertable*: `T` provides a constructor that takes an rvalue of type
111/// (non-`const`) `T`. More precisely, `T` is `move-insertable` into `X`
112/// means that the following expression is well-formed:
113/// `allocator_traits<A>::construct(m, p, rv)`
114///
115/// *copy-insertable*: `T` provides a constructor that takes an lvalue or
116/// rvalue of type (possibly `const`) `T`. More precisely, `T` is
117/// `copy-insertable` into `X` means that the following expression is
118/// well-formed:
119/// `allocator_traits<A>::construct(m, p, v)`
120///
121/// *move-assignable*: `T` provides an assignment operator that takes an rvalue
122/// of type (non-`const`) `T`.
123///
124/// *copy-assignable*: `T` provides an assignment operator that takes an lvalue
125/// or rvalue of type (possibly `const`) `T`.
126///
127/// *emplace-constructible*: `T` is `emplace-constructible` into `X` from
128/// `args` means that the following expression is well-formed:
129/// `allocator_traits<A>::construct(m, p, args)`
130///
131/// *erasable*: `T` provides a destructor. More precisely, `T` is `erasable`
132/// from `X` means that the following expression is well-formed:
133/// `allocator_traits<A>::destroy(m, p)`
134///
135/// *equality-comparable*: The type provides an equality-comparison operator
136/// that defines an equivalence relationship and is both reflexive and
137/// transitive.
138///
139/// ## Memory Allocation {#bslstl_deque-memory-allocation}
140///
141///
142/// The type supplied as a deque's `ALLOCATOR` template parameter determines
143/// how that deque will allocate memory. The `deque` template supports
144/// allocators meeting the requirements of the C++03 standard, in addition it
145/// supports scoped-allocators derived from the `bslma::Allocator` memory
146/// allocation protocol. Clients intending to use `bslma` style allocators
147/// should use the template's default `ALLOCATOR` type: The default type for the
148/// `ALLOCATOR` template parameter, `bsl::allocator`, provides a C++11
149/// standard-compatible adapter for a `bslma::Allocator` object.
150///
151/// ### bslma-Style Allocators {#bslstl_deque-bslma-style-allocators}
152///
153///
154/// If the (template parameter) type `ALLOCATOR` of a `deque` instantiation' is
155/// `bsl::allocator`, then objects of that deque type will conform to the
156/// standard behavior of a `bslma`-allocator-enabled type. Such a deque
157/// accepts an optional `bslma::Allocator` argument at construction. If the
158/// address of a `bslma::Allocator` object is explicitly supplied at
159/// construction, it is used to supply memory for the deque throughout its
160/// lifetime; otherwise, the deque will use the default allocator installed at
161/// the time of the deque's construction (see @ref bslma_default ). In addition to
162/// directly allocating memory from the indicated `bslma::Allocator`, a deque
163/// supplies that allocator's address to the constructors of contained objects
164/// of the (template parameter) `VALUE_TYPE` if it defines the
165/// `bslma::UsesBslmaAllocator` trait.
166///
167/// ## Operations {#bslstl_deque-operations}
168///
169///
170/// This section describes the run-time complexity of operations on instances
171/// of `deque`:
172/// @code
173/// Legend
174/// ------
175/// 'V' - (template parameter) 'VALUE_TYPE' of the deque
176/// 'a', 'b' - two distinct objects of type 'deque<V>'
177/// 'rv' - modifiable rvalue of type 'deque<V>'
178/// 'n', 'm' - number of elements in 'a' and 'b', respectively
179/// 'i' - valid index into the deque
180/// 'k' - non-negative integer
181/// 'al - an STL-style memory allocator
182/// 'i1', 'i2' - two iterators defining a sequence of 'V' objects
183/// 'rg' - range of objects convertible to 'V'
184/// 'il' - object of type 'std::initializer_list<V>'
185/// 'lil' - length of 'il'
186/// 'vt' - object of type 'VALUE_TYPE'
187/// 'rvt' - modifiable rvalue of type 'VALUE_TYPE'
188/// 'p1', 'p2' - two 'const_iterator's belonging to 'a'
189/// 'distance(i1, i2)' - number of elements in the range '[i1 .. i2)'
190/// 'minHalf(p1)' - 'min(distance(a.begin(), p1), distance(p1, a.end()))'
191/// 'args' - 0 or more arguments
192///
193/// |-----------------------------------------+-------------------------------|
194/// | Operation | Complexity |
195/// |=========================================+===============================|
196/// | deque<V> a (default construction) | O[1] |
197/// | deque<V> a(al) | |
198/// |-----------------------------------------+-------------------------------|
199/// | deque<V> a(b) (copy construction) | O[n] |
200/// | deque<V> a(b, al) | |
201/// |-----------------------------------------+-------------------------------|
202/// | deque<V> a(rv) (move construction) | O[1] if 'a' and 'rv' use the |
203/// | deque<V> a(rv, al) | same allocator; O[n] otherwise|
204/// |-----------------------------------------+-------------------------------|
205/// | deque<V> a(k) | O[k] |
206/// | deque<V> a(k, al) | |
207/// |-----------------------------------------+-------------------------------|
208/// | deque<V> a(k, vt) | O[k] |
209/// | deque<V> a(k, vt, al) | |
210/// |-----------------------------------------+-------------------------------|
211/// | deque<V> a(i1, i2) | O[distance(i1, i2)] |
212/// | deque<V> a(i1, i2, al) | |
213/// |-----------------------------------------+-------------------------------|
214/// | deque<V> a(from_range, rg) | O[ranges::distance(rg)] |
215/// | deque<V> a(from_range, rg, al) | |
216/// |-----------------------------------------+-------------------------------|
217/// | deque<V> a(il) | O[lil] |
218/// | deque<V> a(il, al) | |
219/// |-----------------------------------------+-------------------------------|
220/// | a.~deque<V>() (destruction) | O[n] |
221/// |-----------------------------------------+-------------------------------|
222/// | a.assign(k, vt) | O[k] |
223/// |-----------------------------------------+-------------------------------|
224/// | a.assign(i1, i2) | O[distance(i1, i2)] |
225/// |-----------------------------------------+-------------------------------|
226/// | a.assign_range(rg) | O[ranges::distance(rg)] |
227/// |-----------------------------------------+-------------------------------|
228/// | a.assign(il) | O[lil] |
229/// |-----------------------------------------+-------------------------------|
230/// | get_allocator() | O[1] |
231/// |-----------------------------------------+-------------------------------|
232/// | a.begin(), a.end() | O[1] |
233/// | a.cbegin(), a.cend() | |
234/// | a.rbegin(), a.rend() | |
235/// | a.crbegin(), a.crend() | |
236/// |-----------------------------------------+-------------------------------|
237/// | a.size() | O[1] |
238/// |-----------------------------------------+-------------------------------|
239/// | a.max_size() | O[1] |
240/// |-----------------------------------------+-------------------------------|
241/// | a.resize(k) | O[k] |
242/// | a.resize(k, vt) | |
243/// |-----------------------------------------+-------------------------------|
244/// | a.empty() | O[1] |
245/// |-----------------------------------------+-------------------------------|
246/// | a.reserve(k) | O[k] |
247/// |-----------------------------------------+-------------------------------|
248/// | a.shrink_to_fit() | O[n] |
249/// |-----------------------------------------+-------------------------------|
250/// | a[i] | O[1] |
251/// |-----------------------------------------+-------------------------------|
252/// | a.at(i) | O[1] |
253/// |-----------------------------------------+-------------------------------|
254/// | a.front() | O[1] |
255/// |-----------------------------------------+-------------------------------|
256/// | a.back() | O[1] |
257/// |-----------------------------------------+-------------------------------|
258/// | a.push_back(vt) | O[1] |
259/// | a.push_front(vt) | |
260/// |-----------------------------------------+-------------------------------|
261/// | a.push_back(rvt) | O[1] |
262/// | a.push_front(rvt) | |
263/// |-----------------------------------------+-------------------------------|
264/// | a.pop_back() | O[1] |
265/// | a.pop_front() | |
266/// |-----------------------------------------+-------------------------------|
267/// | a.emplace_back(args) | O[1] |
268/// | a.emplace_front(args) | |
269/// |-----------------------------------------+-------------------------------|
270/// | a.prepend_range(rg) | O[ranges::distance(rg)] |
271/// | a.append_range(rg) | |
272/// |-----------------------------------------+-------------------------------|
273/// | a.emplace(p1, args) | O[1 + minHalf(p1)] |
274/// |-----------------------------------------+-------------------------------|
275/// | a.insert(p1, vt) | O[1 + minHalf(p1)] |
276/// |-----------------------------------------+-------------------------------|
277/// | a.insert(p1, rvt) | O[1 + minHalf(p1)] |
278/// |-----------------------------------------+-------------------------------|
279/// | a.insert(p1, k, vt) | O[k + minHalf(p1)] |
280/// |-----------------------------------------+-------------------------------|
281/// | a.insert(p1, i1, i2) | O[distance(i1, i2) |
282/// | | + minHalf(p1)] |
283/// |-----------------------------------------+-------------------------------|
284/// | a.insert_range(p1, rg) | O[ranges::distance(rg) |
285/// | | + minHalf(p1)] |
286/// |-----------------------------------------+-------------------------------|
287/// | a.insert(p1, il) | O[lil + minHalf(p1)] |
288/// |-----------------------------------------+-------------------------------|
289/// | a.erase(p1) | O[1 + minHalf(p1)] |
290/// |-----------------------------------------+-------------------------------|
291/// | a.erase(p1, p2) | O[distance(p1, p2) |
292/// | | + min(distance(a.begin, p1), |
293/// | | distance(p2, a.end())] |
294/// |-----------------------------------------+-------------------------------|
295/// | a.swap(b), swap(a, b) | O[1] if 'a' and 'b' use the |
296/// | | same allocator; O[n + m] |
297/// | | otherwise |
298/// |-----------------------------------------+-------------------------------|
299/// | a.clear() | O[n] |
300/// |-----------------------------------------+-------------------------------|
301/// | a = b; (copy assignment) | O[n] |
302/// |-----------------------------------------+-------------------------------|
303/// | a = rv; (move assignment) | O[1] if 'a' and 'rv' use the |
304/// | | same allocator; O[n] otherwise|
305/// |-----------------------------------------+-------------------------------|
306/// | a = il; | O[lil] |
307/// |-----------------------------------------+-------------------------------|
308/// | a == b, a != b | O[n] |
309/// |-----------------------------------------+-------------------------------|
310/// | a < b, a <= b, a > b, a >= b | O[n] |
311/// |-----------------------------------------+-------------------------------|
312/// @endcode
313///
314/// ## Exceptional Behavior {#bslstl_deque-exceptional-behavior}
315///
316///
317/// Since this component is below the BSL STL, we centralize all the exceptional
318/// behavior into a `bslstl::StdExceptUtil` class, which has a dual purpose:
319///
320/// * Remove the dependency of this header on the `<exception>` header, so that
321/// this implementation can offer an exception handler with the native
322/// exceptions, and so that all the C-strings may be defined in a single
323/// library (`bsl`) and not in all the translation units including this
324/// header.
325/// * Allow installation of exception handlers at a higher level to throw BSL
326/// STL exceptions (which differ from the native exceptions) and thus
327/// establish a full standard compliance for this component when used as
328/// `bsl::deque` in the BSL STL.
329///
330/// ## Usage {#bslstl_deque-usage}
331///
332///
333/// In this section we show intended usage of this component.
334///
335/// ### Example 1: Using a deque to Implement a Laundry Queue {#bslstl_deque-example-1-using-a-deque-to-implement-a-laundry-queue}
336///
337///
338/// Suppose we want to define a class to maintain a process queue of names of
339/// customers who are dropping off their laundry at a drop-off laundry service.
340/// We can accomplish this by defining a new class characterizing a
341/// laundry-process queue that uses `bsl::deque` in its implementation.
342///
343/// The process queue provides two methods, `push` and `expeditedPush`, for
344/// inserting names of customers onto the queue. When calling the `push`
345/// method, the customer's name will be inserted at the back of the queue -- his
346/// laundry will be done after the laundry of customers previously on the queue.
347/// The `expeditedPush` method is reserved for customers who have bribed the
348/// merchant for expedited service. When calling the `expeditedPush` method,
349/// the customer's name will be inserted onto the front of the queue -- his
350/// laundry will be done before customers previously on the queue.
351///
352/// When the workers are ready to do some laundry, they call the `next` method
353/// of the queue, which returns the name of the customer whose laundry is to be
354/// done next. For brevity of the usage example, we do not show how customers
355/// are track while or after their laundry is being done.
356///
357/// In addition, the laundry queue also provides the `find` method, which
358/// returns a `bool` to indicate whether a given customer is still in the queue.
359///
360/// First, we declare a class `LaundryQueue` based on a deque, to store names of
361/// customers at a drop-off laundry:
362/// @code
363/// // This `class` keeps track of customers enqueued to have their laundry
364/// // done by a laundromat.
365/// class LaundryQueue {
366///
367/// // DATA
368/// bsl::deque<bsl::string> d_queue;
369///
370/// public:
371/// // CREATORS
372///
373/// /// Create a `LaundryQueue` object using the specified
374/// /// `basicAllocator`. If `basicAllocator` is not provided, use the
375/// /// default allocator.
376/// LaundryQueue(bslma::Allocator *basicAllocator = 0);
377///
378/// // MANIPULATORS
379///
380/// /// Add the specified `customerName` to the back of the laundry
381/// /// queue.
382/// void push(const bsl::string& customerName);
383///
384/// /// Add the specified `customerName` to the laundry queue at the
385/// /// front.
386/// void expeditedPush(const bsl::string& customerName);
387///
388/// /// Return the name from the front of the queue, removing it from
389/// /// the queue. If the queue is empty, return `(* empty *)` which is
390/// /// not a valid name for a customer.
391/// bsl::string next();
392///
393/// // ACCESSORS
394///
395/// /// Return `true` if `customerName` is in the queue, and `false`
396/// /// otherwise.
397/// bool find(const bsl::string& customerName);
398/// };
399/// @endcode
400/// Then, we define the implementation of the methods of `LaundryQueue`
401/// @code
402/// // CREATORS
403/// LaundryQueue::LaundryQueue(bslma::Allocator *basicAllocator)
404/// : d_queue(basicAllocator)
405/// {
406/// // Note that the allocator is propagated to the underlying `deque`,
407/// // which will use the default allocator is `0 == basicAllocator`.
408/// }
409///
410/// // MANIPULATORS
411/// void LaundryQueue::push(const bsl::string& customerName)
412/// {
413/// d_queue.push_back(customerName); // note constant time
414/// }
415///
416/// void LaundryQueue::expeditedPush(const bsl::string& customerName)
417/// {
418/// d_queue.push_front(customerName); // note constant time
419/// }
420///
421/// bsl::string LaundryQueue::next()
422/// {
423/// if (d_queue.empty()) {
424/// return "(* empty *)";
425/// }
426///
427/// bsl::string ret = d_queue.front(); // note constant time
428///
429/// d_queue.pop_front(); // note constant time
430///
431/// return ret;
432/// }
433///
434/// // ACCESSORS
435/// bool LaundryQueue::find(const bsl::string& customerName)
436/// {
437/// // Note `d_queue.empty() || d_queue[0] == d_queue.front()`
438///
439/// for (size_t i = 0; i < d_queue.size(); ++i) {
440/// if (customerName == d_queue[i]) { // note '[]' is constant time
441/// return true;
442/// }
443/// }
444///
445/// return false;
446/// }
447/// @endcode
448/// @}
449/** @} */
450/** @} */
451
452/** @addtogroup bsl
453 * @{
454 */
455/** @addtogroup bslstl
456 * @{
457 */
458/** @addtogroup bslstl_deque
459 * @{
460 */
461
462#include <bslscm_version.h>
463
464#include <bslstl_algorithm.h>
465#include <bslstl_iterator.h>
466#include <bslstl_iteratorutil.h>
468#include <bslstl_ranges.h>
469#include <bslstl_stdexceptutil.h>
470
471#include <bslalg_containerbase.h>
472#include <bslalg_dequeimputil.h>
473#include <bslalg_dequeiterator.h>
475#include <bslalg_rangecompare.h>
478
480#include <bslma_allocatorutil.h>
482#include <bslma_isstdallocator.h>
483#include <bslma_bslallocator.h>
485
486#include <bslmf_assert.h>
488#include <bslmf_isconvertible.h>
489#include <bslmf_issame.h>
490#include <bslmf_matchanytype.h>
492#include <bslmf_movableref.h>
493#include <bslmf_nil.h>
494#include <bslmf_typeidentity.h>
495#include <bslmf_util.h> // 'forward(V)'
496
497#include <bsls_assert.h>
499#include <bsls_keyword.h>
500#include <bsls_libraryfeatures.h>
501#include <bsls_performancehint.h>
502#include <bsls_util.h> // 'forward<T>(V)'
503
504#include <cstring>
505
506#if defined(BSLS_COMPILERFEATURES_SUPPORT_GENERALIZED_INITIALIZERS)
507#include <initializer_list>
508#endif
509
510#ifndef BDE_DONT_ALLOW_TRANSITIVE_INCLUDES
511#include <bsls_nativestd.h>
512#endif // BDE_DONT_ALLOW_TRANSITIVE_INCLUDES
513
514#ifndef BDE_DONT_ALLOW_TRANSITIVE_INCLUDES
515
516#include <stdexcept>
517#endif
518
519#if defined(BSLS_LIBRARYFEATURES_HAS_CPP20_CONCEPTS) \
520 && defined(BSLS_LIBRARYFEATURES_HAS_CPP20_RANGES)
521# define BSLSTL_DEQUE_REQUIRES_CONTAINER_COMPATIBLE_RANGE(R, T) \
522 requires ::BloombergLP::bslmf::ContainerCompatibleRange<R, T>
523#else
524# define BSLSTL_DEQUE_REQUIRES_CONTAINER_COMPATIBLE_RANGE(R, T)
525#endif
526
527#if BSLS_COMPILERFEATURES_SIMULATE_CPP11_FEATURES
528// clang-format off
529// Include version that can be compiled with C++03
530// Generated on Mon Jan 13 08:31:39 2025
531// Command line: sim_cpp11_features.pl bslstl_deque.h
532
533# define COMPILING_BSLSTL_DEQUE_H
534# include <bslstl_deque_cpp03.h>
535# undef COMPILING_BSLSTL_DEQUE_H
536
537// clang-format on
538#else
539
540namespace bsl {
541
542template <class VALUE_TYPE, class ALLOCATOR>
543class Deque_BlockCreator;
544template <class VALUE_TYPE, class ALLOCATOR>
545class Deque_BlockProctor;
546template <class VALUE_TYPE, class ALLOCATOR>
547class Deque_ClearGuard;
548template <class VALUE_TYPE, class ALLOCATOR>
549class Deque_Guard;
550
551 // ================================
552 // struct Deque_BlockLengthCalcUtil
553 // ================================
554
555/// This `struct` provides a namespace for the calculation of block length
556/// (the number of elements per block within a `deque`). This ensures that
557/// each block in the deque can hold at least 16 elements.
558///
559/// See @ref bslstl_deque
560template <class VALUE_TYPE>
562
563 // TYPES
564 enum {
565 DEFAULT_BLOCK_SIZE = 200, // number of bytes per block
566
567 BLOCK_LENGTH = (16 * sizeof(VALUE_TYPE) >= DEFAULT_BLOCK_SIZE)
568 ? 16
569 : (DEFAULT_BLOCK_SIZE / sizeof(VALUE_TYPE))
570 // number of elements per block
571 };
572};
573
574 // =================
575 // struct Deque_Util
576 // =================
577
578/// This `struct` provides a namespace to implement the `swap` member
579/// function of `deque<VALUE_TYPE, ALLOCATOR>`. This function can be
580/// implemented irrespective of the `VALUE_TYPE` or `ALLOCATOR` template
581/// parameters, which is why we implement it in this non-parameterized,
582/// non-inlined utility.
583///
584/// See @ref bslstl_deque
586
587 // CLASS METHODS
588
589 /// Assign the value of the specified `dst` deque to that of the
590 /// specified `src` deque, and reset the `src` deque to a raw state.
591 static void move(void *dst, void *src);
592
593 /// Exchange the value of the specified `a` deque with that of the
594 /// specified `b` deque.
595 static void swap(void *a, void *b);
596};
597
598 // ================
599 // class Deque_Base
600 // ================
601
602/// This class describes the basic layout for a deque class. It is
603/// important that this class has the same layout as the deque class
604/// implementation. It is parameterized by `VALUE_TYPE` only and implements
605/// the portion of `bsl::deque` that does not need to know about its
606/// (template parameter) type `ALLOCATOR` (in order to generate shorter debug strings).
607///
608/// \note Note that this class must have the same layout as
609/// `Deque_Imp` (see implementation file).
610///
611/// See @ref bslstl_deque
612template <class VALUE_TYPE>
614
615 // PRIVATE TYPES
616 enum {
618 };
619
620 typedef BloombergLP::bslalg::DequeImpUtil<VALUE_TYPE,
621 BLOCK_LENGTH> Imp;
622 typedef typename Imp::Block Block;
623 typedef typename Imp::BlockPtr BlockPtr;
624 typedef BloombergLP::bslalg::DequeIterator<VALUE_TYPE,
625 BLOCK_LENGTH> IteratorImp;
626 typedef BloombergLP::
627 bslstl::RandomAccessIterator<VALUE_TYPE, IteratorImp>
628 Iterator;
629
630 typedef BloombergLP::
631 bslstl::RandomAccessIterator<const VALUE_TYPE, IteratorImp>
632 ConstIterator;
633
634 public:
635 // PUBLIC TYPES
636 typedef VALUE_TYPE& reference;
637 typedef const VALUE_TYPE& const_reference;
638 typedef Iterator iterator;
639 typedef ConstIterator const_iterator;
640 typedef std::size_t size_type;
641 typedef std::ptrdiff_t difference_type;
642 typedef VALUE_TYPE value_type;
643
644 // For consistent behavior on all compilers, we must 'bsl::'-qualify
645 // @ref reverse_iterator . (For most compilers, @ref reverse_iterator is in
646 // namespace 'std', and NOT in namespace 'bsl'. Hence, we need to
647 // actively look into a different namespace to find the iterator. However,
648 // on Solaris we explicitly provide a @ref reverse_iterator implementation, IN
649 // namespace 'bsl', to replace their broken one. See 'bslstl_iterator.h'.)
650
651 typedef bsl::reverse_iterator<Iterator> reverse_iterator;
652 typedef bsl::reverse_iterator<ConstIterator> const_reverse_iterator;
653
654 protected:
655 // PROTECTED DATA
656 BlockPtr *d_blocks_p; // array of pointer to blocks (owned)
657 std::size_t d_blocksLength; // length of 'd_blocks_p' array
658 IteratorImp d_start; // iterator to first element
659 IteratorImp d_finish; // iterator to one past last element
660
661 public:
662 // MANIPULATORS
663
664 // *** iterators ***
665
666 /// Return an iterator providing modifiable access to the first element
667 /// in this deque, and the past-the-end iterator if this deque is empty.
669
670 /// Return the past-the-end (forward) iterator providing modifiable
671 /// access to this deque.
673
674 /// Return a reverse iterator providing modifiable access to the last
675 /// element in this deque, and the past-the-end reverse iterator if this
676 /// deque is empty.
678
679 /// Return the past-the-end reverse iterator providing modifiable access
680 /// to this deque.
682
683 // *** element access ***
684
685 /// Return a reference providing modifiable access to the element at the
686 /// specified `position` in this deque.
687 ///
688 /// \pre The behavior is undefined unless `position < size()`.
689 reference operator[](size_type position);
690
691 /// Return a reference providing modifiable access to the element at the
692 /// specified `position` in this deque. Throw a `std::out_of_range`
693 /// exception if `position >= size()`.
695
696 /// Return a reference providing modifiable access to the first element in this deque.
697 ///
698 /// \pre The behavior is undefined unless this deque is not
699 /// empty.
701
702 /// Return a reference providing modifiable access to the last element in this deque.
703 ///
704 /// \pre The behavior is undefined unless this deque is not
705 /// empty.
707
708 // ACCESSORS
709
710 // *** iterators ***
711
713
714 /// Return an iterator providing non-modifiable access to the first
715 /// element in this deque, and the past-the-end iterator if this deque
716 /// is empty.
718
720
721 /// Return the past-the-end (forward) iterator providing non-modifiable
722 /// access to this deque.
724
726
727 /// Return a reverse iterator providing non-modifiable access to the
728 /// last element in this deque, and the past-the-end reverse iterator if
729 /// this deque is empty.
731
733
734 /// Return the past-the-end reverse iterator providing non-modifiable
735 /// access to this deque.
737
738 // *** capacity ***
739
740 /// Return the number of elements contained by this deque.
742
743 /// Return the sum of the current size of this deque plus the minimum
744 /// number of `push_front` or `push_back` operations needed to invalidate iterators in this deque.
745 ///
746 /// \note Note that this method is not
747 /// part of the C++ standard.
749
750 /// Return `true` if this deque contains no elements, and `false`
751 /// otherwise.
753
754 // *** element access ***
755
756 /// Return a reference providing non-modifiable access to the element at
757 /// the specified `position` in this deque.
758 ///
759 /// \pre The behavior is undefined unless `position < size()`.
760 const_reference operator[](size_type position) const;
761
762 /// Return a reference providing non-modifiable access to the element at
763 /// the specified `position` in this deque. Throw a `std::out_of_range`
764 /// exception if `position >= size()`.
765 const_reference at(size_type position) const;
766
767 /// Return a reference providing non-modifiable access to the first element in this deque.
768 ///
769 /// \pre The behavior is undefined unless this deque
770 /// is not empty.
772
773 /// Return a reference providing non-modifiable access to the last element in this deque.
774 ///
775 /// \pre The behavior is undefined unless this deque
776 /// is not empty.
778};
779
780 // ===========
781 // class deque
782 // ===========
783
784/// This class template provides an STL-compliant `deque` that conforms to
785/// the `bslma::Allocator` model. For the requirements of a deque class,
786/// consult the C++11 standard. In particular, this implementation offers
787/// the general rules that:
788/// 1. A call to any method that would result in a deque having a size
789/// greater than the value returned by @ref max_size triggers a call to
790/// `bslstl::StdExceptUtil::throwLengthError`.
791/// 2. A call to an `at` method that attempts to access a position
792/// outside of the valid range of a deque triggers a call to
793/// `bslstl::StdExceptUtil::throwOutOfRange`.
794///
795///
796/// \note Note that portions of the standard methods are implemented in
797/// `Deque_Base`, which is parameterized on only `VALUE_TYPE` in order to
798/// generate smaller debug strings.
799///
800/// This class:
801/// * supports a complete set of *value-semantic* operations
802/// - except for `BDEX` serialization
803/// * is *exception-neutral*
804/// * is *alias-safe*
805/// * is `const` *thread-safe*
806/// For terminology see @ref bsldoc_glossary .
807///
808/// In addition, the following members offer a full guarantee of rollback:
809/// if an exception is thrown during the invocation of `insert`,
810/// `push_front`, or `push_back` on a pre-existing object, the object is
811/// left in a valid state and its value is unchanged.
812template <class VALUE_TYPE, class ALLOCATOR = allocator<VALUE_TYPE> >
813class deque : public Deque_Base<VALUE_TYPE>
814 , private BloombergLP::bslalg::ContainerBase<ALLOCATOR> {
815
816 // PRIVATE TYPES
817 enum {
819 };
820
821 typedef Deque_Base<VALUE_TYPE> Base;
822
823 typedef BloombergLP::bslalg::ContainerBase<ALLOCATOR> ContainerBase;
824
825 typedef BloombergLP::bslalg::DequeImpUtil<VALUE_TYPE,
826 BLOCK_LENGTH> Imp;
827 typedef typename Imp::Block Block;
828 typedef typename Imp::BlockPtr BlockPtr;
829
830 typedef BloombergLP::bslalg::DequeIterator<VALUE_TYPE,
831 BLOCK_LENGTH> IteratorImp;
832
833 typedef BloombergLP::
834 bslstl::RandomAccessIterator<VALUE_TYPE,
835 IteratorImp> Iterator;
836
837 typedef BloombergLP::
838 bslstl::RandomAccessIterator<const VALUE_TYPE,
839 IteratorImp> ConstIterator;
840
845
846 typedef BloombergLP::bslalg::DequePrimitives<VALUE_TYPE,
847 BLOCK_LENGTH> DequePrimitives;
848
849 typedef BloombergLP::bslma::AllocatorUtil AllocatorUtil;
851
852 /// This typedef is a convenient alias for the utility associated with
853 /// movable references.
854 typedef BloombergLP::bslmf::MovableRefUtil MoveUtil;
855
856 /// Special type (and value) used to create a "raw" deque, which has a
857 /// block length of 0, and null start and finish pointers.
858 enum RawInit { k_RAW_INIT = 0 };
859
860 public:
861 // PUBLIC TYPES
862 typedef VALUE_TYPE& reference;
863 typedef const VALUE_TYPE& const_reference;
864 typedef Iterator iterator;
865 typedef ConstIterator const_iterator;
866 typedef std::size_t size_type;
867 typedef std::ptrdiff_t difference_type;
868 typedef VALUE_TYPE value_type;
869
870 typedef ALLOCATOR allocator_type;
873
874 // As above, we must 'bsl::'-qualify @ref reverse_iterator .
875
876 typedef bsl::reverse_iterator<Iterator> reverse_iterator;
877 typedef bsl::reverse_iterator<ConstIterator> const_reverse_iterator;
878
879 private:
880 // STATIC ASSERTIONS
881
884 typename Base::const_reference>::value));
885 // These need not necessarily be true as per the C++ standard, but are
886 // safe assumptions for this implementation and allow us to implement
887 // the element access within the 'Base' type (that is parameterized by
888 // 'VALUE_TYPE' only).
889
890 // PRIVATE CREATORS
891
892 /// Create a "raw" deque (i.e., a deque that obeys the raw deque
893 /// invariants and is destructible) that uses the specified `allocator`
894 /// to supply memory. The following holds for a raw deque:
895 /// `0 == d_blocks_p`, `0 == d_blocksLength`, and `d_start` and
896 /// `d_finish` are singular iterators (i.e., have null internal pointers).
897 ///
898 /// \note Note that the constructed deque contains no allocated
899 /// storage. Also note that the purpose of a raw deque is to provide an
900 /// exception-safe repository for intermediate calculations.
901 deque(RawInit, const allocator_type& allocator);
902
903 // PRIVATE MANIPULATORS
904
905 /// Return one block allocated from this object's allocator.
906 ///
907 /// \note Note that the block is not initialized.
908 Block *allocateBlock();
909
910 /// Allocate an array having the specified `n` elements of type `BlockPtr` from this object's allocator.
911 ///
912 /// \note Note that the array
913 /// elements are not initialized.
914 BlockPtr *allocateBlockPtrs(std::size_t n);
915
916 /// Deallocate from this object's allocator the block at the specified `p` address.
917 ///
918 /// \note Note that this function does not call any destructors
919 /// on `p` or `*p`.
920 void deallocateBlock(Block *p);
921
922 /// Deallocate from this object's allocator an array at the specified
923 /// `p` address having the specified `n` elements of type `BlockPtr`.
924 ///
925 /// \note Note that if any of the array elements point to an allocated block,
926 /// then that block is not deallocated (and might be leaked).
927 void deallocateBlockPtrs(BlockPtr *p, std::size_t n);
928
929 /// Append the elements in the range specified by `[first .. last)` to
930 /// this deque, and return the number of elements appended.
931 ///
932 /// \pre The behavior is undefined unless `first` and `last` refer to a sequence of valid
933 /// values where `first` is at a position at or before `last`.
934 template <class INPUT_ITERATOR, class SENTINEL>
935 size_type privateAppend(INPUT_ITERATOR first, SENTINEL last);
936
937 /// Append the elements in the range specified by `[first .. last)` to
938 /// this deque, and return the number of elements appended. The third
939 /// argument is used for overload resolution.
940 ///
941 /// \pre The behavior is undefined unless `first` and `last` refer to a sequence of valid values where
942 /// `first` is at a position at or before `last`.
943 template <class INPUT_ITERATOR, class SENTINEL>
944 size_type privateAppend(INPUT_ITERATOR first,
945 SENTINEL last,
946 std::input_iterator_tag);
947 template <class INPUT_ITERATOR, class SENTINEL>
948 size_type privateAppend(INPUT_ITERATOR first,
949 SENTINEL last,
950 std::random_access_iterator_tag);
951
952 /// Append the specified `numElements` value-inititalized objects to
953 /// this deque.
954 void privateAppendDefaultInsertable(size_type numElements);
955
956 /// Append the specified `numElements` copies of the specified `value`
957 /// to this deque.
958 void privateAppendRaw(size_type numElements, const VALUE_TYPE& value);
959
960 /// Assign the elements in the range specified by `[first .. last)` to this
961 /// deque.
962 template <class t_ITERATOR, class t_SENTINEL>
963 void privateAssign(t_ITERATOR first, t_SENTINEL last);
964
965 /// Initialize `d_start` and `d_finish` for eventual insertion of the
966 /// specified `numElements` elements. After this method returns, this
967 /// object is fully constructed with memory allocated for `numElements`,
968 /// with all member variables obeying the class invariants, and with size 0.
969 ///
970 /// \pre The behavior is undefined unless this object is in a "raw" state.
971 ///
972 /// \note Note that this method must not be called while constructing
973 /// this object (although a constructor may call it for a temporary
974 /// object).
975 void privateInit(size_type numElements);
976
977 /// Insert the specified `numElements` copies of the specified `value`
978 /// into this deque at the specified `position`. This overload matches
979 /// `privateInsert` when the second and third arguments are of the same
980 /// type which happens to be an integral type. The fourth and fifth
981 /// arguments are used for overload resolution only.
982 template <class INTEGER_TYPE>
983 void privateInsertDispatch(
984 const_iterator position,
985 INTEGER_TYPE numElements,
986 INTEGER_TYPE value,
987 BloombergLP::bslmf::MatchArithmeticType,
988 BloombergLP::bslmf::Nil);
989
990 /// Insert the elements in the range specified by `[first .. last)` into
991 /// this deque at the specified `position`. The third and fourth
992 /// arguments are used for overload resolution only, so that this
993 /// function is not called if `first` and `last` are of integral type.
994 ///
995 /// \pre The behavior is undefined unless `first` and `last` refer to a
996 /// sequence of valid values where `first` is at a position at or before
997 /// `last`.
998 template <class INPUT_ITERATOR>
999 void privateInsertDispatch(const_iterator position,
1000 INPUT_ITERATOR first,
1001 INPUT_ITERATOR last,
1002 BloombergLP::bslmf::MatchAnyType,
1003 BloombergLP::bslmf::MatchAnyType);
1004
1005 /// Insert the elements in the range specified by `[first .. last)` into
1006 /// this deque at the specified `position`.
1007 template <class INPUT_ITERATOR, class SENTINEL>
1008 void privateInsert(const_iterator position,
1009 INPUT_ITERATOR first,
1010 SENTINEL last);
1011
1012 /// Specialized insertion for input iterators.
1013 template <class INPUT_ITERATOR, class SENTINEL>
1014 void privateInsert(const_iterator position,
1015 INPUT_ITERATOR first,
1016 SENTINEL last,
1017 std::input_iterator_tag);
1018
1019 /// Specialized insertion for forward, bidirectional, and random-access
1020 /// iterators.
1021 template <class INPUT_ITERATOR, class SENTINEL>
1022 void privateInsert(const_iterator position,
1023 INPUT_ITERATOR first,
1024 SENTINEL last,
1025 std::random_access_iterator_tag);
1026
1027 /// Join `*this` and the specified `other` deque into one. After the
1028 /// join, `*this` contains the concatenated sequence, in order, of
1029 /// `*other` and `*this` elements, and 'other is made a raw deque.
1030 void privateJoinPrepend(deque *other);
1031
1032 /// Join `*this` and the specified `other` deque into one. After the
1033 /// join, `*this` contains the concatenated sequence, in order, of
1034 /// `*this` and `*other` elements, and 'other is made a raw deque.
1035 void privateJoinAppend(deque *other);
1036
1037 /// Prepend the elements in the range specified by `[first .. last)` to
1038 /// this deque, and return the number of elements prepended.
1039 ///
1040 /// \pre The behavior is undefined unless `first` and `last` refer to a sequence of valid
1041 /// values where `first` is at a position at or before `last`.
1042 template <class INPUT_ITERATOR, class SENTINEL>
1043 size_type privatePrepend(INPUT_ITERATOR first, SENTINEL last);
1044
1045 /// Prepend the elements in the range specified by `[first .. last)` to
1046 /// this deque, and return the number of elements prepended. The third
1047 /// argument is used for overload resolution only.
1048 ///
1049 /// \pre The behavior is undefined unless `first` and `last` refer to a sequence of valid
1050 /// values where `first` is at a position at or before `last`.
1051 template <class INPUT_ITERATOR, class SENTINEL>
1052 size_type privatePrepend(INPUT_ITERATOR first,
1053 SENTINEL last,
1054 std::input_iterator_tag);
1055 template <class INPUT_ITERATOR, class SENTINEL>
1056 size_type privatePrepend(INPUT_ITERATOR first,
1057 SENTINEL last,
1058 std::bidirectional_iterator_tag);
1059 template <class INPUT_ITERATOR, class SENTINEL>
1060 size_type privatePrepend(INPUT_ITERATOR first,
1061 SENTINEL last,
1062 std::random_access_iterator_tag);
1063
1064 /// Prepend the specified `numElements` copies of the specified `value`
1065 /// to this deque.
1066 void privatePrependRaw(size_type numElements, const VALUE_TYPE& value);
1067
1068 /// Split this deque in two such that after the split, `*this` contains
1069 /// elements formerly in the range specified by `[d_start .. pos)` and
1070 /// the specified `other` deque contains elements formerly in the range `[pos .. d_finish)`.
1071 ///
1072 /// \pre The behavior is undefined unless `other` is a
1073 /// raw deque, i.e., the `RawInit` constructor was used to create
1074 /// `other`.
1075 void privateSplit(deque *other, IteratorImp pos);
1076
1077 // FRIENDS
1078 template <class VALUE_TYPE2, class ALLOCATOR2>
1080
1081 template <class VALUE_TYPE2, class ALLOCATOR2>
1083
1084 template <class VALUE_TYPE2, class ALLOCATOR2>
1085 friend class Deque_Guard;
1086
1087 public:
1088 // CREATORS
1089
1090 // *** construct/copy/destroy ***
1091
1092 /// Create an empty deque. Optionally specify a `basicAllocator` used
1093 /// to supply memory. If `basicAllocator` is not supplied, a
1094 /// default-constructed object of the (template parameter) type
1095 /// `ALLOCATOR` is used. If the type `ALLOCATOR` is `bsl::allocator`
1096 /// (the default), then `basicAllocator`, if supplied, shall be
1097 /// convertible to `bslma::Allocator *`. If the type `ALLOCATOR` is
1098 /// `bsl::allocator` and `basicAllocator` is not supplied, the currently
1099 /// installed default allocator is used.
1101 explicit deque(const ALLOCATOR& basicAllocator);
1102
1103 /// Create a deque of the specified `numElements` size whose every
1104 /// element is value-initialized. Optionally specify a `basicAllocator`
1105 /// used to supply memory. If `basicAllocator` is not supplied, a
1106 /// default-constructed object of the (template parameter) type
1107 /// `ALLOCATOR` is used. If the type `ALLOCATOR` is `bsl::allocator`
1108 /// (the default), then `basicAllocator`, if supplied, shall be
1109 /// convertible to `bslma::Allocator *`. If the type `ALLOCATOR` is
1110 /// `bsl::allocator` and `basicAllocator` is not supplied, the currently
1111 /// installed default allocator is used. Throw `bsl::length_error` if
1112 /// `numElements > max_size()`. This method requires that the (template
1113 /// parameter) `VALUE_TYPE` be `default-insertable` into this deque (see
1114 /// {Requirements on `VALUE_TYPE`}).
1115 explicit
1116 deque(size_type numElements,
1117 const ALLOCATOR& basicAllocator = ALLOCATOR());
1118
1119 /// Create a deque of the specified `numElements` size whose every
1120 /// element has the specified `value`. Optionally specify a
1121 /// `basicAllocator` used to supply memory. If `basicAllocator` is not
1122 /// supplied, a default-constructed object of the (template parameter)
1123 /// type `ALLOCATOR` is used. If the type `ALLOCATOR` is
1124 /// `bsl::allocator` (the default), then `basicAllocator`, if supplied,
1125 /// shall be convertible to `bslma::Allocator *`. If the type
1126 /// `ALLOCATOR` is `bsl::allocator` and `basicAllocator` is not
1127 /// supplied, the currently installed default allocator is used. Throw
1128 /// `bsl::length_error` if `numElements > max_size()`. This method
1129 /// requires that the (template parameter) `VALUE_TYPE` be
1130 /// `copy-insertable` into this deque (see {Requirements on
1131 /// `VALUE_TYPE`}).
1132 deque(size_type numElements,
1133 const VALUE_TYPE& value,
1134 const ALLOCATOR& basicAllocator = ALLOCATOR());
1135
1136 /// Create a deque initially containing copies of the values in the
1137 /// range starting at the specified `first` and ending immediately
1138 /// before the specified `last` iterators of the (template parameter)
1139 /// type `INPUT_ITERATOR`. Optionally specify a `basicAllocator` used
1140 /// to supply memory. If `basicAllocator` is not supplied, a
1141 /// default-constructed object of the (template parameter) type
1142 /// `ALLOCATOR` is used. If the type `ALLOCATOR` is `bsl::allocator`
1143 /// (the default), then `basicAllocator`, if supplied, shall be
1144 /// convertible to `bslma::Allocator *`. If the type `ALLOCATOR` is
1145 /// `bsl::allocator` and `basicAllocator` is not supplied, the currently
1146 /// installed default allocator is used. Throw `bsl::length_error` if
1147 /// the number of elements in `[first .. last)` exceeds the size
1148 /// returned by @ref max_size . The (template parameter) type
1149 /// `INPUT_ITERATOR` shall meet the requirements of an input iterator
1150 /// defined in the C++11 standard [input.iterators] providing access to
1151 /// values of a type convertible to `value_type`, and `value_type` must
1152 /// be `emplace-constructible` from `*i` into this deque, where `i` is a
1153 /// dereferenceable iterator in the range `[first .. last)` (see {Requirements on `VALUE_TYPE`}).
1154 ///
1155 /// \pre The behavior is undefined unless
1156 /// `first` and `last` refer to a sequence of valid values where `first`
1157 /// is at a position at or before `last`.
1158 template <class INPUT_ITERATOR>
1159 deque(INPUT_ITERATOR first,
1160 INPUT_ITERATOR last,
1161 const ALLOCATOR& basicAllocator = ALLOCATOR());
1162
1163 /// Create a deque from the elements of the specifed `range`. Optionally
1164 /// specify an `basicAllocator` used to supply memory. If `basicAllocator`
1165 /// is not specified, a default-constructed object of the (template parameter) type `ALLOCATOR` is used.
1166 ///
1167 /// \note Note that `range` must meet the
1168 /// requirements of an input range and the values from `range` must have a
1169 /// type matching or convertible to (template parameter) `VALUE_TYPE`.
1170 template <class t_RANGE>
1173 BSLS_COMPILERFEATURES_FORWARD_REF(t_RANGE) range,
1174 const ALLOCATOR& basicAllocator =
1175 ALLOCATOR());
1176
1177 /// Create a deque that has the same value as the specified `original`
1178 /// object. Use the allocator returned by
1179 /// 'bsl::allocator_traits<ALLOCATOR>::
1180 /// select_on_container_copy_construction(original.get_allocator())' to
1181 /// supply memory. If the (template parameter) type `ALLOCATOR` is
1182 /// `bsl::allocator` (the default), the currently installed default
1183 /// allocator is used. This method requires that the (template
1184 /// parameter) `VALUE_TYPE` be `copy-insertable` into this deque (see
1185 /// {Requirements on `VALUE_TYPE`}).
1186 deque(const deque& original);
1187
1188 /// Create a deque that has the same value as the specified `original`
1189 /// object and that uses the specified `basicAllocator` to supply
1190 /// memory. This method requires that the (template parameter)
1191 /// `VALUE_TYPE` be `copy-insertable` into this deque (see {Requirements on `VALUE_TYPE`}).
1192 ///
1193 /// \note Note that a `bslma::Allocator *`
1194 /// can be supplied for `basicAllocator` if the (template parameter)
1195 /// type `ALLOCATOR` is `bsl::allocator` (the default).
1196 deque(const deque& original,
1197 const typename type_identity<ALLOCATOR>::type& basicAllocator);
1198
1199 /// Create a deque having the same value as the specified `original`
1200 /// object by moving (in constant time) the contents of `original` to
1201 /// the new deque. The allocator associated with `original` is
1202 /// propagated for use in the newly-created deque. `original` is left
1203 /// in a valid but unspecified state.
1204 deque(BloombergLP::bslmf::MovableRef<deque> original); // IMPLICIT
1205
1206 /// Create a deque having the same value as the specified `original`
1207 /// object that uses the specified `basicAllocator` to supply memory.
1208 /// The contents of `original` are moved (in constant time) to the new
1209 /// deque if `basicAllocator == original.get_allocator()`, and are move-
1210 /// inserted (in linear time) using `basicAllocator` otherwise.
1211 /// `original` is left in a valid but unspecified state. This method
1212 /// requires that the (template parameter) `VALUE_TYPE` be
1213 /// `move-insertable` into this deque (see {Requirements on `VALUE_TYPE`}).
1214 ///
1215 /// \note Note that a `bslma::Allocator *` can be supplied
1216 /// for `basicAllocator` if the (template parameter) `ALLOCATOR` is
1217 /// `bsl::allocator` (the default).
1218 deque(BloombergLP::bslmf::MovableRef<deque> original,
1219 const typename type_identity<ALLOCATOR>::type& basicAllocator);
1220
1221#if defined(BSLS_COMPILERFEATURES_SUPPORT_GENERALIZED_INITIALIZERS)
1222 /// Create a deque and append each `value_type` object in the specified
1223 /// `values` initializer list. Optionally specify a `basicAllocator`
1224 /// used to supply memory. If `basicAllocator` is not supplied, a
1225 /// default-constructed object of the (template parameter) type
1226 /// `ALLOCATOR` is used. If the type `ALLOCATOR` is `bsl::allocator`
1227 /// (the default), then `basicAllocator`, if supplied, shall be
1228 /// convertible to `bslma::Allocator *`. If the type `ALLOCATOR` is
1229 /// `bsl::allocator` and `basicAllocator` is not supplied, the currently
1230 /// installed default allocator is used. This method requires that the
1231 /// (template parameter) `VALUE_TYPE` be `copy-insertable` into this
1232 /// deque (see {Requirements on `VALUE_TYPE`}).
1233 deque(std::initializer_list<value_type> values,
1234 const ALLOCATOR& basicAllocator = ALLOCATOR());
1235#endif
1236
1237 /// Destroy this object.
1239
1240 // MANIPULATORS
1241
1242 /// Assign to this object the value of the specified `rhs` object,
1243 /// propagate to this object the allocator of `rhs` if the `ALLOCATOR`
1244 /// type has trait @ref propagate_on_container_copy_assignment , and return
1245 /// a reference providing modifiable access to this object. If an
1246 /// exception is thrown, `*this` is left in a valid but unspecified
1247 /// state. This method requires that the (template parameter)
1248 /// `VALUE_TYPE` be `copy-assignable` and `copy-insertable` into this
1249 /// deque (see {Requirements on `VALUE_TYPE`}).
1251
1252 /// Assign to this object the value of the specified `rhs` object,
1253 /// propagate to this object the allocator of `rhs` if the `ALLOCATOR`
1254 /// type has trait @ref propagate_on_container_move_assignment , and return
1255 /// a reference providing modifiable access to this object. The
1256 /// contents of `rhs` are moved (in constant time) to this deque if
1257 /// `get_allocator() == rhs.get_allocator()` (after accounting for the
1258 /// aforementioned trait); otherwise, all elements in this deque are
1259 /// either destroyed or move-assigned to and each additional element in
1260 /// `rhs` is move-inserted into this deque. `rhs` is left in a valid
1261 /// but unspecified state, and if an exception is thrown, `*this` is
1262 /// left in a valid but unspecified state. This method requires that
1263 /// the (template parameter) `VALUE_TYPE` be `move-assignable` and
1264 /// `move-insertable` into this deque (see {Requirements on
1265 /// `VALUE_TYPE`}).
1266 deque& operator=(BloombergLP::bslmf::MovableRef<deque> rhs)
1268 AllocatorTraits::is_always_equal::value);
1269
1270#if defined(BSLS_COMPILERFEATURES_SUPPORT_GENERALIZED_INITIALIZERS)
1271 /// Assign to this object the value resulting from first clearing this
1272 /// deque and then appending each `value_type` object in the specified
1273 /// `values` initializer list; return a reference providing modifiable
1274 /// access to this object. This method requires that the (template
1275 /// parameter) `VALUE_TYPE` be `copy-insertable` into this deque (see
1276 /// {Requirements on `VALUE_TYPE`}).
1277 deque& operator=(std::initializer_list<value_type> values);
1278#endif
1279
1280 /// Assign to this deque the values in the range starting at the
1281 /// specified `first` and ending immediately before the specified `last`
1282 /// iterators of the (template parameter) type `INPUT_ITERATOR`. The
1283 /// (template parameter) type `INPUT_ITERATOR` shall meet the
1284 /// requirements of an input iterator defined in the C++11 standard
1285 /// [input.iterators] providing access to values of a type convertible
1286 /// to `value_type`, and `value_type` must be `copy-assignable` and
1287 /// `emplace-constructible` from `*i` into this deque, where `i` is a
1288 /// dereferenceable iterator in the range `[first .. last)` (see {Requirements on `VALUE_TYPE`}).
1289 ///
1290 /// \pre The behavior is undefined unless
1291 /// `first` and `last` refer to a sequence of valid values where `first`
1292 /// is at a position at or before `last`.
1293 template <class INPUT_ITERATOR>
1294 void assign(INPUT_ITERATOR first, INPUT_ITERATOR last);
1295
1296 /// Assign to this object the value resulting from first clearing this
1297 /// deque and then appending the specified `numElements` having the
1298 /// specified `value`. This method requires that the (template
1299 /// parameter) `VALUE_TYPE` be `copy-assignable` and `copy-insertable`
1300 /// into this deque (see {Requirements on `VALUE_TYPE`}).
1301 void assign(size_type numElements, const VALUE_TYPE& value);
1302
1303#if defined(BSLS_COMPILERFEATURES_SUPPORT_GENERALIZED_INITIALIZERS)
1304 /// Assign to this object the value resulting from first clearing this
1305 /// deque and then appending each `value_type` object in the specified
1306 /// `values` initializer list. This method requires that the (template
1307 /// parameter) `VALUE_TYPE` be `copy-assignable` and `copy-insertable`
1308 /// into this deque (see {Requirements on `VALUE_TYPE`}).
1309 void assign(std::initializer_list<value_type> values);
1310#endif
1311
1312 /// Assign to this object the elements of the specified `range`.
1313 ///
1314 /// \note Note that `range` must meet the requirements of an input range and the values
1315 /// from `range` must have a type matching or convertible to (template
1316 /// parameter) `VALUE_TYPE`.
1317 template <class t_RANGE>
1319 void assign_range(BSLS_COMPILERFEATURES_FORWARD_REF(t_RANGE) range);
1320
1321 // *** capacity ***
1322
1323 /// Change the capacity of this deque such that, after this method
1324 /// returns, iterators remain valid provided that no more than the
1325 /// specified `numElements` objects are pushed to the front or back of
1326 /// the deque after this call. If it is already possible to push
1327 /// `numElements` objects to either end of this deque without
1328 /// invalidating iterators, this method has no effect.
1329 ///
1330 /// \note Note that inserting elements into the deque may still incur memory allocation.
1331 /// Also note that this method, if it has any effect, will invalidate
1332 /// iterators initialized prior to the call. Also note that this method
1333 /// is not part of the C++ standard.
1334 void reserve(size_type numElements);
1335
1336 /// Change the size of this deque to the specified `newSize`. Erase
1337 /// `size() - newSize` elements at the back if `newSize < size()`.
1338 /// Append `newSize - size()` elements at the back having the optionally
1339 /// specified `value` if `newSize > size()`; if `value` is not
1340 /// specified, value-initialized objects of the (template parameter)
1341 /// `VALUE_TYPE` are emplaced. This method has no effect if
1342 /// `newSize == size()`. Throw `bsl::length_error` if
1343 /// `newSize > max_size()`.
1344 void resize(size_type newSize);
1345 void resize(size_type newSize, const VALUE_TYPE& value);
1346
1347 /// Minimize the memory used by this deque to the extent possible
1348 /// without moving any contained elements. If an exception is thrown, the value of this object is unchanged.
1349 ///
1350 /// \note Note that this method has no
1351 /// effect on the memory used by individual elements of the (template
1352 /// parameter) `VALUE_TYPE`.
1353 void shrink_to_fit();
1354
1355 // *** modifiers ***
1356
1357 /// Append to the end of this object the elements of the specified `range`.
1358 ///
1359 /// \note Note that `range` must meet the requirements of an input range and the
1360 /// values from `range` must have a type matching or convertible to
1361 /// (template parameter) `VALUE_TYPE`.
1362 template <class t_RANGE>
1364 void append_range(BSLS_COMPILERFEATURES_FORWARD_REF(t_RANGE) range);
1365
1366 /// Prepend to the front of this object the elements of the specified `range`.
1367 ///
1368 /// \note Note that `range` must meet the requirements of an input
1369 /// range and the values from `range` must have a type matching or
1370 /// convertible to (template parameter) `VALUE_TYPE`.
1371 template <class t_RANGE>
1373 void prepend_range(BSLS_COMPILERFEATURES_FORWARD_REF(t_RANGE) range);
1374
1375 /// Prepend to the front of this deque a copy of the specified `value`.
1376 /// This method offers full guarantee of rollback in case an exception
1377 /// is thrown. This method requires that the (template parameter)
1378 /// `VALUE_TYPE` be `copy-constructible` (see {Requirements on
1379 /// `VALUE_TYPE`}).
1380 void push_front(const VALUE_TYPE& value);
1381
1382 /// Prepend to the front of this deque the specified move-insertable
1383 /// `value`. `value` is left in a valid but unspecified state. If an
1384 /// exception is thrown (other than by the move constructor of a
1385 /// non-copy-insertable `value_type`), this method has no effect. This
1386 /// method requires that the (template parameter) `VALUE_TYPE` be
1387 /// `move-insertable` into this deque (see {Requirements on
1388 /// `VALUE_TYPE`}).
1389 void push_front(BloombergLP::bslmf::MovableRef<value_type> value);
1390
1391 /// Append to the back of this deque a copy of the specified `value`.
1392 /// This method offers full guarantee of rollback in case an exception
1393 /// is thrown. This method requires that the (template parameter)
1394 /// `VALUE_TYPE` be `copy-constructible` (see {Requirements on
1395 /// `VALUE_TYPE`}).
1396 void push_back(const VALUE_TYPE& value);
1397
1398 /// Append to the back of this deque the specified move-insertable
1399 /// `value`. `value` is left in a valid but unspecified state. If an
1400 /// exception is thrown (other than by the move constructor of a
1401 /// non-copy-insertable `value_type`), this method has no effect. This
1402 /// method requires that the (template parameter) `VALUE_TYPE` be
1403 /// `move-insertable` into this deque (see {Requirements on
1404 /// `VALUE_TYPE`}).
1405 void push_back(BloombergLP::bslmf::MovableRef<value_type> value);
1406
1407#if !BSLS_COMPILERFEATURES_SIMULATE_CPP11_FEATURES
1408 /// Prepend to the front of this deque a newly created `value_type`
1409 /// object, constructed by forwarding `get_allocator()` (if required)
1410 /// and the specified (variable number of) `arguments` to the
1411 /// corresponding constructor of `value_type`. Return a reference
1412 /// providing modifiable access to the inserted element. If an
1413 /// exception is thrown (other than by the move constructor of a
1414 /// non-copy-insertable `value_type`), this method has no effect. This
1415 /// method requires that the (template parameter) `VALUE_TYPE` be
1416 /// `move-insertable` into this deque and `emplace-constructible` from
1417 /// `arguments` (see
1418 /// {Requirements on `VALUE_TYPE`}).
1419 template <class... Args>
1420 reference emplace_front(Args&&... arguments);
1421
1422 /// Append to the back of this deque a newly created `value_type`
1423 /// object, constructed by forwarding `get_allocator()` (if required)
1424 /// and the specified (variable number of) `arguments` to the
1425 /// corresponding constructor of `value_type`. Return a reference
1426 /// providing modifiable access to the inserted element. If an
1427 /// exception is thrown (other than by the move constructor of a
1428 /// non-copy-insertable `value_type`), this method has no effect. This
1429 /// method requires that the (template parameter) `VALUE_TYPE` be
1430 /// `move-insertable` into this deque and `emplace-constructible` from
1431 /// `arguments` (see
1432 /// {Requirements on `VALUE_TYPE`}).
1433 template <class... Args>
1434 reference emplace_back(Args&&... arguments);
1435#endif
1436
1437#if !BSLS_COMPILERFEATURES_SIMULATE_CPP11_FEATURES
1438 /// Insert at the specified `position` in this deque a newly created
1439 /// `value_type` object, constructed by forwarding `get_allocator()` (if
1440 /// required) and the specified (variable number of) `arguments` to the
1441 /// corresponding constructor of `value_type`, and return an iterator
1442 /// providing modifiable access to the newly created and inserted
1443 /// element. If an exception is thrown (other than by the copy
1444 /// constructor, move constructor, assignment operator, or move
1445 /// assignment operator of `value_type`), this method has no effect.
1446 /// This method requires that the (template parameter) `VALUE_TYPE` be
1447 /// `move-insertable` into this deque and `emplace-constructible` from
1448 /// `arguments` (see {Requirements on `VALUE_TYPE`}).
1449 ///
1450 /// \pre The behavior is undefined unless `position` is an iterator in the range
1451 /// `[cbegin() .. cend()]` (both endpoints included).
1452 template <class... Args>
1453 iterator emplace(const_iterator position, Args&&... arguments);
1454#endif
1455
1456 /// Erase the first element from this deque.
1457 ///
1458 /// \pre The behavior is undefined if this deque is empty.
1460
1461 /// Erase the last element from this deque.
1462 ///
1463 /// \pre The behavior is undefined if this deque is empty.
1464 void pop_back();
1465
1466 /// Insert at the specified `position` in this deque a copy of the
1467 /// specified `value`, and return an iterator providing modifiable
1468 /// access to the newly inserted element. This method offers full
1469 /// guarantee of rollback in case an exception is thrown other than by
1470 /// the `VALUE_TYPE` copy constructor or assignment operator. This
1471 /// method requires that the (template parameter) `VALUE_TYPE` be
1472 /// `copy-insertable` into this deque (see {Requirements on `VALUE_TYPE`}).
1473 ///
1474 /// \pre The behavior is undefined unless `position` is an
1475 /// iterator in the range `[cbegin() .. cend()]` (both endpoints
1476 /// included).
1477 iterator insert(const_iterator position, const VALUE_TYPE& value);
1478
1479 /// Insert at the specified `position` in this deque the specified
1480 /// move-insertable `value`, and return an iterator providing modifiable
1481 /// access to the newly inserted element. `value` is left in a valid
1482 /// but unspecified state. If an exception is thrown (other than by the
1483 /// copy constructor, move constructor, assignment operator, or move
1484 /// assignment operator of `value_type`), this method has no effect.
1485 /// This method requires that the (template parameter) `VALUE_TYPE` be
1486 /// `move-insertable` into this deque (see {Requirements on `VALUE_TYPE`}).
1487 ///
1488 /// \pre The behavior is undefined unless `position` is an
1489 /// iterator in the range `[cbegin() .. cend()]` (both endpoints
1490 /// included).
1492 BloombergLP::bslmf::MovableRef<value_type> value);
1493
1494 /// Insert at the specified `position` in this deque the specified
1495 /// `numElements` copies of the specified `value`, and return an
1496 /// iterator providing modifiable access to the first element in the
1497 /// newly inserted sequence of elements. This method offers full
1498 /// guarantee of rollback in case an exception is thrown other than by
1499 /// the `VALUE_TYPE` copy constructor or assignment operator. This
1500 /// method requires that the (template parameter) `VALUE_TYPE` be
1501 /// `copy-insertable` into this deque (see {Requirements on `VALUE_TYPE`}).
1502 ///
1503 /// \pre The behavior is undefined unless `position` is an
1504 /// iterator in the range `[cbegin() .. cend()]` (both endpoints
1505 /// included).
1507 size_type numElements,
1508 const VALUE_TYPE& value);
1509
1510 /// Insert at the specified `position` in this deque the values in the
1511 /// range starting at the specified `first` and ending immediately
1512 /// before the specified `last` iterators of the (template parameter)
1513 /// type `INPUT_ITERATOR`, and return an iterator providing modifiable
1514 /// access to the first element in the newly inserted sequence of
1515 /// elements. This method offers full guarantee of rollback in case an
1516 /// exception is thrown other than by the `VALUE_TYPE` copy constructor
1517 /// or assignment operator. The (template parameter) type
1518 /// `INPUT_ITERATOR` shall meet the requirements of an input iterator
1519 /// defined in the C++11 standard [input.iterators] providing access to
1520 /// values of a type convertible to `value_type`, and `value_type` must
1521 /// be `emplace-constructible` from `*i` into this deque, where `i` is a
1522 /// dereferenceable iterator in the range `[first .. last)` (see {Requirements on `VALUE_TYPE`}).
1523 ///
1524 /// \pre The behavior is undefined unless
1525 /// `position` is an iterator in the range `[cbegin() .. cend()]` (both
1526 /// endpoints included), and `first` and `last` refer to a sequence of
1527 /// valid values where `first` is at a position at or before `last`.
1528 template <class INPUT_ITERATOR>
1530 INPUT_ITERATOR first,
1531 INPUT_ITERATOR last);
1532
1533#if defined(BSLS_COMPILERFEATURES_SUPPORT_GENERALIZED_INITIALIZERS)
1534 /// Insert at the specified `position` in this deque the value of each
1535 /// `value_type` object in the specified `values` initializer list, and
1536 /// return an iterator providing modifiable access to the first element
1537 /// in the newly inserted sequence of elements. This method offers full
1538 /// guarantee of rollback in case an exception is thrown other than by
1539 /// the `VALUE_TYPE` copy constructor or assignment operator. This
1540 /// method requires that the (template parameter) `VALUE_TYPE` be
1541 /// `copy-insertable` into this deque (see {Requirements on `VALUE_TYPE`}).
1542 ///
1543 /// \pre The behavior is undefined unless `position` is an
1544 /// iterator in the range `[cbegin() .. cend()]` (both endpoints
1545 /// included).
1546 iterator insert(const_iterator position,
1547 std::initializer_list<value_type> values);
1548#endif
1549
1550 /// Insert at the specified `position` in this object the elements of the specified `range`.
1551 ///
1552 /// \note Note that `range` must meet the requirements of an
1553 /// input range and the values from `range` must have a type matching or
1554 /// convertible to (template parameter) `VALUE_TYPE`.
1555 template <class t_RANGE>
1557 iterator insert_range(const_iterator position,
1558 BSLS_COMPILERFEATURES_FORWARD_REF(t_RANGE) range);
1559
1560 /// Remove from this deque the element at the specified `position`, and
1561 /// return an iterator providing modifiable access to the element
1562 /// immediately following the removed element, or the position returned
1563 /// by the method `end` if the removed element was the last in the sequence.
1564 ///
1565 /// \pre The behavior is undefined unless `position` is an
1566 /// iterator in the range `[cbegin() .. cend())`.
1568
1569 /// Remove from this deque the sequence of elements starting at the
1570 /// specified `first` position and ending before the specified `last`
1571 /// position, and return an iterator providing modifiable access to the
1572 /// element immediately following the last removed element, or the
1573 /// position returned by the method `end` if the removed elements were last in the sequence.
1574 ///
1575 /// \pre The behavior is undefined unless `first` is
1576 /// an iterator in the range `[cbegin() .. cend()]` (both endpoints
1577 /// included) and `last` is an iterator in the range
1578 /// `[first .. cend()]` (both endpoints included).
1580
1581 /// Exchange the value of this object with that of the specified `other`
1582 /// object; also exchange the allocator of this object with that of
1583 /// `other` if the (template parameter) type `ALLOCATOR` has the
1584 /// @ref propagate_on_container_swap trait, and do not modify either
1585 /// allocator otherwise. This method provides the no-throw
1586 /// exception-safety guarantee. This operation has `O[1]` complexity if
1587 /// either this object was created with the same allocator as `other` or
1588 /// `ALLOCATOR` has the @ref propagate_on_container_swap trait; otherwise,
1589 /// it has `O[n + m]` complexity, where `n` and `m` are the number of elements in this object and `other`, respectively.
1590 ///
1591 /// \note Note that this
1592 /// method`s support for swapping objects created with different
1593 /// allocators when `ALLOCATOR` does not have the
1594 /// @ref propagate_on_container_swap trait is a departure from the
1595 /// C++ Standard.
1596 void swap(deque<VALUE_TYPE, ALLOCATOR>& other)
1598 AllocatorTraits::is_always_equal::value);
1599
1600 /// Remove all elements from this deque making its size 0.
1601 ///
1602 /// \note Note that although this deque is empty after this method returns, it preserves
1603 /// the same capacity it had before the method was called.
1605
1606 // ACCESSORS
1607
1608 // *** construct/copy/destroy ***
1609
1610 /// Return the allocator used by this deque to supply memory.
1612
1613 /// Return the maximum possible size of this deque.
1614 /// \note Note that this is a
1615 /// theoretical maximum (such as the maximum value that can be held by
1616 /// `size_type`). Also note that any request to create or enlarge a
1617 /// deque to a size greater than `max_size()` is guaranteed to raise a
1618 /// `bsl::length_error` exception.
1620};
1621
1622#ifdef BSLS_COMPILERFEATURES_SUPPORT_CTAD
1623// CLASS TEMPLATE DEDUCTION GUIDES
1624
1625/// Deduce the template parameter `VALUE` from the corresponding parameter
1626/// supplied to the constructor of `deque`. This deduction guide does not
1627/// participate unless the supplied allocator is convertible to
1628/// `bsl::allocator<VALUE>`.
1629template <
1630 class SIZE_TYPE,
1631 class VALUE,
1632 class ALLOC,
1633 class DEFAULT_ALLOCATOR = bsl::allocator<VALUE>,
1634 class = bsl::enable_if_t<
1635 bsl::is_convertible_v<
1636 SIZE_TYPE,
1638 class = bsl::enable_if_t<bsl::is_convertible_v<ALLOC *, DEFAULT_ALLOCATOR>>
1639 >
1640deque(SIZE_TYPE, VALUE, ALLOC *) -> deque<VALUE>;
1641
1642/// Deduce the template parameter `VALUE` from the `value_type` of the
1643/// iterators supplied to the constructor of `deque`.
1644template <
1645 class INPUT_ITERATOR,
1646 class VALUE =
1647 typename BloombergLP::bslstl::IteratorUtil::IterVal_t<INPUT_ITERATOR>
1648 >
1649deque(INPUT_ITERATOR, INPUT_ITERATOR) -> deque<VALUE>;
1650
1651/// Deduce the template parameter `VALUE` from the `value_type` of the
1652/// iterators supplied to the constructor of `deque`. This deduction guide
1653/// does not participate unless the supplied allocator meets the
1654/// requirements of a standard allocator.
1655template<
1656 class INPUT_ITERATOR,
1657 class ALLOCATOR,
1658 class VALUE =
1659 typename BloombergLP::bslstl::IteratorUtil::IterVal_t<INPUT_ITERATOR>,
1660 class = bsl::enable_if_t<bsl::IsStdAllocator_v<ALLOCATOR>>>
1661deque(INPUT_ITERATOR, INPUT_ITERATOR, ALLOCATOR) -> deque<VALUE, ALLOCATOR>;
1662
1663/// Deduce the template parameter `VALUE` from the `value_type` of the
1664/// iterators supplied to the constructor of `deque`. This deduction guide
1665/// does not participate unless the supplied allocator is convertible to
1666/// `bsl::allocator<VALUE>`.
1667template<
1668 class INPUT_ITERATOR,
1669 class ALLOC,
1670 class VALUE =
1671 typename BloombergLP::bslstl::IteratorUtil::IterVal_t<INPUT_ITERATOR>,
1672 class DEFAULT_ALLOCATOR = bsl::allocator<VALUE>,
1673 class = bsl::enable_if_t<bsl::is_convertible_v<ALLOC *, DEFAULT_ALLOCATOR>>
1674 >
1675deque(INPUT_ITERATOR, INPUT_ITERATOR, ALLOC *)
1676-> deque<VALUE>;
1677
1678/// Deduce the template parameter `VALUE` from the `value_type` of the
1679/// initializer_list supplied to the constructor of `deque`. This deduction
1680/// guide does not participate unless the supplied allocator is convertible
1681/// to `bsl::allocator<VALUE>`.
1682template<
1683 class VALUE,
1684 class ALLOC,
1685 class DEFAULT_ALLOCATOR = bsl::allocator<VALUE>,
1686 class = bsl::enable_if_t<bsl::is_convertible_v<ALLOC *, DEFAULT_ALLOCATOR>>
1687 >
1688deque(std::initializer_list<VALUE>, ALLOC *)
1689-> deque<VALUE>;
1690
1691#if defined(BSLS_LIBRARYFEATURES_HAS_CPP20_CONCEPTS) \
1692 && defined(BSLS_LIBRARYFEATURES_HAS_CPP20_RANGES)
1693/// Deduce the template parameters `VALUE_TYPE` and `ALLOCATOR` from the
1694/// parameters supplied to the constructor of `deque`.
1695template <ranges::input_range t_RANGE,
1696 class t_ALLOCATOR =
1698deque(from_range_t, t_RANGE&&, t_ALLOCATOR = t_ALLOCATOR())
1700#endif
1701#endif
1702
1703// FREE OPERATORS
1704
1705/// Return `true` if the specified `lhs` and `rhs` objects have the same
1706/// value, and `false` otherwise. Two `deque` objects `lhs` and `rhs` have
1707/// the same value if they have the same number of elements, and each
1708/// element in the ordered sequence of elements of `lhs` has the same value
1709/// as the corresponding element in the ordered sequence of elements of
1710/// `rhs`. This method requires that the (template parameter) type
1711/// `VALUE_TYPE` be `equality-comparable` (see {Requirements on
1712/// `VALUE_TYPE`}).
1713template <class VALUE_TYPE, class ALLOCATOR>
1714bool operator==(const deque<VALUE_TYPE, ALLOCATOR>& lhs,
1716
1717#ifndef BSLS_COMPILERFEATURES_SUPPORT_THREE_WAY_COMPARISON
1718/// Return `true` if the specified `lhs` and `rhs` objects do not have the
1719/// same value, and `false` otherwise. Two `deque` objects `lhs` and `rhs`
1720/// do not have the same value if they do not have the same number of
1721/// elements, or some element in the ordered sequence of elements of `lhs`
1722/// does not have the same value as the corresponding element in the ordered
1723/// sequence of elements of `rhs`. This method requires that the (template
1724/// parameter) type `VALUE_TYPE` be `equality-comparable` (see {Requirements
1725/// on `VALUE_TYPE`}).
1726template <class VALUE_TYPE, class ALLOCATOR>
1727bool operator!=(const deque<VALUE_TYPE, ALLOCATOR>& lhs,
1729#endif
1730
1731#ifdef BSLALG_SYNTHTHREEWAYUTIL_AVAILABLE
1732
1733/// Perform a lexicographic three-way comparison of the specified `lhs` and
1734/// the specified `rhs` containers by using the comparison operators of
1735/// `VALUE_TYPE` on each element; return the result of that comparison.
1736template <class VALUE_TYPE, class ALLOCATOR>
1737BloombergLP::bslalg::SynthThreeWayUtil::Result<VALUE_TYPE> operator<=>(
1740
1741#else
1742
1743/// Return `true` if the value of the specified `lhs` deque is
1744/// lexicographically less than that of the specified `rhs` deque, and
1745/// `false` otherwise. Given iterators `i` and `j` over the respective
1746/// sequences `[lhs.begin() .. lhs.end())` and `[rhs.begin() .. rhs.end())`,
1747/// the value of deque `lhs` is lexicographically less than that of deque
1748/// `rhs` if `true == *i < *j` for the first pair of corresponding iterator
1749/// positions where `*i < *j` and `*j < *i` are not both `false`. If no
1750/// such corresponding iterator position exists, the value of `lhs` is
1751/// lexicographically less than that of `rhs` if `lhs.size() < rhs.size()`.
1752/// This method requires that `operator<`, inducing a total order, be
1753/// defined for `value_type`.
1754template <class VALUE_TYPE, class ALLOCATOR>
1755bool operator<(const deque<VALUE_TYPE, ALLOCATOR>& lhs,
1757
1758/// Return `true` if the value of the specified `lhs` deque is
1759/// lexicographically greater than that of the specified `rhs` deque, and
1760/// `false` otherwise. The value of deque `lhs` is lexicographically
1761/// greater than that of deque `rhs` if `rhs` is lexicographically less than
1762/// `lhs` (see `operator<`). This method requires that `operator<`, inducing a total order, be defined for `value_type`.
1763///
1764/// \note Note that this
1765/// operator returns `rhs < lhs`.
1766template <class VALUE_TYPE, class ALLOCATOR>
1767bool operator>(const deque<VALUE_TYPE, ALLOCATOR>& lhs,
1769
1770/// Return `true` if the value of the specified `lhs` deque is
1771/// lexicographically less than or equal to that of the specified `rhs`
1772/// deque, and `false` otherwise. The value of deque `lhs` is
1773/// lexicographically less than or equal to that of deque `rhs` if `rhs` is
1774/// not lexicographically less than `lhs` (see `operator<`). This method
1775/// requires that `operator<`, inducing a total order, be defined for `value_type`.
1776///
1777/// \note Note that this operator returns `!(rhs < lhs)`.
1778template <class VALUE_TYPE, class ALLOCATOR>
1779bool operator<=(const deque<VALUE_TYPE, ALLOCATOR>& lhs,
1781
1782/// Return `true` if the value of the specified `lhs` deque is
1783/// lexicographically greater than or equal to that of the specified `rhs`
1784/// deque, and `false` otherwise. The value of deque `lhs` is
1785/// lexicographically greater than or equal to that of deque `rhs` if `lhs`
1786/// is not lexicographically less than `rhs` (see `operator<`). This method
1787/// requires that `operator<`, inducing a total order, be defined for `value_type`.
1788///
1789/// \note Note that this operator returns `!(lhs < rhs)`.
1790template <class VALUE_TYPE, class ALLOCATOR>
1791bool operator>=(const deque<VALUE_TYPE, ALLOCATOR>& lhs,
1793
1794#endif // BSLALG_SYNTHTHREEWAYUTIL_AVAILABLE
1795
1796// FREE FUNCTIONS
1797
1798/// Erase all the elements in the specified deque `deq` that compare equal
1799/// to the specified `value`. Return the number of elements erased.
1800template <class VALUE_TYPE, class ALLOCATOR, class BDE_OTHER_TYPE>
1802erase(deque<VALUE_TYPE, ALLOCATOR>& deq, const BDE_OTHER_TYPE& value);
1803
1804/// Erase all the elements in the specified deque `deq` that satisfy the
1805/// specified predicate `predicate`. Return the number of elements erased.
1806template <class VALUE_TYPE, class ALLOCATOR, class PREDICATE>
1808erase_if(deque<VALUE_TYPE, ALLOCATOR>& deq, PREDICATE predicate);
1809
1810/// Exchange the value of the specified `a` object with that of the
1811/// specified `b` object; also exchange the allocator of `a` with that of
1812/// `b` if the (template parameter) type `ALLOCATOR` has the
1813/// @ref propagate_on_container_swap trait, and do not modify either allocator
1814/// otherwise. This function provides the no-throw exception-safety
1815/// guarantee. This operation has `O[1]` complexity if either `a` was
1816/// created with the same allocator as `b` or `ALLOCATOR` has the
1817/// @ref propagate_on_container_swap trait; otherwise, it has `O[n + m]`
1818/// complexity, where `n` and `m` are the number of elements in `a` and `b`, respectively.
1819///
1820/// \note Note that this function`s support for swapping objects
1821/// created with different allocators when `ALLOCATOR` does not have the
1822/// @ref propagate_on_container_swap trait is a departure from the C++
1823/// Standard.
1824template <class VALUE_TYPE, class ALLOCATOR>
1827 a.swap(b)));
1828
1829 // ========================
1830 // class Deque_BlockCreator
1831 // ========================
1832
1833/// This class allocates blocks at the front or back of a deque and
1834/// tentatively adds them to the deque. It also keeps track of how many of
1835/// the newly allocated blocks have actually been used by the deque. The
1836/// destructor automatically frees any unused blocks (e.g., in case an
1837/// exception is thrown).
1838///
1839/// See @ref bslstl_deque
1840template <class VALUE_TYPE, class ALLOCATOR>
1842
1843 // PRIVATE TYPES
1844 enum {
1846 };
1847
1848 typedef BloombergLP::bslalg::DequeImpUtil<VALUE_TYPE,
1849 BLOCK_LENGTH> Imp;
1850 typedef typename Imp::Block Block;
1851 typedef typename Imp::BlockPtr BlockPtr;
1852 typedef std::size_t size_type;
1853
1854 // DATA
1856 BlockPtr *d_boundary_p;
1857
1858 private:
1859 // NOT IMPLEMENTED
1861 Deque_BlockCreator& operator=(const Deque_BlockCreator&);
1862
1863 public:
1864 // CREATORS
1865
1866 /// Construct a block allocator for the specified `deque`.
1867 explicit
1869
1870 /// Free any blocks that have been allocated by this allocator but have
1871 /// not yet been used by the deque.
1873
1874 // MANIPULATORS
1875
1876 /// Allocate the specified `n` blocks at the front of the block array.
1877 /// This method invalidates all iterators except `d_deque_p->d_start`
1878 /// and `d_deque_p->d_finish`.
1879 void insertAtFront(size_type n);
1880
1881 /// Allocate the specified `n` blocks at the back of the block array.
1882 /// This method invalidates all iterators except `d_deque_p->d_start`
1883 /// and `d_deque_p->d_finish`.
1884 void insertAtBack(size_type n);
1885
1886 /// Make room for the specified `numNewBlocks` pointers in the blocks
1887 /// array. If the specified `atFront` is `true`, then make room at the
1888 /// front of the array, else make room at the back of the array. Return
1889 /// a pointer to the insertion point, i.e., the point where new blocks
1890 /// can be stored into the array, working backwards if `atFront` is
1891 /// `true`, or working forwards if `atFront` is `false`. This method
1892 /// invalidates all iterators and updates `d_deque_p->d_start` and
1893 /// `d_deque_p->d_finish`.
1894 BlockPtr *reserveBlockSlots(size_type numNewBlocks, bool atFront);
1895
1896 /// Relinquish control over any allocated blocks. The destructor will
1897 /// do nothing following a call to this method.
1898 void release();
1899};
1900
1901 // ========================
1902 // class Deque_BlockProctor
1903 // ========================
1904
1905/// This class implements a proctor that, upon destruction and unless its
1906/// `release` method has previously been invoked, deallocates empty blocks
1907/// at one end (i.e., front or back) of a proctored deque. The end at which
1908/// empty blocks are to be proctored is indicated by a flag supplied at
1909/// construction. See `emplace` for a use case.
1910///
1911/// See @ref bslstl_deque
1912template <class VALUE_TYPE, class ALLOCATOR>
1914
1915 // PRIVATE TYPES
1916 enum {
1918 };
1919
1920 typedef BloombergLP::bslalg::DequeImpUtil<VALUE_TYPE,
1921 BLOCK_LENGTH> Imp;
1922
1923 typedef typename Imp::BlockPtr BlockPtr;
1924
1925 // DATA
1926 deque<VALUE_TYPE, ALLOCATOR> *d_deque_p; // proctored deque
1927
1928 BlockPtr *d_boundary_p; // boundary of proctored
1929 // blocks
1930
1931 bool d_atFront; // if 'true', proctor blocks
1932 // at the front of the deque;
1933 // otherwise, proctor blocks
1934 // at the block
1935
1936 private:
1937 // NOT IMPLEMENTED
1939 Deque_BlockProctor& operator=(const Deque_BlockProctor&);
1940
1941 public:
1942 // CREATORS
1943
1944 /// Create a block proctor object to proctor blocks at one end (i.e.,
1945 /// front or back) of the specified `deque` as indicated by the
1946 /// specified `atFront` flag. If `atFront` is `true`, blocks at the
1947 /// front of `deque` are proctored; otherwise, blocks at the back of
1948 /// `deque` are proctored.
1950
1951 /// Destroy this block proctor, and deallocate empty blocks at the back
1952 /// of the proctored deque as indicated by the `atFront` flag supplied
1953 /// at construction. If no deque is currently being managed, this
1954 /// method has no effect.
1956
1957 // MANIPULATORS
1958
1959 /// Release from management the deque currently managed by this proctor.
1960 /// If no deque is currently being managed, this method has no effect.
1961 void release();
1962};
1963
1964 // ======================
1965 // class Deque_ClearGuard
1966 // ======================
1967
1968/// This class provides a proctor which, at destruction, calls `clear` on
1969/// the deque supplied at construction, unless the guard has been released
1970/// prior.
1971///
1972/// See @ref bslstl_deque
1973template <class VALUE_TYPE, class ALLOCATOR>
1975
1976 // PRIVATE TYPES
1977 typedef BloombergLP::bslalg::ContainerBase<ALLOCATOR> ContainerBase;
1978
1979 // DATA
1980 deque<VALUE_TYPE, ALLOCATOR> *d_deque_p; // proctored object
1981
1982 private:
1983 // NOT IMPLEMENTED
1985 Deque_ClearGuard& operator=(const Deque_ClearGuard&);
1986
1987 public:
1988 // CREATORS
1989
1990 /// Create a clear guard object to proctor the specified `deque`.
1991 explicit
1993
1994 /// Destroy this guard, and call `clear` on the deque supplied at
1995 /// construction, unless `release` has been called on this object.
1997
1998 // MANIPULATORS
1999
2000 /// Release from management the deque proctored by this object.
2001 void release();
2002};
2003
2004 // =================
2005 // class Deque_Guard
2006 // =================
2007
2008/// This class provides a proctor that maintains a count of the number of
2009/// elements constructed at the front or back of a deque, but not yet
2010/// committed to the deque's range of valid elements; if the count is
2011/// non-zero at destruction, the destructor destroys the elements in the
2012/// range `[d_deque_p->end() .. d_deque_p->end() + d_count)`, or the range
2013/// `[d_deque_p->begin() - d_count .. d_deque_p->begin())`, depending on
2014/// whether this proctor guards the back or front. This guard is used to
2015/// undo element constructors in the event of an exception. It is up to the
2016/// client code to increment the count whenever a new element is constructed
2017/// and to decrement the count whenever `d_start` or `d_finish` of the
2018/// guarded deque is moved to incorporate more elements.
2019///
2020/// See @ref bslstl_deque
2021template <class VALUE_TYPE, class ALLOCATOR>
2023
2024 // PRIVATE TYPES
2025 enum {
2027 };
2028
2029 typedef BloombergLP::bslalg::DequeIterator<VALUE_TYPE,
2030 BLOCK_LENGTH> IteratorImp;
2031 typedef BloombergLP::bslalg::DequePrimitives<VALUE_TYPE,
2032 BLOCK_LENGTH> DequePrimitives;
2033
2034 // DATA
2036 std::size_t d_count;
2037 bool d_isTail;
2038
2039 private:
2040 // NOT IMPLEMENTED
2041 Deque_Guard(const Deque_Guard&);
2042 Deque_Guard& operator=(const Deque_Guard&);
2043
2044 public:
2045 // CREATORS
2046
2047 /// Initializes object to guard 0 items from the specified `deque`.
2048 /// This guards either the tail or the head, as determined by the
2049 /// specified `isTail` boolean.
2051
2052 /// Call the (template parameter) `VALUE_TYPE` destructor on objects in
2053 /// the range `[d.end() .. d.end() + count())` if `isTail` was specified
2054 /// as `true` during construction, or
2055 /// `[d.start() - count() .. d.start()]` if `isTail` was specified as
2056 /// `false` during construction, where `d` is the deque used to
2057 /// construct this guard.
2058 ~Deque_Guard();
2059
2060 // MANIPULATORS
2061
2062 /// Increment the count of this guard, and return the new count.
2063 std::size_t operator++();
2064
2065 /// Decrement the count of this guard, and return the new count.
2066 std::size_t operator--();
2067
2068 /// Set the count of this guard to 0.
2069 /// \note Note that this guard's destructor
2070 /// will do nothing if count is not incremented again after this call.
2071 void release();
2072
2073 // ACCESSORS
2074
2075 /// Return the current count maintained by this guard.
2076 std::size_t count() const BSLS_KEYWORD_NOEXCEPT;
2077
2078 /// Return a pointer after the first item in the guarded range.
2079 IteratorImp begin() const BSLS_KEYWORD_NOEXCEPT;
2080
2081 /// Return a pointer after the last item in the guarded range.
2082 IteratorImp end() const BSLS_KEYWORD_NOEXCEPT;
2083};
2084
2085// ============================================================================
2086// TEMPLATE AND INLINE FUNCTION DEFINITIONS
2087// ============================================================================
2088
2089// See IMPLEMENTATION NOTES in the .cpp before modifying anything below.
2090
2091 // ----------------
2092 // class Deque_Base
2093 // ----------------
2094
2095// MANIPULATORS
2096template <class VALUE_TYPE>
2097inline
2103
2104template <class VALUE_TYPE>
2105inline
2111
2112template <class VALUE_TYPE>
2113inline
2119
2120template <class VALUE_TYPE>
2121inline
2127
2128template <class VALUE_TYPE>
2129inline
2132{
2133 BSLS_ASSERT_SAFE(position < size());
2134
2135 return *(begin() + position);
2136}
2137
2138template <class VALUE_TYPE>
2141{
2142 if (BSLS_PERFORMANCEHINT_PREDICT_UNLIKELY(position >= size())) {
2144
2145 BloombergLP::bslstl::StdExceptUtil::throwOutOfRange(
2146 "deque<...>::at(n): invalid position");
2147 }
2148 return *(begin() + position);
2149}
2150
2151template <class VALUE_TYPE>
2152inline
2155{
2157
2158 return *d_start;
2159}
2160
2161template <class VALUE_TYPE>
2162inline
2165{
2167
2168 IteratorImp backIterator = d_finish;
2169 --backIterator;
2170 return *backIterator;
2171}
2172
2173// ACCESSORS
2174template <class VALUE_TYPE>
2175inline
2181
2182template <class VALUE_TYPE>
2183inline
2189
2190template <class VALUE_TYPE>
2191inline
2197
2198template <class VALUE_TYPE>
2199inline
2205
2206template <class VALUE_TYPE>
2207inline
2213
2214template <class VALUE_TYPE>
2215inline
2221
2222template <class VALUE_TYPE>
2223inline
2229
2230template <class VALUE_TYPE>
2231inline
2237
2238template <class VALUE_TYPE>
2239inline
2245
2246template <class VALUE_TYPE>
2249{
2250 // 'allocateBlockPtrs', which creates the 'd_blocks_p' array,
2251 // does not, in its contract, guarantee to initialize the array to 0.
2252 // Since we read these values, we have to make sure they're initialized to
2253 // avoid purify 'read before write' errors. Note that we initialize them
2254 // to null in which case they are not valid pointers, but we never
2255 // dereference them, and the pointer arithmetic we do on them will still
2256 // work.
2257
2258 if (d_start.blockPtr() > d_blocks_p) {
2259 d_blocks_p[0] = 0;
2260 }
2261 if (d_finish.blockPtr() < d_blocks_p + d_blocksLength - 1) {
2262 d_blocks_p[d_blocksLength - 1] = 0;
2263 }
2264
2265 const IteratorImp first(d_blocks_p);
2266
2267 // 'last' points to the empty slot at the end of the last block in
2268 // 'd_blocks_p', which might not actually be there.
2269
2270 IteratorImp last(d_blocks_p + d_blocksLength - 1);
2271 last += BLOCK_LENGTH - 1;
2272
2273 BSLS_ASSERT_SAFE(!(d_start < first)); // 'IteratorImp' has no '>='
2274 BSLS_ASSERT_SAFE(!(last < d_finish));
2275
2276 const size_type frontCapacity = d_finish - first;
2277 const size_type backCapacity = last - d_start;
2278
2279 // Return the min (we are below 'bsl_algorithm.h', so we have to do it by
2280 // hand).
2281
2282 return frontCapacity < backCapacity ? frontCapacity : backCapacity;
2283}
2284
2285template <class VALUE_TYPE>
2286inline
2291
2292template <class VALUE_TYPE>
2293inline
2296{
2297 BSLS_ASSERT_SAFE(position < size());
2298
2299 return *(begin() + position);
2300}
2301
2302template <class VALUE_TYPE>
2305{
2306 if (BSLS_PERFORMANCEHINT_PREDICT_UNLIKELY(position >= size())) {
2308
2309 BloombergLP::bslstl::StdExceptUtil::throwOutOfRange(
2310 "const deque<...>::at(n): invalid position");
2311 }
2312 return *(begin() + position);
2313}
2314
2315template <class VALUE_TYPE>
2316inline
2319{
2321
2322 return *d_start;
2323}
2324
2325template <class VALUE_TYPE>
2326inline
2329{
2331
2332 IteratorImp backIterator = d_finish;
2333 --backIterator;
2334 return *backIterator;
2335}
2336
2337 // -----------
2338 // class deque
2339 // -----------
2340
2341// PRIVATE CREATORS
2342template <class VALUE_TYPE, class ALLOCATOR>
2343inline
2344deque<VALUE_TYPE, ALLOCATOR>::deque(RawInit, const ALLOCATOR& allocator)
2345: Deque_Base<VALUE_TYPE>()
2346, ContainerBase(allocator)
2347{
2348 this->d_blocks_p = 0;
2349}
2350
2351// PRIVATE MANIPULATORS
2352template <class VALUE_TYPE, class ALLOCATOR>
2353inline
2354typename deque<VALUE_TYPE, ALLOCATOR>::Block *
2355deque<VALUE_TYPE, ALLOCATOR>::allocateBlock()
2356{
2357 return AllocatorUtil::allocateObject<Block>(this->allocatorRef());
2358}
2359
2360template <class VALUE_TYPE, class ALLOCATOR>
2361inline
2362typename deque<VALUE_TYPE, ALLOCATOR>::BlockPtr *
2363deque<VALUE_TYPE, ALLOCATOR>::allocateBlockPtrs(std::size_t n)
2364{
2365 return AllocatorUtil::allocateObject<BlockPtr>(this->allocatorRef(), n);
2366}
2367
2368template <class VALUE_TYPE, class ALLOCATOR>
2369inline
2370void deque<VALUE_TYPE, ALLOCATOR>::deallocateBlock(Block *p)
2371{
2372 AllocatorUtil::deallocateObject(this->allocatorRef(), p);
2373}
2374
2375template <class VALUE_TYPE, class ALLOCATOR>
2376inline
2377void
2378deque<VALUE_TYPE, ALLOCATOR>::deallocateBlockPtrs(BlockPtr *p, std::size_t n)
2379{
2380 AllocatorUtil::deallocateObject(this->allocatorRef(), p, n);
2381}
2382
2383template <class VALUE_TYPE, class ALLOCATOR>
2384template <class INPUT_ITERATOR, class SENTINEL>
2385inline
2386typename deque<VALUE_TYPE, ALLOCATOR>::size_type
2388 SENTINEL last)
2389{
2390 if (first == last) {
2391 return 0; // RETURN
2392 }
2393 typedef typename iterator_traits<INPUT_ITERATOR>::iterator_category Tag;
2394 return privateAppend(first, last, Tag());
2395}
2396
2397template <class VALUE_TYPE, class ALLOCATOR>
2398template <class INPUT_ITERATOR, class SENTINEL>
2401 INPUT_ITERATOR first,
2402 SENTINEL last,
2403 std::random_access_iterator_tag)
2404{
2405 BlockCreator newBlocks(this);
2406 Guard guard(this, true);
2407
2408 const size_type numElements =
2409 BloombergLP::bslstl::IteratorUtil::insertDistance(first, last);
2411 numElements > max_size() - this->size())) {
2413
2414 BloombergLP::bslstl::StdExceptUtil::throwLengthError(
2415 "deque<...>::insert(pos,n,v): deque too big");
2416 }
2417
2418 for ( ; first != last; ++first) {
2419 IteratorImp insertPoint = guard.end();
2420
2421 // There must be room for the iterator to be incremented. Allocate new
2422 // block now if necessary. We cannot wait until after the new element
2423 // is constructed or else we won't be able to increment the guard right
2424 // away and there will be a window where an exception will cause a
2425 // resource leak.
2426
2427 if (1 == insertPoint.remainingInBlock()) {
2428 newBlocks.insertAtBack(1);
2429 insertPoint = guard.end(); // 'insertAtBack(1)' invalidated
2430 // iterator
2431 }
2432 AllocatorTraits::construct(this->allocatorRef(),
2433 BSLS_UTIL_ADDRESSOF(*insertPoint),
2434 *first);
2435 ++guard;
2436 }
2437
2438 this->d_finish += guard.count();
2439
2440 guard.release();
2441 return numElements;
2442}
2443
2444template <class VALUE_TYPE, class ALLOCATOR>
2445template <class INPUT_ITERATOR, class SENTINEL>
2448 SENTINEL last,
2449 std::input_iterator_tag)
2450{
2451 BlockCreator newBlocks(this);
2452 Guard guard(this, true);
2453
2454 size_type numElements = 0;
2455 size_type maxNumElements = max_size() - this->size();
2456 for ( ; first != last; ++first) {
2457 ++numElements;
2459 numElements > maxNumElements)) {
2461
2462 BloombergLP::bslstl::StdExceptUtil::throwLengthError(
2463 "deque<...>::insert(pos,n,v): deque too big");
2464 }
2465 IteratorImp insertPoint = guard.end();
2466
2467 // There must be room for the iterator to be incremented. Allocate new
2468 // block now if necessary. We cannot wait until after the new element
2469 // is constructed or else we won't be able to increment the guard right
2470 // away and there will be a window where an exception will cause a
2471 // resource leak.
2472
2473 if (1 == insertPoint.remainingInBlock()) {
2474 newBlocks.insertAtBack(1);
2475 insertPoint = guard.end(); // 'insertAtBack(1)' invalidated
2476 // iterator
2477 }
2478
2479 AllocatorTraits::construct(this->allocatorRef(),
2480 BSLS_UTIL_ADDRESSOF(*insertPoint),
2481 *first);
2482 ++guard;
2483 }
2484
2485 this->d_finish += guard.count();
2486
2487 guard.release();
2488 return numElements;
2489}
2490
2491template <class VALUE_TYPE, class ALLOCATOR>
2493 size_type numElements)
2494{
2495 // Create new blocks at the back. In case an exception is thrown, any
2496 // unused blocks are returned to the allocator.
2497
2498 size_type numNewBlocks = (this->d_finish.offsetInBlock() + numElements) /
2499 BLOCK_LENGTH;
2500 BlockCreator newBlocks(this);
2501 newBlocks.insertAtBack(numNewBlocks);
2502 DequePrimitives::valueInititalizeN(&this->d_finish,
2503 this->d_finish,
2504 numElements,
2505 this->allocatorRef());
2506}
2507
2508template <class VALUE_TYPE, class ALLOCATOR>
2509void deque<VALUE_TYPE, ALLOCATOR>::privateAppendRaw(
2510 size_type numElements,
2511 const VALUE_TYPE& value)
2512{
2513 // Create new blocks at the back. In case an exception is thrown, any
2514 // unused blocks are returned to the allocator.
2515
2516 size_type numNewBlocks = (this->d_finish.offsetInBlock() + numElements) /
2517 BLOCK_LENGTH;
2518 BlockCreator newBlocks(this);
2519 newBlocks.insertAtBack(numNewBlocks);
2520
2521 DequePrimitives::uninitializedFillNBack(&this->d_finish,
2522 this->d_finish,
2523 numElements,
2524 value,
2525 this->allocatorRef());
2526}
2527
2528template <class VALUE_TYPE, class ALLOCATOR>
2529template <class t_ITERATOR, class t_SENTINEL>
2530void deque<VALUE_TYPE, ALLOCATOR>::privateAssign(t_ITERATOR first,
2531 t_SENTINEL last)
2532{
2533 typedef typename iterator_traits<t_ITERATOR>::iterator_category Tag;
2534
2535 // If an exception is thrown, clear the deque to provide standard behavior,
2536 // which is:
2537 // ```
2538 // erase(begin(), end());
2539 // insert(begin(), first, last);
2540 // ```
2541
2542 ClearGuard guard(this);
2543
2544 // Copy over existing elements.
2545
2546 IteratorImp i;
2547 for (i = this->d_start; !(i == this->d_finish) && first != last;
2548 ++i, ++first) {
2549 *i = *first;
2550 }
2551
2552 if (!(i == this->d_finish)) {
2553 // Erase elements past the last one copied.
2554
2555 erase(i, this->end());
2556 }
2557 else {
2558 // Still more elements to copy. Append them.
2559
2560 privateAppend(first, last, Tag());
2561 }
2562
2563 guard.release();
2564}
2565
2566template <class VALUE_TYPE, class ALLOCATOR>
2567void deque<VALUE_TYPE, ALLOCATOR>::privateInit(size_type numElements)
2568{
2569 size_type blocksLength = numElements / BLOCK_LENGTH + 1 +
2570 2 * Imp::BLOCK_ARRAY_PADDING;
2571
2572 // Allocate block pointer array.
2573
2574 this->d_blocks_p = this->allocateBlockPtrs(blocksLength);
2575
2576 this->d_blocksLength = blocksLength;
2577
2578 // Allocate the first block and store its pointer into the array. Leave a
2579 // little room at the front and back of the array for growth.
2580
2581 BlockPtr *firstBlockPtr = &this->d_blocks_p[Imp::BLOCK_ARRAY_PADDING];
2582 *firstBlockPtr = this->allocateBlock();
2583
2584 // Calculate the offset into the first block such that 'n' elements will
2585 // leave equal space at the front of the first block and at the end of the
2586 // last block, remembering that the last element of the last block cannot
2587 // be used. Centering the elements reduces the chance that either
2588 // 'push_back' or 'push_front' will need to allocate a new block. In case
2589 // of an odd number of unused elements, slight preference is given to
2590 // 'push_back' over 'push_front'.
2591
2592 const int offset = static_cast<int>(
2593 (BLOCK_LENGTH - 1 - numElements % BLOCK_LENGTH) / 2);
2594
2595 // Initialize the begin and end iterators.
2596
2597 this->d_start = this->d_finish = IteratorImp(
2598 firstBlockPtr,
2599 (*firstBlockPtr)->d_data + offset);
2600}
2601
2602template <class VALUE_TYPE, class ALLOCATOR>
2603template <class INTEGRAL_TYPE>
2604inline
2606 const_iterator position,
2607 INTEGRAL_TYPE numElements,
2608 INTEGRAL_TYPE value,
2609 BloombergLP::bslmf::MatchArithmeticType,
2610 BloombergLP::bslmf::Nil)
2611{
2612 insert(position,
2613 static_cast<size_type>(numElements),
2614 static_cast<VALUE_TYPE>(value));
2615}
2616
2617template <class VALUE_TYPE, class ALLOCATOR>
2618template <class INPUT_ITERATOR>
2620 const_iterator position,
2621 INPUT_ITERATOR first,
2622 INPUT_ITERATOR last,
2623 BloombergLP::bslmf::MatchAnyType,
2624 BloombergLP::bslmf::MatchAnyType)
2625{
2626 typedef typename iterator_traits<INPUT_ITERATOR>::iterator_category Tag;
2627
2628 if (first == last) {
2629 return; // RETURN
2630 }
2631
2632 if (position == this->cbegin()) {
2633 privatePrepend(first, last, Tag());
2634 return; // RETURN
2635 }
2636
2637 if (position == this->cend()) {
2638 privateAppend(first, last, Tag());
2639 return; // RETURN
2640 }
2641
2642 privateInsert(position, first, last, Tag());
2643}
2644
2645template <class VALUE_TYPE, class ALLOCATOR>
2646template <class INPUT_ITERATOR, class SENTINEL>
2647inline
2648void deque<VALUE_TYPE, ALLOCATOR>::privateInsert(const_iterator position,
2649 INPUT_ITERATOR first,
2650 SENTINEL last)
2651{
2652 if (first == last) {
2653 return; // RETURN
2654 }
2655
2656 typedef typename iterator_traits<INPUT_ITERATOR>::iterator_category Tag;
2657 if (position == this->cbegin()) {
2658 privatePrepend(first, last, Tag());
2659 }
2660 else if (position == this->cend()) {
2661 privateAppend(first, last, Tag());
2662 }
2663 else {
2664 privateInsert(position, first, last, Tag());
2665 }
2666}
2667
2668template <class VALUE_TYPE, class ALLOCATOR>
2669template <class INPUT_ITERATOR, class SENTINEL>
2670void deque<VALUE_TYPE, ALLOCATOR>::privateInsert(
2671 const_iterator position,
2672 INPUT_ITERATOR first,
2673 SENTINEL last,
2674 std::input_iterator_tag tag)
2675{
2676 BSLS_ASSERT(first != last);
2677
2678 iterator pos(position.imp());
2679 const size_type currentSize = this->size();
2680 const size_type posIdx = pos - this->begin();
2681
2682 deque temp(k_RAW_INIT, this->get_allocator());
2683 privateSplit(&temp, position.imp());
2684
2685 if (posIdx <= currentSize / 2) {
2687 static_cast<Base *>(this), static_cast<Base *>(&temp));
2688 privatePrepend(first, last, tag);
2689 privateJoinPrepend(&temp);
2690 }
2691 else {
2692 privateAppend(first, last, tag);
2693 privateJoinAppend(&temp);
2694 }
2695}
2696
2697template <class VALUE_TYPE, class ALLOCATOR>
2698void deque<VALUE_TYPE, ALLOCATOR>::privateSplit(
2699 deque<VALUE_TYPE, ALLOCATOR> *other,
2700 IteratorImp pos)
2701{
2702 // BEFORE:
2703 //..
2704 // this->d_start.valuePtr() -----------+
2705 // V
2706 // this->d_start.blockPtr() --> H -> __AAA
2707 // I -> AAAAA
2708 // pos.blockPtr() -> J -> BBBxx <- pos.valuePtr() (at 1st x)
2709 // K -> yyyyy
2710 // this->d_finish.blockPtr() -> L -> y____
2711 // ^
2712 // +- this->d_finish.valuePtr()
2713 //
2714 // AFTER:
2715 // this->d_start.valuePtr() -----------+
2716 // V
2717 // this->d_start.blockPtr() --> H -> __AAA
2718 // I -> AAAAA
2719 // this->d_finish.blockPtr() -> J -> BBB__
2720 // ^
2721 // +- this->d_finish.valuePtr()
2722 //
2723 // other->d_start.valuePtr() ------------+
2724 // V
2725 // other->d_start.blockPtr() --> M -> ___xx
2726 // K -> yyyyy
2727 // other->d_finish.blockPtr() -> L -> y____
2728 // ^
2729 // +- other->d_finish.valuePtr()
2730 //
2731 // assert(! other.d_blocks_p);
2732 //..
2733
2734 if (pos.blockPtr() == this->d_finish.blockPtr()) {
2735 // Split point is in last block. Just copy portion after the split to
2736 // new block in 'other'.
2737
2738 difference_type numAfter = this->d_finish.valuePtr() - pos.valuePtr();
2739 other->privateInit(numAfter);
2740 BloombergLP::bslalg::ArrayPrimitives::destructiveMove(
2741 other->d_start.valuePtr(),
2742 pos.valuePtr(),
2743 this->d_finish.valuePtr(),
2744 this->allocatorRef());
2745 other->d_finish += numAfter;
2746 this->d_finish = pos;
2747 return; // RETURN
2748 }
2749
2750 if (pos.blockPtr() == this->d_start.blockPtr()) {
2751 // Split point is in first block. Copy portion before the split to new
2752 // block in 'other' and swap.
2753
2754 difference_type numBefore = pos.valuePtr() - this->d_start.valuePtr();
2755 other->privateInit(numBefore);
2756 BloombergLP::bslalg::ArrayPrimitives::destructiveMove(
2757 other->d_start.valuePtr(),
2758 this->d_start.valuePtr(),
2759 pos.valuePtr(),
2760 this->allocatorRef());
2761 other->d_finish += numBefore;
2762 this->d_start = pos;
2764 static_cast<Base *>(this), static_cast<Base *>(other));
2765 return; // RETURN
2766 }
2767
2768 // Compute number of unsplit blocks to move.
2769
2770 difference_type numMoveBlocks = this->d_finish.blockPtr() - pos.blockPtr();
2771
2772 size_type otherBlocksLength = numMoveBlocks + 1 +
2773 2 * Imp::BLOCK_ARRAY_PADDING;
2774
2775 other->d_blocks_p = this->allocateBlockPtrs(otherBlocksLength);
2776 other->d_blocksLength = otherBlocksLength;
2777
2778 // Good time to allocate block for exception safety.
2779
2780 Block *newBlock = this->allocateBlock();
2781
2782 // The following chunk of code will never throw an exception. Move unsplit
2783 // blocks from 'this' to 'other', then adjust the iterators.
2784
2785 std::memcpy(other->d_blocks_p + 1 + Imp::BLOCK_ARRAY_PADDING,
2786 pos.blockPtr() + 1,
2787 sizeof(BlockPtr) * numMoveBlocks);
2788
2789 other->d_start = IteratorImp(&other->d_blocks_p[
2790 1 + Imp::BLOCK_ARRAY_PADDING]);
2791 other->d_finish = IteratorImp(other->d_start.blockPtr() +
2792 numMoveBlocks - 1,
2793 this->d_finish.valuePtr());
2794
2795 BlockPtr *newBlockPtr = pos.blockPtr() + 1;
2796 *newBlockPtr = newBlock;
2797 this->d_finish = IteratorImp(newBlockPtr);
2798
2799 // Current situation:
2800 //..
2801 // this->d_start.valuePtr() -----------+
2802 // V
2803 // this->d_start.blockPtr() --> H -> __AAA
2804 // I -> AAAAA
2805 // pos.blockPtr() -> J -> BBBxx <- pos.valuePtr() (1st x)
2806 // this->d_finish.blockPtr() -> M -> _____
2807 // / ^
2808 // newBlockPtr -+ +- this->d_finish.valuePtr()
2809 //
2810 // other->d_start.valuePtr() ---------+
2811 // V
2812 // other->d_start.blockPtr() --> K -> yyyyy
2813 // other->d_finish.blockPtr() -> L -> y____
2814 // ^
2815 // +- other->d_finish.valuePtr()
2816 //..
2817 // Now we split the block containing "BBBxx" into two blocks, with the "xx"
2818 // part going into '*newBlockPtr'. An exception can safely occur here
2819 // because the 'bslalg::ArrayPrimitives' functions are exception-neutral
2820 // and because all class invariants for both '*this' and 'other' hold going
2821 // in to this section.
2822
2823 size_type splitOffset = pos.offsetInBlock();
2824 if (splitOffset >= pos.remainingInBlock()) {
2825 // Move the tail part of the block into the new block.
2826
2827 value_type *splitValuePtr = newBlock->d_data + splitOffset;
2828 BloombergLP::bslalg::ArrayPrimitives::destructiveMove(
2829 splitValuePtr,
2830 pos.valuePtr(),
2831 pos.blockEnd(),
2832 this->allocatorRef());
2833 }
2834 else {
2835 // Move the head part of the block into the new block, then swap the
2836 // blocks within the 'd_blocks_p' array.
2837
2838 BloombergLP::bslalg::ArrayPrimitives::destructiveMove(
2839 newBlock->d_data,
2840 pos.blockBegin(),
2841 pos.valuePtr(),
2842 this->allocatorRef());
2843 *newBlockPtr = *pos.blockPtr();
2844 *pos.blockPtr() = newBlock;
2845 }
2846
2847 // Move block to 'other' and adjust the iterators. This will not throw.
2848
2849 this->d_finish = IteratorImp(&newBlockPtr[-1],
2850 newBlockPtr[-1]->d_data + splitOffset);
2851 other->d_start.previousBlock();
2852 *(other->d_start.blockPtr()) = *newBlockPtr;
2853 other->d_start = IteratorImp(other->d_start.blockPtr(),
2854 other->d_start.blockBegin() + splitOffset);
2855}
2856
2857template <class VALUE_TYPE, class ALLOCATOR>
2858inline
2859void deque<VALUE_TYPE, ALLOCATOR>::privateJoinPrepend(
2860 deque<VALUE_TYPE, ALLOCATOR> *other)
2861{
2862 privatePrepend(other->begin(),
2863 other->end(),
2864 std::random_access_iterator_tag());
2865
2866 // Make 'other' raw again, and free its resources.
2867
2868 deque<VALUE_TYPE, ALLOCATOR> temp(k_RAW_INIT, other->allocatorRef());
2869 Deque_Util::move(static_cast<Base *>(&temp), static_cast<Base *>(other));
2870}
2871
2872template <class VALUE_TYPE, class ALLOCATOR>
2873inline
2874void deque<VALUE_TYPE, ALLOCATOR>::privateJoinAppend(
2875 deque<VALUE_TYPE, ALLOCATOR> *other)
2876{
2877 privateAppend(other->begin(),
2878 other->end(),
2879 std::random_access_iterator_tag());
2880
2881 // Make 'other' raw again, and free its resources.
2882
2883 deque<VALUE_TYPE, ALLOCATOR> temp(k_RAW_INIT, other->allocatorRef());
2884 Deque_Util::move(static_cast<Base *>(&temp), static_cast<Base *>(other));
2885}
2886
2887template <class VALUE_TYPE, class ALLOCATOR>
2888template <class INPUT_ITERATOR, class SENTINEL>
2889void deque<VALUE_TYPE, ALLOCATOR>::privateInsert(
2890 const_iterator position,
2891 INPUT_ITERATOR first,
2892 SENTINEL last,
2893 std::random_access_iterator_tag tag)
2894{
2895 BSLS_ASSERT(first != last);
2896
2897 if (position == this->cbegin()) {
2898 privatePrepend(first, last, tag);
2899 return; // RETURN
2900 }
2901
2902 if (position == this->cend()) {
2903 privateAppend(first, last, tag);
2904 return; // RETURN
2905 }
2906
2907 const size_type currentSize = this->size();
2908 const size_type numElements =
2909 BloombergLP::bslstl::IteratorUtil::insertDistance(first, last);
2911 numElements > max_size() - currentSize)) {
2913
2914 BloombergLP::bslstl::StdExceptUtil::throwLengthError(
2915 "deque<...>::insert(pos,n,v): deque too big");
2916 }
2917
2918 iterator pos(position.imp());
2919 const size_type posIdx = position - this->cbegin();
2920 if (posIdx <= currentSize / 2) {
2921 // Create new blocks at the front. In case an exception is thrown, any
2922 // unused blocks are returned to the allocator.
2923
2924 size_type numNewBlocks = (this->d_start.remainingInBlock()
2925 + numElements - 1) / BLOCK_LENGTH;
2926 BlockCreator newBlocks(this);
2927 newBlocks.insertAtFront(numNewBlocks);
2928
2929 DequePrimitives::insertAndMoveToFront(&this->d_start,
2930 this->d_start,
2931 this->d_start + posIdx,
2932 first,
2933 last,
2934 numElements,
2935 this->allocatorRef());
2936 } else {
2937 // Create new blocks at front. In case an exception is thrown, any
2938 // unused blocks are returned to the allocator.
2939
2940 size_type numNewBlocks = (this->d_finish.offsetInBlock() + numElements)
2941 / BLOCK_LENGTH;
2942 BlockCreator newBlocks(this);
2943 newBlocks.insertAtBack(numNewBlocks);
2944
2945 DequePrimitives::insertAndMoveToBack(&this->d_finish,
2946 this->d_finish,
2947 this->d_start + posIdx,
2948 first,
2949 last,
2950 numElements,
2951 this->allocatorRef());
2952 }
2953}
2954
2955template <class VALUE_TYPE, class ALLOCATOR>
2956void deque<VALUE_TYPE, ALLOCATOR>::privatePrependRaw(
2957 size_type numElements,
2958 const VALUE_TYPE& value)
2959{
2960 // Create new blocks at front. In case an exception is thrown, any unused
2961 // blocks are returned to the allocator.
2962
2963 size_type numNewBlocks = (this->d_start.remainingInBlock() +
2964 numElements - 1) / BLOCK_LENGTH;
2965 BlockCreator newBlocks(this);
2966 newBlocks.insertAtFront(numNewBlocks);
2967
2968 DequePrimitives::uninitializedFillNFront(&this->d_start,
2969 this->d_start,
2970 numElements,
2971 value,
2972 this->allocatorRef());
2973}
2974
2975template <class VALUE_TYPE, class ALLOCATOR>
2976template <class INPUT_ITERATOR, class SENTINEL>
2977inline
2978typename deque<VALUE_TYPE, ALLOCATOR>::size_type
2980 SENTINEL last)
2981{
2982 if (first == last) {
2983 return 0; // RETURN
2984 }
2985 typedef typename iterator_traits<INPUT_ITERATOR>::iterator_category Tag;
2986 return privatePrepend(first, last, Tag());
2987}
2988
2989template <class VALUE_TYPE, class ALLOCATOR>
2990template <class INPUT_ITERATOR, class SENTINEL>
2993 SENTINEL last,
2994 std::input_iterator_tag tag)
2995{
2996 deque temp(k_RAW_INIT, this->get_allocator());
2997 temp.privateInit(this->size() + 1);
2998 size_type numElements = temp.privateAppend(first, last, tag);
2999
3000 // Check whether appending or prepending is more economical.
3001
3002 if (numElements > this->size()) {
3003 Deque_Util::swap((Base *)this, (Base *)&temp);
3004 privateJoinAppend(&temp);
3005 }
3006 else {
3007 privateJoinPrepend(&temp);
3008 }
3009
3010 return numElements;
3011}
3012
3013template <class VALUE_TYPE, class ALLOCATOR>
3014template <class INPUT_ITERATOR, class SENTINEL>
3017 INPUT_ITERATOR first,
3018 SENTINEL last,
3019 std::bidirectional_iterator_tag)
3020{
3021
3022 BlockCreator newBlocks(this);
3023 Guard guard(this, false);
3024
3025 size_type numElements = 0;
3026 size_type maxNumElements = max_size() - this->size();
3027 do {
3028 ++numElements;
3030 numElements > maxNumElements)) {
3032
3033 BloombergLP::bslstl::StdExceptUtil::throwLengthError(
3034 "deque<...>::insert(pos,n,v): deque too big");
3035 }
3036
3037 IteratorImp insertPoint = guard.begin();
3038
3039 // There must be room for the iterator to be decremented. Allocate new
3040 // block now if necessary, with same caveat as above.
3041
3042 if (insertPoint.valuePtr() == insertPoint.blockBegin()) {
3043 newBlocks.insertAtFront(1);
3044 insertPoint = guard.begin(); // 'insertAtFront' invalidates
3045 // 'insertPoint'
3046 }
3047 --insertPoint;
3048 AllocatorTraits::construct(this->allocatorRef(),
3049 BSLS_UTIL_ADDRESSOF(*insertPoint),
3050 *--last);
3051 ++guard;
3052 } while (first != last);
3053
3054 this->d_start -= guard.count();
3055 guard.release();
3056 return numElements;
3057}
3058
3059template <class VALUE_TYPE, class ALLOCATOR>
3060template <class INPUT_ITERATOR, class SENTINEL>
3063 INPUT_ITERATOR first,
3064 SENTINEL last,
3065 std::random_access_iterator_tag)
3066{
3067 BSLS_ASSERT_OPT((BloombergLP::bslstl::IteratorUtil
3068 ::canCalculateInsertDistance<INPUT_ITERATOR, SENTINEL>()));
3069 const size_type numElements =
3070 BloombergLP::bslstl::IteratorUtil::insertDistance(first, last);
3072 numElements > max_size() - this->size())) {
3074
3075 BloombergLP::bslstl::StdExceptUtil::throwLengthError(
3076 "deque<...>::insert(pos,n,v): deque too big");
3077 }
3078
3079 BlockCreator newBlocks(this);
3080 Guard guard(this, false);
3081
3082#ifdef BSLS_LIBRARYFEATURES_HAS_CPP20_RANGES
3083 INPUT_ITERATOR end;
3084 if constexpr (std::is_same_v<INPUT_ITERATOR, SENTINEL>) {
3085 end = last;
3086 }
3087 else {
3088 end = first + numElements;
3089 BSLS_ASSERT_SAFE(end == last);
3090 }
3091#else
3092 INPUT_ITERATOR end = last;
3093#endif
3094 do {
3095 IteratorImp insertPoint = guard.begin();
3096
3097 // There must be room for the iterator to be decremented. Allocate new
3098 // block now if necessary, with same caveat as above.
3099
3100 if (insertPoint.valuePtr() == insertPoint.blockBegin()) {
3101 newBlocks.insertAtFront(1);
3102 insertPoint = guard.begin(); // 'insertAtFront' invalidates
3103 // 'insertPoint'
3104 }
3105 --insertPoint;
3106 AllocatorTraits::construct(this->allocatorRef(),
3107 BSLS_UTIL_ADDRESSOF(*insertPoint),
3108 *--end);
3109 ++guard;
3110 } while (first != end);
3111
3112 this->d_start -= guard.count();
3113 guard.release();
3114 return numElements;
3115}
3116
3117// CREATORS
3118template <class VALUE_TYPE, class ALLOCATOR>
3120: Deque_Base<VALUE_TYPE>()
3121, ContainerBase(ALLOCATOR())
3122{
3123 deque temp(k_RAW_INIT, this->get_allocator());
3124 temp.privateInit(0);
3125 Deque_Util::move(static_cast<Base *>(this), static_cast<Base *>(&temp));
3126}
3127
3128template <class VALUE_TYPE, class ALLOCATOR>
3129deque<VALUE_TYPE, ALLOCATOR>::deque(const ALLOCATOR& basicAllocator)
3130: Deque_Base<VALUE_TYPE>()
3131, ContainerBase(basicAllocator)
3132{
3133 deque temp(k_RAW_INIT, this->get_allocator());
3134 temp.privateInit(0);
3135 Deque_Util::move(static_cast<Base *>(this), static_cast<Base *>(&temp));
3136}
3137
3138template <class VALUE_TYPE, class ALLOCATOR>
3140 const ALLOCATOR& basicAllocator)
3141: Deque_Base<VALUE_TYPE>()
3142, ContainerBase(basicAllocator)
3143{
3144 if (BSLS_PERFORMANCEHINT_PREDICT_UNLIKELY(numElements > max_size())) {
3146
3147 BloombergLP::bslstl::StdExceptUtil::throwLengthError(
3148 "deque<...>::deque(n): deque too big");
3149 }
3150 deque temp(k_RAW_INIT, this->get_allocator());
3151 temp.privateInit(numElements);
3152 temp.privateAppendDefaultInsertable(numElements);
3153 Deque_Util::move(static_cast<Base *>(this), static_cast<Base *>(&temp));
3154}
3155
3156template <class VALUE_TYPE, class ALLOCATOR>
3158 const VALUE_TYPE& value,
3159 const ALLOCATOR& basicAllocator)
3160: Deque_Base<VALUE_TYPE>()
3161, ContainerBase(basicAllocator)
3162{
3163 if (BSLS_PERFORMANCEHINT_PREDICT_UNLIKELY(numElements > max_size())) {
3165
3166 BloombergLP::bslstl::StdExceptUtil::throwLengthError(
3167 "deque<...>::deque(n,v): deque too big");
3168 }
3169 deque temp(k_RAW_INIT, this->get_allocator());
3170 temp.privateInit(numElements);
3171 temp.privateAppendRaw(numElements, value);
3172 Deque_Util::move(static_cast<Base *>(this), static_cast<Base *>(&temp));
3173}
3174
3175template <class VALUE_TYPE, class ALLOCATOR>
3176template <class INPUT_ITERATOR>
3178 INPUT_ITERATOR last,
3179 const ALLOCATOR& basicAllocator)
3180: Deque_Base<VALUE_TYPE>()
3181, ContainerBase(basicAllocator)
3182{
3183 deque temp(k_RAW_INIT, this->get_allocator());
3184 temp.privateInit(0);
3185 temp.insert(temp.begin(), first, last);
3186 Deque_Util::move(static_cast<Base *>(this), static_cast<Base *>(&temp));
3187}
3188
3189template <class VALUE_TYPE, class ALLOCATOR>
3190template <class t_RANGE>
3192deque<VALUE_TYPE, ALLOCATOR>::deque(
3193 from_range_t ,
3194 BSLS_COMPILERFEATURES_FORWARD_REF(t_RANGE) range,
3195 const ALLOCATOR& basicAllocator)
3196: Deque_Base<VALUE_TYPE>()
3197, ContainerBase(basicAllocator)
3198{
3199 deque temp(k_RAW_INIT, this->get_allocator());
3200 temp.privateInit(0);
3201 temp.append_range(BSLS_COMPILERFEATURES_FORWARD(t_RANGE, range));
3202 Deque_Util::move(static_cast<Base *>(this), static_cast<Base *>(&temp));
3203}
3204
3205template <class VALUE_TYPE, class ALLOCATOR>
3207: Deque_Base<VALUE_TYPE>()
3208, ContainerBase(AllocatorTraits::select_on_container_copy_construction(
3209 original.get_allocator()))
3210{
3211 deque temp(k_RAW_INIT, this->get_allocator());
3212 temp.privateInit(original.size());
3213 temp.privateAppend(original.begin(),
3214 original.end(),
3215 std::random_access_iterator_tag());
3216 Deque_Util::move(static_cast<Base *>(this), static_cast<Base *>(&temp));
3217}
3218
3219template <class VALUE_TYPE, class ALLOCATOR>
3221 const deque& original,
3222 const typename type_identity<ALLOCATOR>::type& basicAllocator)
3223: Deque_Base<VALUE_TYPE>()
3224, ContainerBase(basicAllocator)
3225{
3226 deque temp(k_RAW_INIT, this->get_allocator());
3227 temp.privateInit(original.size());
3228 temp.privateAppend(original.begin(),
3229 original.end(),
3230 std::random_access_iterator_tag());
3231 Deque_Util::move(static_cast<Base *>(this), static_cast<Base *>(&temp));
3232}
3233
3234template <class VALUE_TYPE, class ALLOCATOR>
3236 BloombergLP::bslmf::MovableRef<deque> original)
3237: Deque_Base<VALUE_TYPE>()
3238, ContainerBase(MoveUtil::access(original).get_allocator())
3239{
3240 deque temp(k_RAW_INIT, this->get_allocator());
3241 temp.privateInit(0);
3242 Deque_Util::move(static_cast<Base *>(this), static_cast<Base *>(&temp));
3243
3244 deque& lvalue = original;
3245 Deque_Util::swap(static_cast<Base *>(this), static_cast<Base *>(&lvalue));
3246}
3247
3248template <class VALUE_TYPE, class ALLOCATOR>
3250 BloombergLP::bslmf::MovableRef<deque> original,
3251 const typename type_identity<ALLOCATOR>::type& basicAllocator)
3252: Deque_Base<VALUE_TYPE>()
3253, ContainerBase(basicAllocator)
3254{
3255 deque temp(k_RAW_INIT, this->get_allocator());
3256 temp.privateInit(0);
3257
3258 deque& lvalue = original;
3259
3261 get_allocator() == lvalue.get_allocator())) {
3262 Deque_Util::move(static_cast<Base *>(this),
3263 static_cast<Base *>(&temp));
3264 Deque_Util::swap(static_cast<Base *>(this),
3265 static_cast<Base *>(&lvalue));
3266 }
3267 else {
3268 const size_type size = lvalue.size();
3269 temp.reserve(size);
3270 for (size_type pos = 0; pos < size; ++pos) {
3271 temp.push_back(MoveUtil::move(lvalue[pos]));
3272 }
3273 Deque_Util::move(static_cast<Base *>(this),
3274 static_cast<Base *>(&temp));
3275 }
3276}
3277
3278#if defined(BSLS_COMPILERFEATURES_SUPPORT_GENERALIZED_INITIALIZERS)
3279template <class VALUE_TYPE, class ALLOCATOR>
3280inline
3282 std::initializer_list<value_type> values,
3283 const ALLOCATOR& basicAllocator)
3284: deque(values.begin(), values.end(), basicAllocator)
3285{
3286}
3287#endif
3288
3289template <class VALUE_TYPE, class ALLOCATOR>
3291{
3292 if (0 == this->d_blocks_p) {
3293 // Nothing to do when destroying raw deques.
3294
3295 return; // RETURN
3296 }
3297
3298 if (0 != this->d_start.blockPtr()) {
3299 // Destroy all elements and deallocate all but one block.
3300 clear();
3301
3302 // Deallocate the remaining (empty) block.
3303 this->deallocateBlock(*this->d_start.blockPtr());
3304 }
3305
3306 // Deallocate the array of block pointers.
3307 this->deallocateBlockPtrs(this->d_blocks_p, this->d_blocksLength);
3308}
3309
3310// MANIPULATORS
3311template <class VALUE_TYPE, class ALLOCATOR>
3314{
3315 typedef typename
3317
3319 if (Propagate::value && get_allocator() != rhs.get_allocator()) {
3320 deque other(rhs, rhs.get_allocator());
3321
3322 Deque_Util::swap(static_cast<Base *>(this),
3323 static_cast<Base *>(&other));
3324 AllocatorUtil::swap(&this->allocatorRef(), &other.allocatorRef(),
3325 Propagate());
3326 }
3327 else {
3328 size_type origSize = this->size();
3329 size_type rhsSize = rhs.size();
3330 size_type minSize;
3331
3332 if (origSize > rhsSize) {
3333 // Make shorter by deleting excess elements.
3334
3335 minSize = rhsSize;
3336 erase(this->begin() + minSize, this->end());
3337 }
3338 else {
3339 // Make longer by appending new elements.
3340
3341 minSize = origSize;
3342 privateAppend(rhs.begin() + minSize,
3343 rhs.end(),
3344 std::random_access_iterator_tag());
3345 }
3346
3347 // Copy the smaller of the number of elements in 'rhs' and '*this'.
3348
3349 IteratorImp from = rhs.d_start;
3350 IteratorImp to = this->d_start;
3351 for (size_type i = 0; i < minSize; ++i) {
3352 *to = *from;
3353 ++to;
3354 ++from;
3355 }
3356 }
3357 }
3358
3359 return *this;
3360}
3361
3362template <class VALUE_TYPE, class ALLOCATOR>
3365 BloombergLP::bslmf::MovableRef<deque> rhs)
3367 AllocatorTraits::is_always_equal::value)
3368{
3369 deque& lvalue = rhs;
3370
3371 typedef typename
3372 AllocatorTraits::propagate_on_container_move_assignment Propagate;
3373 if (BSLS_PERFORMANCEHINT_PREDICT_LIKELY(this != &lvalue)) {
3374 if (get_allocator() == lvalue.get_allocator()) {
3375 Deque_Util::swap(static_cast<Base *>(this),
3376 static_cast<Base *>(&lvalue));
3377 }
3378 else if (Propagate::value) {
3379 deque other(MoveUtil::move(lvalue));
3380 Deque_Util::swap(static_cast<Base *>(this),
3381 static_cast<Base *>(&other));
3382 AllocatorUtil::swap(&this->allocatorRef(), &other.allocatorRef(),
3383 Propagate());
3384 }
3385 else {
3386 deque other(MoveUtil::move(lvalue), get_allocator());
3387 Deque_Util::swap(static_cast<Base *>(this),
3388 static_cast<Base *>(&other));
3389 }
3390 }
3391 return *this;
3392}
3393
3394#if defined(BSLS_COMPILERFEATURES_SUPPORT_GENERALIZED_INITIALIZERS)
3395template <class VALUE_TYPE, class ALLOCATOR>
3396inline
3397deque<VALUE_TYPE, ALLOCATOR>&
3399 std::initializer_list<value_type> values)
3400{
3401 assign(values.begin(), values.end());
3402 return *this;
3403}
3404#endif
3405
3406template <class VALUE_TYPE, class ALLOCATOR>
3407template <class INPUT_ITERATOR>
3409 INPUT_ITERATOR last)
3410{
3411 privateAssign(first, last);
3412}
3413
3414template <class VALUE_TYPE, class ALLOCATOR>
3416 const VALUE_TYPE& value)
3417{
3418 if (BSLS_PERFORMANCEHINT_PREDICT_UNLIKELY(numElements > max_size())) {
3420
3421 BloombergLP::bslstl::StdExceptUtil::throwLengthError(
3422 "deque<...>::assign(n,v): deque too big");
3423 }
3424
3425 // If an exception is thrown, clear the deque to provide standard behavior,
3426 // which is:
3427 //..
3428 // erase(begin(), end());
3429 // insert(begin(), first, last);
3430 //..
3431
3432 ClearGuard guard(this);
3433
3434 size_type origSize = this->size();
3435 size_type minSize;
3436
3437 if (numElements < origSize) {
3438 minSize = numElements;
3439 erase(this->begin() + numElements, this->end());
3440 }
3441 else {
3442 minSize = origSize;
3443 privateAppendRaw(numElements - origSize, value);
3444 }
3445
3446 IteratorImp to = this->d_start;
3447 for (size_type i = 0; i < minSize; ++i) {
3448 *to = value;
3449 ++to;
3450 }
3451
3452 guard.release();
3453}
3454
3455#if defined(BSLS_COMPILERFEATURES_SUPPORT_GENERALIZED_INITIALIZERS)
3456template <class VALUE_TYPE, class ALLOCATOR>
3457inline
3459 std::initializer_list<value_type> values)
3460{
3461 assign(values.begin(), values.end());
3462}
3463#endif
3464
3465template <class VALUE_TYPE, class ALLOCATOR>
3466template <class t_RANGE>
3468void deque<VALUE_TYPE, ALLOCATOR>::assign_range(
3469 BSLS_COMPILERFEATURES_FORWARD_REF(t_RANGE) range)
3470{
3471 privateAssign(ranges::begin(range), ranges::end(range));
3472}
3473
3474template <class VALUE_TYPE, class ALLOCATOR>
3476{
3477 // Make sure 'numElements' isn't high enough to make the calculations of
3478 // 'num(Front|Back)Blocks' overflow.
3479
3481 max_size() - (BLOCK_LENGTH - 1))) {
3483
3484 BloombergLP::bslstl::StdExceptUtil::throwLengthError(
3485 "deque<...>::reserve(n): deque too big");
3486 }
3487
3488 // 'allocateBlockPtrs', which creates the 'd_blocks_p' array, does
3489 // not, in its contract, guarantee to initialize the array to 0. Since we
3490 // read these values, we have to make sure they're initialized to avoid
3491 // purify 'read before write' errors. Note that we initialize them to 0,
3492 // making them invalid pointers, but we never dereference them, and the
3493 // pointer arithmetic we do on them will still work.
3494
3495 if (this->d_start.blockPtr() > this->d_blocks_p) {
3496 this->d_blocks_p[0] = 0;
3497 }
3498 if (this->d_finish.blockPtr() < this->d_blocks_p + this->d_blocksLength-1){
3499 this->d_blocks_p[this->d_blocksLength - 1] = 0;
3500 }
3501
3502 const IteratorImp first(this->d_blocks_p);
3503 IteratorImp last( this->d_blocks_p + this->d_blocksLength - 1);
3504 last += BLOCK_LENGTH - 1;
3505
3506 const size_type frontRoom = this->d_start - first;
3507 const size_type backRoom = last - this->d_finish;
3508
3509 size_type numFrontBlocks = numElements > frontRoom
3510 ? (numElements - frontRoom + BLOCK_LENGTH - 1) /
3511 BLOCK_LENGTH
3512 : 0;
3513 size_type numBackBlocks = numElements > backRoom
3514 ? (numElements - backRoom + BLOCK_LENGTH - 1) /
3515 BLOCK_LENGTH
3516 : 0;
3517
3518 if (0 == numFrontBlocks && 0 == numBackBlocks) {
3519 return; // RETURN
3520 }
3521
3522 // Make sure that if we throw, it's before we modify the deque.
3523
3524 size_type existingSpace = last - first;
3525 if (BSLS_PERFORMANCEHINT_PREDICT_UNLIKELY(numFrontBlocks >
3526 (max_size() - existingSpace) / BLOCK_LENGTH
3527 || (existingSpace += numFrontBlocks * BLOCK_LENGTH,
3528 numBackBlocks >
3529 (max_size() - existingSpace) / BLOCK_LENGTH))) {
3531
3532 BloombergLP::bslstl::StdExceptUtil::throwLengthError(
3533 "deque<...>::reserve(n): deque too big");
3534 }
3535
3536 // When 'numFrontBlocks' or 'numBackBlocks' are 0, the respective calls
3537 // will be no-ops.
3538
3539 BlockCreator newBlocks(this);
3540 newBlocks.reserveBlockSlots(numFrontBlocks, true);
3541 newBlocks.reserveBlockSlots(numBackBlocks, false);
3542}
3543
3544template <class VALUE_TYPE, class ALLOCATOR>
3546{
3547 if (BSLS_PERFORMANCEHINT_PREDICT_UNLIKELY(newSize > max_size())) {
3549
3550 BloombergLP::bslstl::StdExceptUtil::throwLengthError(
3551 "deque<...>::resize(n): deque too big");
3552 }
3553
3554 size_type origSize = this->size();
3555
3556 if (newSize <= origSize) {
3557 // Note that we do not use 'erase' here as 'erase' requires elements be
3558 // copy-insertable, while the standard does not require elements be
3559 // copy-insertable for this 'resize' overload.
3560
3561 IteratorImp oldEnd = this->d_finish;
3562 IteratorImp newEnd = this->d_start + newSize;
3563 DequePrimitives::destruct(newEnd, oldEnd, this->allocatorRef());
3564 // Deallocate blocks no longer used
3565 for (; oldEnd.blockPtr() != newEnd.blockPtr();
3566 oldEnd.previousBlock()) {
3567 this->deallocateBlock(*oldEnd.blockPtr());
3568 }
3569 this->d_finish = newEnd;
3570 }
3571 else {
3572 privateAppendDefaultInsertable(newSize - origSize);
3573 }
3574}
3575
3576template <class VALUE_TYPE, class ALLOCATOR>
3578 const VALUE_TYPE& value)
3579{
3580 if (BSLS_PERFORMANCEHINT_PREDICT_UNLIKELY(newSize > max_size())) {
3582
3583 BloombergLP::bslstl::StdExceptUtil::throwLengthError(
3584 "deque<...>::resize(n,v): deque too big");
3585 }
3586
3587 size_type origSize = this->size();
3588
3589 if (newSize <= origSize) {
3590 erase(this->begin() + newSize, this->end());
3591 }
3592 else {
3593 privateAppendRaw(newSize - origSize, value);
3594 }
3595}
3596
3597template <class VALUE_TYPE, class ALLOCATOR>
3599{
3600 // Minimize the length of 'd_blocks_p' without moving any elements. A more
3601 // complex algorithm is not justified. At most 'BLOCK_LENGTH' bytes are
3602 // wasted.
3603
3604 const size_type newBlocksLength =
3605 this->d_finish.blockPtr() - this->d_start.blockPtr() + 1;
3606
3607 if (newBlocksLength == this->d_blocksLength) {
3608 return; // RETURN
3609 }
3610
3611 const size_type offsetStart = this->d_start.offsetInBlock();
3612 const size_type offsetFinish = this->d_finish.offsetInBlock();
3613
3614 BlockPtr *newBlocks = this->allocateBlockPtrs(newBlocksLength);
3615
3616 std::memmove(newBlocks,
3617 this->d_start.blockPtr(),
3618 newBlocksLength * sizeof(BlockPtr));
3619
3620 this->deallocateBlockPtrs(this->d_blocks_p, this->d_blocksLength);
3621
3622 this->d_blocks_p = newBlocks;
3623 this->d_blocksLength = newBlocksLength;
3624
3625 this->d_start.setBlock(newBlocks);
3626 this->d_start += offsetStart;
3627
3628 this->d_finish.setBlock(newBlocks + newBlocksLength - 1);
3629 this->d_finish += offsetFinish;
3630}
3631
3632template <class VALUE_TYPE, class ALLOCATOR>
3633template <class t_RANGE>
3635void deque<VALUE_TYPE, ALLOCATOR>::append_range(
3636 BSLS_COMPILERFEATURES_FORWARD_REF(t_RANGE) range)
3637{
3638 privateAppend(ranges::begin(range), ranges::end(range));
3639}
3640
3641template <class VALUE_TYPE, class ALLOCATOR>
3642template <class t_RANGE>
3644void deque<VALUE_TYPE, ALLOCATOR>::prepend_range(
3645 BSLS_COMPILERFEATURES_FORWARD_REF(t_RANGE) range)
3646{
3647 privatePrepend(ranges::begin(range), ranges::end(range));
3648}
3649
3650template <class VALUE_TYPE, class ALLOCATOR>
3651void deque<VALUE_TYPE, ALLOCATOR>::push_front(const VALUE_TYPE& value)
3652{
3653 if (BSLS_PERFORMANCEHINT_PREDICT_UNLIKELY(this->size() >= max_size())) {
3655
3656 BloombergLP::bslstl::StdExceptUtil::throwLengthError(
3657 "deque<...>::push_front(v): deque too big");
3658 }
3659
3661 0 == this->d_start.offsetInBlock())) {
3663
3664 BlockCreator newBlocks(this);
3665 newBlocks.insertAtFront(1); // The deque's value is not modified.
3666
3667 AllocatorTraits::construct(
3668 this->allocatorRef(), (this->d_start - 1).valuePtr(), value);
3669
3670 --this->d_start;
3671 }
3672 else {
3673 // Since the offset is non-zero, it is safe to directly decrement the
3674 // pointer. This is much quicker than calling 'operator--'.
3675
3676 AllocatorTraits::construct(
3677 this->allocatorRef(), this->d_start.valuePtr() - 1, value);
3678 this->d_start.valuePtrDecrement();
3679 }
3680}
3681
3682template <class VALUE_TYPE, class ALLOCATOR>
3684 BloombergLP::bslmf::MovableRef<value_type> value)
3685{
3686 if (BSLS_PERFORMANCEHINT_PREDICT_UNLIKELY(this->size() >= max_size())) {
3688
3689 BloombergLP::bslstl::StdExceptUtil::throwLengthError(
3690 "deque<...>::push_front(v): deque too big");
3691 }
3692
3693 VALUE_TYPE& lvalue = value;
3694
3696 0 == this->d_start.offsetInBlock())) {
3698
3699 BlockCreator newBlocks(this);
3700 newBlocks.insertAtFront(1); // The deque's value is not modified.
3701
3702 AllocatorTraits::construct(this->allocatorRef(),
3703 (this->d_start - 1).valuePtr(),
3704 MoveUtil::move(lvalue));
3705 --this->d_start;
3706 }
3707 else {
3708 // Since the offset is non-zero, it is safe to directly decrement the
3709 // pointer. This is much quicker than calling 'operator--'.
3710
3711 AllocatorTraits::construct(this->allocatorRef(),
3712 this->d_start.valuePtr() - 1,
3713 MoveUtil::move(lvalue));
3714 this->d_start.valuePtrDecrement();
3715 }
3716}
3717
3718template <class VALUE_TYPE, class ALLOCATOR>
3719void deque<VALUE_TYPE, ALLOCATOR>::push_back(const VALUE_TYPE& value)
3720{
3721 if (BSLS_PERFORMANCEHINT_PREDICT_UNLIKELY(this->size() >= max_size())) {
3723
3724 BloombergLP::bslstl::StdExceptUtil::throwLengthError(
3725 "deque<...>::push_back(v): deque too big");
3726 }
3727
3729 1 < this->d_finish.remainingInBlock())) {
3730 AllocatorTraits::construct(
3731 this->allocatorRef(), this->d_finish.valuePtr(), value);
3732 this->d_finish.valuePtrIncrement();
3733 }
3734 else {
3736
3737 BlockCreator newBlocks(this);
3738 newBlocks.insertAtBack(1); // The deque's value is not modified.
3739
3740 AllocatorTraits::construct(
3741 this->allocatorRef(), this->d_finish.valuePtr(), value);
3742 this->d_finish.nextBlock();
3743 }
3744}
3745
3746template <class VALUE_TYPE, class ALLOCATOR>
3748 BloombergLP::bslmf::MovableRef<value_type> value)
3749{
3750 if (BSLS_PERFORMANCEHINT_PREDICT_UNLIKELY(this->size() >= max_size())) {
3752
3753 BloombergLP::bslstl::StdExceptUtil::throwLengthError(
3754 "deque<...>::push_back(v): deque too big");
3755 }
3756
3757 VALUE_TYPE& lvalue = value;
3758
3760 1 < this->d_finish.remainingInBlock())) {
3761 AllocatorTraits::construct(this->allocatorRef(),
3762 this->d_finish.valuePtr(),
3763 MoveUtil::move(lvalue));
3764 this->d_finish.valuePtrIncrement();
3765 }
3766 else {
3768
3769 BlockCreator newBlocks(this);
3770 newBlocks.insertAtBack(1); // The deque's value is not modified.
3771
3772 AllocatorTraits::construct(this->allocatorRef(),
3773 this->d_finish.valuePtr(),
3774 MoveUtil::move(lvalue));
3775 this->d_finish.nextBlock();
3776 }
3777}
3778
3779#if !BSLS_COMPILERFEATURES_SIMULATE_CPP11_FEATURES
3780template <class VALUE_TYPE, class ALLOCATOR>
3781template <class... Args>
3784{
3785 if (BSLS_PERFORMANCEHINT_PREDICT_UNLIKELY(this->size() >= max_size())) {
3787
3788 BloombergLP::bslstl::StdExceptUtil::throwLengthError(
3789 "deque<...>::emplace_front(args): deque too big");
3790 }
3791
3793 0 == this->d_start.offsetInBlock())) {
3795
3796 BlockCreator newBlocks(this);
3797 newBlocks.insertAtFront(1); // The deque's value is not modified.
3798
3799 AllocatorTraits::construct(
3800 this->allocatorRef(),
3801 (this->d_start - 1).valuePtr(),
3802 BSLS_COMPILERFEATURES_FORWARD(Args, arguments)...);
3803 --this->d_start;
3804 }
3805 else {
3806 // Since the offset is non-zero, it is safe to directly decrement the
3807 // pointer. This is much quicker than calling 'operator--'.
3808
3809 AllocatorTraits::construct(
3810 this->allocatorRef(),
3811 this->d_start.valuePtr() - 1,
3812 BSLS_COMPILERFEATURES_FORWARD(Args, arguments)...);
3813 this->d_start.valuePtrDecrement();
3814 }
3815 return *(this->d_start);
3816}
3817
3818template <class VALUE_TYPE, class ALLOCATOR>
3819template <class... Args>
3822{
3823 if (BSLS_PERFORMANCEHINT_PREDICT_UNLIKELY(this->size() >= max_size())) {
3825
3826 BloombergLP::bslstl::StdExceptUtil::throwLengthError(
3827 "deque<...>::emplace_back(args): deque too big");
3828 }
3829
3831 1 < this->d_finish.remainingInBlock())) {
3832 AllocatorTraits::construct(
3833 this->allocatorRef(),
3834 this->d_finish.valuePtr(),
3835 BSLS_COMPILERFEATURES_FORWARD(Args, arguments)...);
3836 this->d_finish.valuePtrIncrement();
3837 }
3838 else {
3840
3841 BlockCreator newBlocks(this);
3842 newBlocks.insertAtBack(1); // The deque's value is not modified.
3843
3844 AllocatorTraits::construct(
3845 this->allocatorRef(),
3846 this->d_finish.valuePtr(),
3847 BSLS_COMPILERFEATURES_FORWARD(Args, arguments)...);
3848 this->d_finish.nextBlock();
3849 }
3850 return *(this->d_finish - 1);
3851}
3852#endif
3853
3854#if !BSLS_COMPILERFEATURES_SIMULATE_CPP11_FEATURES
3855template <class VALUE_TYPE, class ALLOCATOR>
3856template <class... Args>
3859 Args&&... arguments)
3860{
3861 BSLS_ASSERT(position >= this->cbegin());
3862 BSLS_ASSERT(position <= this->cend());
3863
3864 if (position == this->cbegin()) {
3865 emplace_front(BSLS_COMPILERFEATURES_FORWARD(Args, arguments)...);
3866 return this->begin(); // RETURN
3867 }
3868
3869 if (position == this->cend()) {
3870 emplace_back(BSLS_COMPILERFEATURES_FORWARD(Args, arguments)...);
3871 return iterator(this->d_finish - 1); // RETURN
3872 }
3873
3874 // The test is placed here because @ref emplace_front and @ref emplace_back do
3875 // the same check.
3876
3877 const size_type currentSize = this->size();
3878 if (BSLS_PERFORMANCEHINT_PREDICT_UNLIKELY(currentSize >= max_size())) {
3880
3881 BloombergLP::bslstl::StdExceptUtil::throwLengthError(
3882 "deque<...>::emplace(args): deque too big");
3883 }
3884
3885 iterator pos(position.imp());
3886 const size_type posIdx = position - this->cbegin();
3887 if (posIdx <= currentSize / 2) {
3888 BlockCreator newBlocks(this);
3889 if (this->d_start.remainingInBlock() == BLOCK_LENGTH) {
3890 newBlocks.insertAtFront(1);
3891 }
3892
3893 BlockProctor proctor(this, true);
3894 DequePrimitives::emplaceAndMoveToFront(
3895 &this->d_start,
3896 this->d_start,
3897 this->d_start + posIdx,
3898 this->allocatorRef(),
3899 BSLS_COMPILERFEATURES_FORWARD(Args, arguments)...);
3900 proctor.release();
3901 }
3902 else {
3903 BlockCreator newBlocks(this);
3904 if (this->d_finish.offsetInBlock() == BLOCK_LENGTH - 1) {
3905 newBlocks.insertAtBack(1);
3906 }
3907
3908 BlockProctor proctor(this, false);
3909 DequePrimitives::emplaceAndMoveToBack(
3910 &this->d_finish,
3911 this->d_finish,
3912 this->d_start + posIdx,
3913 this->allocatorRef(),
3914 BSLS_COMPILERFEATURES_FORWARD(Args, arguments)...);
3915 proctor.release();
3916 }
3917 return this->begin() + posIdx;
3918}
3919#endif
3920
3921template <class VALUE_TYPE, class ALLOCATOR>
3923{
3924 BSLS_ASSERT(!this->empty());
3925
3926 BloombergLP::bslma::DestructionUtil::destroy(this->d_start.valuePtr());
3927
3928 if (1 == this->d_start.remainingInBlock()) {
3929 this->deallocateBlock(*this->d_start.blockPtr());
3930 this->d_start.nextBlock();
3931 return; // RETURN
3932 }
3933
3934 this->d_start.valuePtrIncrement();
3935}
3936
3937template <class VALUE_TYPE, class ALLOCATOR>
3939{
3940 BSLS_ASSERT(!this->empty());
3941
3942 if (0 == this->d_finish.offsetInBlock()) {
3943 --this->d_finish;
3944 BloombergLP::bslma::DestructionUtil::destroy(
3945 this->d_finish.valuePtr());
3946 this->deallocateBlock(this->d_finish.blockPtr()[1]);
3947 return; // RETURN
3948 }
3949
3950 this->d_finish.valuePtrDecrement();
3951 BloombergLP::bslma::DestructionUtil::destroy(this->d_finish.valuePtr());
3952}
3953
3954template <class VALUE_TYPE, class ALLOCATOR>
3957 const VALUE_TYPE& value)
3958{
3959 BSLS_ASSERT(position >= this->cbegin());
3960 BSLS_ASSERT(position <= this->cend());
3961
3962 if (position == this->cbegin()) {
3963 push_front(value);
3964 return this->begin(); // RETURN
3965 }
3966
3967 if (position == this->cend()) {
3968 push_back(value);
3969 return iterator(this->d_finish - 1); // RETURN
3970 }
3971
3972 // The test is placed here because 'push_front' and 'push_back' do the same
3973 // check.
3974
3975 const size_type currentSize = this->size();
3976 if (BSLS_PERFORMANCEHINT_PREDICT_UNLIKELY(currentSize >= max_size())) {
3978
3979 BloombergLP::bslstl::StdExceptUtil::throwLengthError(
3980 "deque<...>::insert(pos,n,v): deque too big");
3981 }
3982
3983 iterator pos(position.imp());
3984 const size_type posIdx = position - this->cbegin();
3985 if (posIdx <= currentSize / 2) {
3986 BlockCreator newBlocks(this);
3987 if (this->d_start.remainingInBlock() == BLOCK_LENGTH) {
3988 newBlocks.insertAtFront(1);
3989 }
3990 DequePrimitives::insertAndMoveToFront(&this->d_start,
3991 this->d_start,
3992 this->d_start + posIdx,
3993 1,
3994 value,
3995 this->allocatorRef());
3996 }
3997 else {
3998 BlockCreator newBlocks(this);
3999 if (this->d_finish.offsetInBlock() == BLOCK_LENGTH - 1) {
4000 newBlocks.insertAtBack(1);
4001 }
4002 DequePrimitives::insertAndMoveToBack(&this->d_finish,
4003 this->d_finish,
4004 this->d_start + posIdx,
4005 1,
4006 value,
4007 this->allocatorRef());
4008 }
4009 return this->begin() + posIdx;
4010}
4011
4012template <class VALUE_TYPE, class ALLOCATOR>
4015 const_iterator position,
4016 BloombergLP::bslmf::MovableRef<VALUE_TYPE> value)
4017{
4018 BSLS_ASSERT(position >= this->cbegin());
4019 BSLS_ASSERT(position <= this->cend());
4020
4021 VALUE_TYPE& lvalue = value;
4022
4023 if (position == this->cbegin()) {
4024 push_front(MoveUtil::move(lvalue));
4025 return this->begin(); // RETURN
4026 }
4027
4028 if (position == this->cend()) {
4029 push_back(MoveUtil::move(lvalue));
4030 return iterator(this->d_finish - 1); // RETURN
4031 }
4032
4033 // The test is placed here because 'push_front' and 'push_back' do the same
4034 // check.
4035
4036 const size_type currentSize = this->size();
4037 if (BSLS_PERFORMANCEHINT_PREDICT_UNLIKELY(currentSize >= max_size())) {
4039
4040 BloombergLP::bslstl::StdExceptUtil::throwLengthError(
4041 "deque<...>::insert(pos,n,v): deque too big");
4042 }
4043
4044 iterator pos(position.imp());
4045 const size_type posIdx = position - this->cbegin();
4046 if (posIdx <= currentSize / 2) {
4047 BlockCreator newBlocks(this);
4048 if (this->d_start.remainingInBlock() == BLOCK_LENGTH) {
4049 newBlocks.insertAtFront(1);
4050 }
4051 DequePrimitives::moveInsertAndMoveToFront(&this->d_start,
4052 this->d_start,
4053 this->d_start + posIdx,
4054 MoveUtil::move(lvalue),
4055 this->allocatorRef());
4056 }
4057 else {
4058 BlockCreator newBlocks(this);
4059 if (this->d_finish.offsetInBlock() == BLOCK_LENGTH - 1) {
4060 newBlocks.insertAtBack(1);
4061 }
4062 DequePrimitives::moveInsertAndMoveToBack(&this->d_finish,
4063 this->d_finish,
4064 this->d_start + posIdx,
4065 MoveUtil::move(lvalue),
4066 this->allocatorRef());
4067 }
4068 return this->begin() + posIdx;
4069}
4070
4071template <class VALUE_TYPE, class ALLOCATOR>
4074 size_type numElements,
4075 const VALUE_TYPE& value)
4076{
4077 BSLS_ASSERT(position >= this->cbegin());
4078 BSLS_ASSERT(position <= this->cend());
4079
4080 const size_type posIdx = position - this->cbegin();
4081
4082 if (0 == numElements) {
4083 return this->begin() + posIdx; // RETURN
4084 }
4085
4086 const size_type currentSize = this->size();
4088 numElements > max_size() - currentSize)) {
4090
4091 BloombergLP::bslstl::StdExceptUtil::throwLengthError(
4092 "deque<...>::insert(pos,n,v): deque too big");
4093 }
4094
4095 if (position == this->cbegin()) {
4096 privatePrependRaw(numElements, value);
4097
4098 return this->begin(); // RETURN
4099 }
4100
4101 if (position == this->cend()) {
4102 privateAppendRaw(numElements, value);
4103
4104 return this->begin() + posIdx; // RETURN
4105 }
4106
4107 if (posIdx <= currentSize / 2) {
4108 // Create new blocks at front. In case an exception is thrown, any
4109 // unused blocks are returned to the allocator.
4110
4111 size_type numNewBlocks = (this->d_start.remainingInBlock()
4112 + numElements - 1) / BLOCK_LENGTH;
4113 BlockCreator newBlocks(this);
4114 newBlocks.insertAtFront(numNewBlocks);
4115
4116 DequePrimitives::insertAndMoveToFront(&this->d_start,
4117 this->d_start,
4118 this->d_start + posIdx,
4119 numElements,
4120 value,
4121 this->allocatorRef());
4122 }
4123 else {
4124 // Create new blocks at back. In case an exception is thrown, any
4125 // unused blocks are returned to the allocator.
4126
4127 size_type numNewBlocks = (this->d_finish.offsetInBlock() + numElements)
4128 / BLOCK_LENGTH;
4129 BlockCreator newBlocks(this);
4130 newBlocks.insertAtBack(numNewBlocks);
4131
4132 DequePrimitives::insertAndMoveToBack(&this->d_finish,
4133 this->d_finish,
4134 this->d_start + posIdx,
4135 numElements,
4136 value,
4137 this->allocatorRef());
4138 }
4139
4140 return this->begin() + posIdx;
4141}
4142
4143template <class VALUE_TYPE, class ALLOCATOR>
4144template <class INPUT_ITERATOR>
4145inline
4148 INPUT_ITERATOR first,
4149 INPUT_ITERATOR last)
4150{
4151 BSLS_ASSERT_SAFE(position >= this->cbegin());
4152 BSLS_ASSERT_SAFE(position <= this->cend());
4153
4154 const size_type posIdx = position - this->cbegin();
4155
4156 privateInsertDispatch(position,
4157 first,
4158 last,
4159 first,
4160 BloombergLP::bslmf::Nil());
4161
4162 return this->begin() + posIdx;
4163}
4164
4165#if defined(BSLS_COMPILERFEATURES_SUPPORT_GENERALIZED_INITIALIZERS)
4166template <class VALUE_TYPE, class ALLOCATOR>
4167inline
4170 const_iterator position,
4171 std::initializer_list<value_type> values)
4172{
4173 BSLS_ASSERT_SAFE(position >= this->cbegin());
4174 BSLS_ASSERT_SAFE(position <= this->cend());
4175
4176 return insert(position, values.begin(), values.end());
4177}
4178#endif
4179
4180template <class VALUE_TYPE, class ALLOCATOR>
4181template <class t_RANGE>
4183typename deque<VALUE_TYPE, ALLOCATOR>::iterator
4185 const_iterator position,
4186 BSLS_COMPILERFEATURES_FORWARD_REF(t_RANGE) range)
4187{
4188 const size_type posIdx = position - this->cbegin();
4189 privateInsert(position, ranges::begin(range), ranges::end(range));
4190 return this->begin() + posIdx;
4191}
4192
4193template <class VALUE_TYPE, class ALLOCATOR>
4196{
4197 BSLS_ASSERT(position >= this->cbegin());
4198 BSLS_ASSERT(position < this->cend());
4199
4200 if (position == const_iterator(this->d_start)) {
4201 pop_front();
4202 return this->begin(); // RETURN
4203 }
4204
4205 if (position + 1 == const_iterator(this->d_finish)) {
4206 pop_back();
4207 return this->end(); // RETURN
4208 }
4209
4210 return erase(position, position + 1);
4211}
4212
4213template <class VALUE_TYPE, class ALLOCATOR>
4216{
4217 BSLS_ASSERT(first >= this->cbegin());
4218 BSLS_ASSERT(first <= this->cend());
4219 BSLS_ASSERT(first <= last);
4220 BSLS_ASSERT(last <= this->cend());
4221
4222 iterator first_imp = this->begin() + (first - this->cbegin());
4223 iterator last_imp = this->begin() + (last - this->cbegin());
4224 iterator oldStart = this->begin();
4225 iterator oldFinish = this->end();
4226 iterator result = iterator(DequePrimitives::erase(&this->d_start,
4227 &this->d_finish,
4228 this->d_start,
4229 first_imp.imp(),
4230 last_imp.imp(),
4231 this->d_finish,
4232 this->allocatorRef()));
4233
4234 // Deallocate blocks no longer used.
4235
4236 for ( ; oldStart.imp().blockPtr() != this->d_start.blockPtr();
4237 oldStart.imp().nextBlock()) {
4238 this->deallocateBlock(oldStart.imp().blockPtr()[0]);
4239 }
4240 for ( ; oldFinish.imp().blockPtr() != this->d_finish.blockPtr();
4241 oldFinish.imp().previousBlock()) {
4242 this->deallocateBlock(oldFinish.imp().blockPtr()[0]);
4243 }
4244 return result;
4245}
4246
4247template <class VALUE_TYPE, class ALLOCATOR>
4250 AllocatorTraits::is_always_equal::value)
4251{
4252 typedef typename
4253 AllocatorTraits::propagate_on_container_swap Propagate;
4254 if (Propagate::value) {
4255 Deque_Util::swap(static_cast<Base *>(this),
4256 static_cast<Base *>(&other));
4257 AllocatorUtil::swap(&this->allocatorRef(), &other.allocatorRef(),
4258 Propagate());
4259 }
4260 else {
4262 this->get_allocator() == other.get_allocator())) {
4263 Deque_Util::swap(static_cast<Base *>(this),
4264 static_cast<Base *>(&other));
4265 }
4266 else {
4268
4269 deque toOtherCopy(MoveUtil::move(*this), other.get_allocator());
4270 deque toThisCopy( MoveUtil::move(other), this->get_allocator());
4271
4272 Deque_Util::swap(static_cast<Base *>(&toThisCopy),
4273 static_cast<Base *>(this));
4274 Deque_Util::swap(static_cast<Base *>(&toOtherCopy),
4275 static_cast<Base *>(&other));
4276 }
4277 }
4278}
4279
4280template <class VALUE_TYPE, class ALLOCATOR>
4282{
4283 DequePrimitives::destruct(this->d_start,
4284 this->d_finish,
4285 this->allocatorRef());
4286
4287 // Deallocate all blocks except 'finishBlock'.
4288
4289 BlockPtr *startBlock = this->d_start.blockPtr();
4290 BlockPtr *finishBlock = this->d_finish.blockPtr();
4291 for ( ; startBlock != finishBlock; ++startBlock) {
4292 this->deallocateBlock(*startBlock);
4293 }
4294
4295 // Reposition in the middle.
4296
4297 size_type blockOffset = this->d_blocksLength / 2;
4298 int offset = BLOCK_LENGTH / 2;
4299 BlockPtr *blockPtr = this->d_blocks_p + blockOffset;
4300
4301 *blockPtr = *finishBlock;
4302
4303 this->d_start = this->d_finish = IteratorImp(blockPtr,
4304 (*blockPtr)->d_data + offset);
4305}
4306
4307// ACCESSORS
4308template <class VALUE_TYPE, class ALLOCATOR>
4309inline
4310typename deque<VALUE_TYPE, ALLOCATOR>::allocator_type
4312{
4313 return this->allocatorRef();
4314}
4315
4316template <class VALUE_TYPE, class ALLOCATOR>
4317inline
4320{
4321 return AllocatorTraits::max_size(this->get_allocator());
4322}
4323
4324// FREE OPERATORS
4325template <class VALUE_TYPE, class ALLOCATOR>
4326bool operator==(const deque<VALUE_TYPE, ALLOCATOR>& lhs,
4328{
4329 if (lhs.size() != rhs.size()) {
4330 return false; // RETURN
4331 }
4332
4333 enum {
4335 };
4336
4337 typedef BloombergLP::bslalg::DequeIterator<VALUE_TYPE,
4338 BLOCK_LENGTH> Iterator;
4339
4340 Iterator lhsBegin = lhs.begin().imp();
4341 Iterator lhsEnd = lhs.end().imp();
4342 Iterator rhsBegin = rhs.begin().imp();
4343
4344 for (; !(lhsBegin == lhsEnd); ++lhsBegin, ++rhsBegin) {
4345 if (!(*lhsBegin == *rhsBegin)) {
4346 return false; // RETURN
4347 }
4348 }
4349 return true;
4350}
4351
4352#ifndef BSLS_COMPILERFEATURES_SUPPORT_THREE_WAY_COMPARISON
4353
4354template <class VALUE_TYPE, class ALLOCATOR>
4355inline
4356bool operator!=(const deque<VALUE_TYPE, ALLOCATOR>& lhs,
4358{
4359 return !(lhs == rhs);
4360}
4361
4362#endif
4363
4364#ifdef BSLALG_SYNTHTHREEWAYUTIL_AVAILABLE
4365
4366template <class VALUE_TYPE, class ALLOCATOR>
4367inline
4368BloombergLP::bslalg::SynthThreeWayUtil::Result<VALUE_TYPE> operator<=>(
4369 const deque<VALUE_TYPE, ALLOCATOR>& lhs,
4370 const deque<VALUE_TYPE, ALLOCATOR>& rhs)
4371{
4372 return bsl::lexicographical_compare_three_way(
4373 lhs.begin(),
4374 lhs.end(),
4375 rhs.begin(),
4376 rhs.end(),
4377 BloombergLP::bslalg::SynthThreeWayUtil::compare);
4378}
4379
4380#else
4381
4382template <class VALUE_TYPE, class ALLOCATOR>
4383inline
4384bool operator<(const deque<VALUE_TYPE, ALLOCATOR>& lhs,
4386{
4387 return 0 > BloombergLP::bslalg::RangeCompare::lexicographical(lhs.begin(),
4388 lhs.end(),
4389 lhs.size(),
4390 rhs.begin(),
4391 rhs.end(),
4392 rhs.size());
4393}
4394
4395template <class VALUE_TYPE, class ALLOCATOR>
4396inline
4397bool operator>(const deque<VALUE_TYPE, ALLOCATOR>& lhs,
4399{
4400 return rhs < lhs;
4401}
4402
4403template <class VALUE_TYPE, class ALLOCATOR>
4404inline
4405bool operator<=(const deque<VALUE_TYPE, ALLOCATOR>& lhs,
4407{
4408 return !(rhs < lhs);
4409}
4410
4411template <class VALUE_TYPE, class ALLOCATOR>
4412inline
4413bool operator>=(const deque<VALUE_TYPE, ALLOCATOR>& lhs,
4415{
4416 return !(lhs < rhs);
4417}
4418
4419#endif // BSLALG_SYNTHTHREEWAYUTIL_AVAILABLE
4420
4421// FREE FUNCTIONS
4422template <class VALUE_TYPE, class ALLOCATOR, class BDE_OTHER_TYPE>
4423inline typename deque<VALUE_TYPE, ALLOCATOR>::size_type
4424erase(deque<VALUE_TYPE, ALLOCATOR>& deq, const BDE_OTHER_TYPE& value)
4425{
4426 typename deque<VALUE_TYPE, ALLOCATOR>::size_type oldSize = deq.size();
4427 deq.erase(bsl::remove(deq.begin(), deq.end(), value), deq.end());
4428 return oldSize - deq.size();
4429}
4430
4431template <class VALUE_TYPE, class ALLOCATOR, class PREDICATE>
4432inline typename deque<VALUE_TYPE, ALLOCATOR>::size_type
4433erase_if(deque<VALUE_TYPE, ALLOCATOR>& deq, PREDICATE predicate)
4434{
4435 typename deque<VALUE_TYPE, ALLOCATOR>::size_type oldSize = deq.size();
4436 deq.erase(bsl::remove_if(deq.begin(), deq.end(), predicate), deq.end());
4437 return oldSize - deq.size();
4438}
4439
4440template <class VALUE_TYPE, class ALLOCATOR>
4441inline
4448
4449 // ------------------------
4450 // class Deque_BlockCreator
4451 // ------------------------
4452
4453// CREATORS
4454template <class VALUE_TYPE, class ALLOCATOR>
4455inline
4462
4463template <class VALUE_TYPE, class ALLOCATOR>
4465{
4466 if (0 != d_boundary_p) {
4467 BlockPtr *delFirst, *delLast;
4468 if (d_boundary_p <= d_deque_p->d_start.blockPtr()) {
4469 delFirst = d_boundary_p;
4470 delLast = d_deque_p->d_start.blockPtr();
4471 }
4472 else {
4473 delFirst = d_deque_p->d_finish.blockPtr() + 1;
4474 delLast = d_boundary_p;
4475 }
4476
4477 for (; delFirst != delLast; ++delFirst) {
4478 // Deallocate the block that '*delFirst' points to.
4479 d_deque_p->deallocateBlock(*delFirst);
4480 }
4481 }
4482}
4483
4484// MANIPULATORS
4485template <class VALUE_TYPE, class ALLOCATOR>
4487{
4488 d_boundary_p = reserveBlockSlots(n, true);
4489 for ( ; n > 0; --n) {
4490 d_boundary_p[-1] = d_deque_p->allocateBlock();
4491
4492 --d_boundary_p;
4493 }
4494}
4495
4496template <class VALUE_TYPE, class ALLOCATOR>
4498{
4499 d_boundary_p = reserveBlockSlots(n, false);
4500 for ( ; n > 0; --n) {
4501 *d_boundary_p = d_deque_p->allocateBlock();
4502 ++d_boundary_p;
4503 }
4504}
4505
4506template <class VALUE_TYPE, class ALLOCATOR>
4507typename Deque_BlockCreator<VALUE_TYPE, ALLOCATOR>::BlockPtr *
4509 size_type numNewBlocks,
4510 bool atFront)
4511{
4512 BlockPtr *blocks = d_deque_p->d_blocks_p;
4513 size_type blocksLength = d_deque_p->d_blocksLength;
4514
4515 BlockPtr *firstSlot = d_deque_p->d_start.blockPtr();
4516 BlockPtr *lastSlot = d_deque_p->d_finish.blockPtr() + 1;
4517
4518 if (atFront) {
4519 if (d_boundary_p) {
4520 firstSlot = d_boundary_p;
4521 }
4522 if (size_type(firstSlot - blocks) >= numNewBlocks) {
4523 // Enough room to insert at the front.
4524
4525 return firstSlot; // RETURN
4526 }
4527 }
4528 else {
4529 if (d_boundary_p) {
4530 lastSlot = d_boundary_p;
4531 }
4532 if (size_type(blocks + blocksLength - lastSlot) >= numNewBlocks) {
4533 // Enough room to insert at the back.
4534
4535 return lastSlot; // RETURN
4536 }
4537 }
4538
4539 BlockPtr *newBlocks = blocks;
4540 size_type newBlocksLength = blocksLength;
4541 size_type numUsedBlocks = lastSlot - firstSlot;
4542 size_type blockOffsetStart = d_deque_p->d_start.blockPtr() - firstSlot;
4543 size_type numCommittedBlocks = (d_deque_p->d_finish.blockPtr() -
4544 d_deque_p->d_start.blockPtr() + 1);
4545 size_type newNumUsedBlocks = numUsedBlocks + numNewBlocks;
4546
4547 if (newNumUsedBlocks > blocksLength) {
4548 const size_type newThreshold = newNumUsedBlocks +
4549 2 * Imp::BLOCK_ARRAY_PADDING;
4550 while (newThreshold > newBlocksLength) {
4551 // Insufficient room. Allocate new blocks array with geometric
4552 // growth. Note that this should never overflow because there are
4553 // at least 16 elements in each block, thus the requested block
4554 // array pointer will never be close to 'max_size() / 2'.
4555
4556 newBlocksLength *= 2;
4557 }
4558 newBlocks = d_deque_p->allocateBlockPtrs(newBlocksLength);
4559 }
4560
4561 // Center block pointers within new blocks array.
4562
4563 BlockPtr *newFirstSlot = newBlocks +
4564 (newBlocksLength - newNumUsedBlocks) / 2;
4565
4566 if (atFront) {
4567 newFirstSlot += numNewBlocks;
4568 }
4569
4570 // Calculate offset for start and finish. Need to do this before moving
4571 // around blocks.
4572
4573 const size_type offsetStart = d_deque_p->d_start.offsetInBlock();
4574 const size_type offsetFinish = d_deque_p->d_finish.offsetInBlock();
4575
4576 // Move old block pointers into new position.
4577
4578 std::memmove(newFirstSlot, firstSlot, numUsedBlocks * sizeof(BlockPtr));
4579
4580 if (newBlocks != blocks) {
4581 // Deallocate old blocks array and install the new one.
4582
4583 if (blocks) {
4584 d_deque_p->deallocateBlockPtrs(blocks, d_deque_p->d_blocksLength);
4585 }
4586 d_deque_p->d_blocks_p = newBlocks;
4587 d_deque_p->d_blocksLength = newBlocksLength;
4588 }
4589
4590 // Adjust start and finish iterators.
4591
4592 d_deque_p->d_start.setBlock(newFirstSlot + blockOffsetStart);
4593 d_deque_p->d_start += offsetStart;
4594 d_deque_p->d_finish.setBlock(newFirstSlot + blockOffsetStart +
4595 numCommittedBlocks - 1);
4596 d_deque_p->d_finish += offsetFinish;
4597
4598 BlockPtr *ret = newFirstSlot;
4599 if (!atFront) {
4600 ret += numUsedBlocks;
4601 }
4602
4603 return ret;
4604}
4605
4606template <class VALUE_TYPE, class ALLOCATOR>
4607inline
4609{
4610 d_boundary_p = 0;
4611}
4612
4613 // ------------------------
4614 // class Deque_BlockProctor
4615 // ------------------------
4616
4617// CREATORS
4618template <class VALUE_TYPE, class ALLOCATOR>
4621 bool atFront)
4622: d_deque_p(deque)
4623, d_boundary_p(atFront
4624 ? d_deque_p->d_start.blockPtr()
4625 : d_deque_p->d_finish.blockPtr())
4626, d_atFront(atFront)
4627{
4628}
4629
4630template <class VALUE_TYPE, class ALLOCATOR>
4632{
4633 if (0 != d_deque_p) {
4634 BlockPtr *delFirst, *delLast;
4635
4636 if (d_atFront && d_boundary_p < d_deque_p->d_start.blockPtr()) {
4637 // Blocks at the front of the deque have been emptied since this
4638 // proctor was created.
4639
4640 delFirst = d_boundary_p;
4641 delLast = d_deque_p->d_start.blockPtr();
4642 }
4643 else if (!d_atFront && d_boundary_p > d_deque_p->d_finish.blockPtr()) {
4644 // Blocks at the back of the deque have been emptied since this
4645 // proctor was created.
4646
4647 delFirst = d_deque_p->d_finish.blockPtr() + 1;
4648 delLast = d_boundary_p + 1;
4649 }
4650 else {
4651 return; // RETURN
4652 }
4653
4654 for (; delFirst != delLast; ++delFirst) {
4655 // Deallocate the block that '*delFirst' points to.
4656
4657 d_deque_p->deallocateBlock(*delFirst);
4658 }
4659 }
4660}
4661
4662// MANIPULATORS
4663template <class VALUE_TYPE, class ALLOCATOR>
4664inline
4666{
4667 d_deque_p = 0;
4668}
4669
4670 // ----------------------
4671 // class Deque_ClearGuard
4672 // ----------------------
4673
4674// CREATORS
4675template <class VALUE_TYPE, class ALLOCATOR>
4676inline
4682
4683template <class VALUE_TYPE, class ALLOCATOR>
4684inline
4686{
4687 if (d_deque_p) {
4688 d_deque_p->clear();
4689 }
4690}
4691
4692// MANIPULATORS
4693template <class VALUE_TYPE, class ALLOCATOR>
4694inline
4696{
4697 d_deque_p = 0;
4698}
4699
4700 // -----------------
4701 // class Deque_Guard
4702 // -----------------
4703
4704// CREATORS
4705template <class VALUE_TYPE, class ALLOCATOR>
4706inline
4709 bool isTail)
4710: d_deque_p(deque)
4711, d_count(0)
4712, d_isTail(isTail)
4713{
4714}
4715
4716template <class VALUE_TYPE, class ALLOCATOR>
4718{
4719 if (0 == d_count) {
4720 return; // RETURN
4721 }
4722
4723 IteratorImp begin, end;
4724
4725 if (d_isTail) {
4726 begin = d_deque_p->d_finish;
4727 end = begin + d_count;
4728 }
4729 else {
4730 end = d_deque_p->d_start;
4731 begin = end - d_count;
4732 }
4733
4734 DequePrimitives::destruct(begin, end, d_deque_p->get_allocator());
4735}
4736
4737// MANIPULATORS
4738template <class VALUE_TYPE, class ALLOCATOR>
4739inline
4741{
4742 return ++d_count;
4743}
4744
4745template <class VALUE_TYPE, class ALLOCATOR>
4746inline
4748{
4749 return --d_count;
4750}
4751
4752template <class VALUE_TYPE, class ALLOCATOR>
4753inline
4755{
4756 d_count = 0;
4757}
4758
4759// ACCESSORS
4760template <class VALUE_TYPE, class ALLOCATOR>
4761inline
4762std::size_t
4767
4768template <class VALUE_TYPE, class ALLOCATOR>
4769inline
4770typename Deque_Guard<VALUE_TYPE, ALLOCATOR>::IteratorImp
4772{
4773 return d_deque_p->d_start - d_count;
4774}
4775
4776template <class VALUE_TYPE, class ALLOCATOR>
4777inline
4778typename Deque_Guard<VALUE_TYPE, ALLOCATOR>::IteratorImp
4780{
4781 return d_deque_p->d_finish + d_count;
4782}
4783
4784} // close namespace bsl
4785
4786// ============================================================================
4787// TYPE TRAITS
4788// ============================================================================
4789
4790// Type traits for STL *sequence* containers:
4791//: o A sequence container defines STL iterators.
4792//: o A sequence container is bitwise-movable if its allocator is
4793//: bitwise-movable.
4794//: o A sequence container uses 'bslma' allocators if the (template parameter)
4795//: type 'ALLOCATOR' is convertible from 'bslma::Allocator *'.
4796
4797
4798
4799namespace bslalg {
4800
4801template <class VALUE_TYPE, class ALLOCATOR>
4802struct HasStlIterators<bsl::deque<VALUE_TYPE, ALLOCATOR> > : bsl::true_type
4803{
4804};
4805
4806} // close namespace bslalg
4807
4808namespace bslmf {
4809
4810template <class VALUE_TYPE, class ALLOCATOR>
4811struct IsBitwiseMoveable<bsl::deque<VALUE_TYPE, ALLOCATOR> >
4812 : IsBitwiseMoveable<ALLOCATOR>
4813{
4814};
4815
4816} // close namespace bslmf
4817
4818namespace bslma {
4819
4820template <class VALUE_TYPE, class ALLOCATOR>
4821struct UsesBslmaAllocator<bsl::deque<VALUE_TYPE, ALLOCATOR> >
4822 : bsl::is_convertible<Allocator *, ALLOCATOR>
4823{
4824};
4825
4826} // close namespace bslma
4827
4828
4829
4830#endif // End C++11 code
4831
4832#undef BSLSTL_DEQUE_REQUIRES_CONTAINER_COMPATIBLE_RANGE
4833
4834#endif
4835
4836// ----------------------------------------------------------------------------
4837// Copyright 2013 Bloomberg Finance L.P.
4838//
4839// Licensed under the Apache License, Version 2.0 (the "License");
4840// you may not use this file except in compliance with the License.
4841// You may obtain a copy of the License at
4842//
4843// http://www.apache.org/licenses/LICENSE-2.0
4844//
4845// Unless required by applicable law or agreed to in writing, software
4846// distributed under the License is distributed on an "AS IS" BASIS,
4847// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
4848// See the License for the specific language governing permissions and
4849// limitations under the License.
4850// ----------------------------- END-OF-FILE ----------------------------------
4851
4852/** @} */
4853/** @} */
4854/** @} */
Definition bslstl_deque.h:613
IteratorImp d_finish
Definition bslstl_deque.h:659
const_reverse_iterator crend() const BSLS_KEYWORD_NOEXCEPT
Definition bslstl_deque.h:2233
iterator end() BSLS_KEYWORD_NOEXCEPT
Definition bslstl_deque.h:2107
reference back()
Definition bslstl_deque.h:2164
reverse_iterator rbegin() BSLS_KEYWORD_NOEXCEPT
Definition bslstl_deque.h:2115
reference operator[](size_type position)
Definition bslstl_deque.h:2131
size_type size() const BSLS_KEYWORD_NOEXCEPT
Return the number of elements contained by this deque.
Definition bslstl_deque.h:2241
const_iterator cbegin() const BSLS_KEYWORD_NOEXCEPT
Definition bslstl_deque.h:2185
bsl::reverse_iterator< Iterator > reverse_iterator
Definition bslstl_deque.h:651
std::size_t d_blocksLength
Definition bslstl_deque.h:657
reverse_iterator rend() BSLS_KEYWORD_NOEXCEPT
Definition bslstl_deque.h:2123
bsl::reverse_iterator< ConstIterator > const_reverse_iterator
Definition bslstl_deque.h:652
reference front()
Definition bslstl_deque.h:2154
BlockPtr * d_blocks_p
Definition bslstl_deque.h:656
Iterator iterator
Definition bslstl_deque.h:638
ConstIterator const_iterator
Definition bslstl_deque.h:639
VALUE_TYPE value_type
Definition bslstl_deque.h:642
iterator begin() BSLS_KEYWORD_NOEXCEPT
Definition bslstl_deque.h:2099
const VALUE_TYPE & const_reference
Definition bslstl_deque.h:637
size_type capacity() const BSLS_KEYWORD_NOEXCEPT
Definition bslstl_deque.h:2248
std::size_t size_type
Definition bslstl_deque.h:640
reference at(size_type position)
Definition bslstl_deque.h:2140
const_iterator cend() const BSLS_KEYWORD_NOEXCEPT
Definition bslstl_deque.h:2201
bool empty() const BSLS_KEYWORD_NOEXCEPT
Definition bslstl_deque.h:2287
const_reverse_iterator crbegin() const BSLS_KEYWORD_NOEXCEPT
Definition bslstl_deque.h:2217
VALUE_TYPE & reference
Definition bslstl_deque.h:636
IteratorImp d_start
Definition bslstl_deque.h:658
std::ptrdiff_t difference_type
Definition bslstl_deque.h:641
Definition bslstl_deque.h:1841
BlockPtr * reserveBlockSlots(size_type numNewBlocks, bool atFront)
Definition bslstl_deque.h:4508
void release()
Definition bslstl_deque.h:4608
~Deque_BlockCreator()
Definition bslstl_deque.h:4464
void insertAtFront(size_type n)
Definition bslstl_deque.h:4486
void insertAtBack(size_type n)
Definition bslstl_deque.h:4497
Definition bslstl_deque.h:1913
~Deque_BlockProctor()
Definition bslstl_deque.h:4631
void release()
Definition bslstl_deque.h:4665
Definition bslstl_deque.h:1974
~Deque_ClearGuard()
Definition bslstl_deque.h:4685
void release()
Release from management the deque proctored by this object.
Definition bslstl_deque.h:4695
Definition bslstl_deque.h:2022
void release()
Definition bslstl_deque.h:4754
std::size_t count() const BSLS_KEYWORD_NOEXCEPT
Return the current count maintained by this guard.
Definition bslstl_deque.h:4763
IteratorImp begin() const BSLS_KEYWORD_NOEXCEPT
Return a pointer after the first item in the guarded range.
Definition bslstl_deque.h:4771
~Deque_Guard()
Definition bslstl_deque.h:4717
IteratorImp end() const BSLS_KEYWORD_NOEXCEPT
Return a pointer after the last item in the guarded range.
Definition bslstl_deque.h:4779
std::size_t operator--()
Decrement the count of this guard, and return the new count.
Definition bslstl_deque.h:4747
std::size_t operator++()
Increment the count of this guard, and return the new count.
Definition bslstl_deque.h:4740
Definition bslma_bslallocator.h:588
Definition bslstl_deque.h:814
ALLOCATOR allocator_type
Definition bslstl_deque.h:870
iterator insert(const_iterator position, const VALUE_TYPE &value)
Definition bslstl_deque.h:3956
ConstIterator const_iterator
Definition bslstl_deque.h:865
bsl::reverse_iterator< ConstIterator > const_reverse_iterator
Definition bslstl_deque.h:877
size_type max_size() const BSLS_KEYWORD_NOEXCEPT
Definition bslstl_deque.h:4319
deque & operator=(const deque &rhs)
Definition bslstl_deque.h:3313
VALUE_TYPE value_type
Definition bslstl_deque.h:868
AllocatorTraits::pointer pointer
Definition bslstl_deque.h:871
AllocatorTraits::const_pointer const_pointer
Definition bslstl_deque.h:872
deque()
Definition bslstl_deque.h:3119
iterator erase(const_iterator position)
Definition bslstl_deque.h:4195
void assign(size_type numElements, const VALUE_TYPE &value)
Definition bslstl_deque.h:3415
const VALUE_TYPE & const_reference
Definition bslstl_deque.h:863
reference emplace_back(Args &&... arguments)
void swap(deque< VALUE_TYPE, ALLOCATOR > &other) BSLS_KEYWORD_NOEXCEPT_SPECIFICATION(AllocatorTraits void clear() BSLS_KEYWORD_NOEXCEPT
Definition bslstl_deque.h:1604
void pop_back()
Definition bslstl_deque.h:3938
void pop_front()
Definition bslstl_deque.h:3922
iterator emplace(const_iterator position, Args &&... arguments)
void push_back(const VALUE_TYPE &value)
Definition bslstl_deque.h:3719
void shrink_to_fit()
Definition bslstl_deque.h:3598
deque &operator=(BloombergLP::bslmf::MovableRef< deque > rhs) BSLS_KEYWORD_NOEXCEPT_SPECIFICATION(AllocatorTraits void assign(INPUT_ITERATOR first, INPUT_ITERATOR last)
Iterator iterator
Definition bslstl_deque.h:864
std::ptrdiff_t difference_type
Definition bslstl_deque.h:867
iterator insert(const_iterator position, INPUT_ITERATOR first, INPUT_ITERATOR last)
reference emplace_front(Args &&... arguments)
allocator_type get_allocator() const BSLS_KEYWORD_NOEXCEPT
Return the allocator used by this deque to supply memory.
Definition bslstl_deque.h:4311
VALUE_TYPE & reference
Definition bslstl_deque.h:862
iterator insert(const_iterator position, size_type numElements, const VALUE_TYPE &value)
Definition bslstl_deque.h:4073
bsl::reverse_iterator< Iterator > reverse_iterator
Definition bslstl_deque.h:876
iterator insert_range(const_iterator position, BSLS_COMPILERFEATURES_FORWARD_REF(t_RANGE) range)
~deque()
Destroy this object.
Definition bslstl_deque.h:3290
deque(const ALLOCATOR &basicAllocator)
Definition bslstl_deque.h:3129
deque(INPUT_ITERATOR first, INPUT_ITERATOR last, const ALLOCATOR &basicAllocator=ALLOCATOR())
Definition bslstl_deque.h:3177
void resize(size_type newSize)
Definition bslstl_deque.h:3545
deque(size_type numElements, const ALLOCATOR &basicAllocator=ALLOCATOR())
Definition bslstl_deque.h:3139
deque(size_type numElements, const VALUE_TYPE &value, const ALLOCATOR &basicAllocator=ALLOCATOR())
Definition bslstl_deque.h:3157
void append_range(BSLS_COMPILERFEATURES_FORWARD_REF(t_RANGE) range)
Definition bslstl_deque.h:3635
void reserve(size_type numElements)
Definition bslstl_deque.h:3475
void push_front(const VALUE_TYPE &value)
Definition bslstl_deque.h:3651
std::size_t size_type
Definition bslstl_deque.h:866
iterator insert(const_iterator position, BloombergLP::bslmf::MovableRef< value_type > value)
Definition bslstl_deque.h:4014
Definition bslstl_pair.h:1280
#define BSLMF_ASSERT(expr)
Definition bslmf_assert.h:231
#define BSLS_ASSERT(X)
Definition bsls_assert.h:1976
#define BSLS_ASSERT_SAFE(X)
Definition bsls_assert.h:1917
#define BSLS_ASSERT_OPT(X)
Definition bsls_assert.h:2045
#define BSLS_COMPILERFEATURES_FORWARD_REF(T)
Definition bsls_compilerfeatures.h:2343
#define BSLS_COMPILERFEATURES_FORWARD(T, V)
Definition bsls_compilerfeatures.h:2349
#define BSLS_IDENT(str)
BSLS_IDENT() - insert string into .comment binary segment (if supported)
Definition bsls_ident.h:238
#define BSLS_KEYWORD_NOEXCEPT_OPERATOR(...)
Definition bsls_keyword.h:677
#define BSLS_KEYWORD_NOEXCEPT
Definition bsls_keyword.h:674
#define BSLS_KEYWORD_NOEXCEPT_SPECIFICATION(...)
Definition bsls_keyword.h:676
#define BSLS_PERFORMANCEHINT_PREDICT_LIKELY(expr)
Definition bsls_performancehint.h:451
#define BSLS_PERFORMANCEHINT_UNLIKELY_HINT
Definition bsls_performancehint.h:484
#define BSLS_PERFORMANCEHINT_PREDICT_UNLIKELY(expr)
Definition bsls_performancehint.h:452
#define BSLS_UTIL_ADDRESSOF(OBJ)
Definition bsls_util.h:296
#define BSLSTL_DEQUE_REQUIRES_CONTAINER_COMPATIBLE_RANGE(R, T)
Definition bslstl_deque.h:524
bsl::size_t size(const TYPE &array)
Return the number of elements in the specified array.
int assign(LHS_TYPE *lhs, const RHS_TYPE &rhs)
Definition bdlat_valuetypefunctions.h:939
T::const_iterator cend(const T &container)
Definition bslstl_iterator.h:1709
ALLOCATOR const STRING_VIEW_LIKE_TYPE & rhs
Definition bslstl_string.h:3918
deque< VALUE_TYPE, ALLOCATOR >::size_type erase(deque< VALUE_TYPE, ALLOCATOR > &deq, const BDE_OTHER_TYPE &value)
Definition bslstl_deque.h:4424
T::iterator begin(T &container)
Definition bslstl_iterator.h:1593
T::const_iterator cbegin(const T &container)
Definition bslstl_iterator.h:1651
ALLOCATOR & lhs
Definition bslstl_string.h:3917
T::iterator end(T &container)
Definition bslstl_iterator.h:1621
deque< VALUE_TYPE, ALLOCATOR >::size_type erase_if(deque< VALUE_TYPE, ALLOCATOR > &deq, PREDICATE predicate)
Definition bslstl_deque.h:4433
BSLS_KEYWORD_CONSTEXPR bool empty(const CONTAINER &container)
Definition bslstl_iterator.h:1377
Definition bdlc_flathashmap.h:2218
Definition baljsn_encoder_testtypes.h:76
Definition bdlbb_blob.h:579
Definition bslstl_deque.h:561
@ DEFAULT_BLOCK_SIZE
Definition bslstl_deque.h:565
@ BLOCK_LENGTH
Definition bslstl_deque.h:567
Definition bslstl_deque.h:585
static void swap(void *a, void *b)
static void move(void *dst, void *src)
Definition bslma_allocatortraits.h:1089
BloombergLP::bslma::AllocatorTraits_ConstPointerType< ALLOCATOR >::type const_pointer
Definition bslma_allocatortraits.h:1183
BloombergLP::bslma::AllocatorTraits_PropOnCopyAssign< ALLOCATOR >::type propagate_on_container_copy_assignment
Definition bslma_allocatortraits.h:1332
BloombergLP::bslma::AllocatorTraits_SizeType< ALLOCATOR_TYPE >::type size_type
Definition bslma_allocatortraits.h:1196
BloombergLP::bslma::AllocatorTraits_PointerType< ALLOCATOR >::type pointer
Definition bslma_allocatortraits.h:1180
Definition bslstl_ranges.h:301
Definition bslmf_isconvertible.h:875
Definition bslmf_issame.h:146
Definition bslma_usesbslmaallocator.h:344
Definition bslmf_isbitwisemoveable.h:718