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