BDE 4.14.0 Production release
Loading...
Searching...
No Matches
bslalg_dequeprimitives.h
Go to the documentation of this file.
1/// @file bslalg_dequeprimitives.h
2///
3/// The content of this file has been pre-processed for Doxygen.
4///
5
6
7// bslalg_dequeprimitives.h -*-C++-*-
8#ifndef INCLUDED_BSLALG_DEQUEPRIMITIVES
9#define INCLUDED_BSLALG_DEQUEPRIMITIVES
10
11#include <bsls_ident.h>
12BSLS_IDENT("$Id: $")
13
14/// @defgroup bslalg_dequeprimitives bslalg_dequeprimitives
15/// @brief Provide primitive algorithms that operate on deques.
16/// @addtogroup bsl
17/// @{
18/// @addtogroup bslalg
19/// @{
20/// @addtogroup bslalg_dequeprimitives
21/// @{
22///
23/// <h1> Outline </h1>
24/// * <a href="#bslalg_dequeprimitives-purpose"> Purpose</a>
25/// * <a href="#bslalg_dequeprimitives-classes"> Classes </a>
26/// * <a href="#bslalg_dequeprimitives-description"> Description </a>
27/// * <a href="#bslalg_dequeprimitives-aliasing"> Aliasing </a>
28/// * <a href="#bslalg_dequeprimitives-usage"> Usage </a>
29///
30/// # Purpose {#bslalg_dequeprimitives-purpose}
31/// Provide primitive algorithms that operate on deques.
32///
33/// # Classes {#bslalg_dequeprimitives-classes}
34///
35/// - bslalg::DequePrimitives: namespace for deque algorithms
36///
37/// @see bslma_constructionutil, bslalg_arrayprimitives
38///
39/// # Description {#bslalg_dequeprimitives-description}
40/// This component provides utilities to initialize, destroy, move,
41/// and otherwise perform various primitive manipulations on deques with a
42/// uniform interface, but selecting a different implementation according to the
43/// various traits possessed by the underlying type, and selecting a simpler
44/// implementation when there is only one element per deque block. See the
45/// @ref bslalg_dequeimputil and @ref bslalg_dequeiterator components for a definition
46/// and visual depiction of the internal organization of a deque, and of the
47/// iterator type used to refer to elements in the deque.
48///
49/// The primitives provided by this component are exceptionally useful for
50/// implementing generic block-based components such as deques. A short
51/// synopsis is provided below describing the observable behavior and mentioning
52/// the relevant traits. See the full function-level contract for detailed
53/// description, including exception-safety guarantees. In the description
54/// below, `Ar` stands for `bslalg::ArrayPrimitives`. Note that some algorithms
55/// are explained in terms of previous algorithms.
56/// @code
57/// Algorithm Short description of observable behavior
58/// ---------------------------- ---------------------------------------------
59/// destruct Destroy each element in the target range.
60///
61/// erase 'destruct' for each element in the target
62/// range, or 'no-op' if bitwise copyable, then
63/// shift the remaining elements from either the
64/// front or the back to fill hole.
65///
66/// uninitializedFillNBack 'Ar::uninitializedFillN' for each block at
67/// the end of the deque
68///
69/// uninitializedFillNFront 'Ar::uninitializedFillN' for each block at
70/// the front of the deque.
71///
72/// valueInititalizeN 'Ar::defaultConstruct' for each block at the
73/// end of the deque.
74///
75/// insertAndMoveToBack Copy construct each element in the target
76/// range, or 'std::memmove' if type is bitwise
77/// moveable, to the back of the deque to create
78/// a hole, followed by copy construct of target
79/// value or range to fill the hole.
80///
81/// insertAndMoveToFront Copy construct each element in the target
82/// range, or 'std::memmove' if type is bitwise
83/// moveable, to the front of the deque to create
84/// a hole, followed by copy construct or
85/// 'std::memmove' of target value or range to
86/// fill the hole.
87///
88/// moveInsertAndMoveToBack Move-construct or move-assign each element in
89/// the target range (or 'std::memmove' if type
90/// is bitwise moveable) to the back of the
91/// deque to create a 1-slot hole, followed by
92/// move-assign of the movable source value to
93/// fill the hole.
94///
95/// moveInsertAndMoveToFront Move-construct or move-assign each element in
96/// the target range (or 'std::memmove' if type
97/// is bitwise moveable) to the front of the
98/// deque to create a 1-slot hole, followed by
99/// move-assign of the movable source value to
100/// fill the hole.
101///
102/// emplaceAndMoveToBack Move-construct or move-assign each element in
103/// the target range (or 'std::memmove' if type
104/// is bitwise moveable) to the back of the
105/// deque to create a 1-slot hole, followed by
106/// in-place construction of the source value to
107/// fill the hole.
108///
109/// emplaceAndMoveToFront Move-construct or move-assign each element in
110/// the target range (or 'std::memmove' if type
111/// is bitwise moveable) to the front of the
112/// deque to create a 1-slot hole, followed by
113/// in-place construction of the source value to
114/// fill the hole.
115/// @endcode
116/// The traits under consideration directly or indirectly by this component are:
117/// @code
118/// Trait English description
119/// ----- -------------------
120/// bslmf::IsBitwiseCopyable "TYPE has the bitwise
121/// copyable trait", or
122/// "TYPE is bitwise copyable"
123///
124/// bslmf::IsBitwiseMoveable "TYPE has the bitwise
125/// moveable trait", or
126/// "TYPE is bitwise moveable"
127/// @endcode
128///
129/// ## Aliasing {#bslalg_dequeprimitives-aliasing}
130///
131///
132/// There are some aliasing concerns in this component, due to the presence of
133/// the reference `const VALUE_TYPE& value` argument, which may belong to a
134/// range that will be modified during the course of the operation. All such
135/// aliasing concerns are taken care of properly. Other aliasing concerns due
136/// to the copying of a range `[first .. last)` are *not* taken care of, since
137/// their intended use is for range assignments and insertions in standard
138/// containers, for which the standard explicitly says that `first` and `last`
139/// shall not be iterators into the container.
140///
141/// ## Usage {#bslalg_dequeprimitives-usage}
142///
143///
144/// This component is for use by the `bslstl` package. Other clients should use
145/// the STL deque (in header `<deque>`).
146/// @}
147/** @} */
148/** @} */
149
150/** @addtogroup bsl
151 * @{
152 */
153/** @addtogroup bslalg
154 * @{
155 */
156/** @addtogroup bslalg_dequeprimitives
157 * @{
158 */
159
160#include <bslscm_version.h>
161
163#include <bslalg_dequeimputil.h>
164#include <bslalg_dequeiterator.h>
165
166#include <bslma_allocator.h>
169
172#include <bslmf_isconvertible.h>
173#include <bslmf_isfundamental.h>
174#include <bslmf_ispointer.h>
175#include <bslmf_movableref.h>
176#include <bslmf_tag.h>
177#include <bslmf_util.h> // 'forward(V)'
178
179#include <bsls_assert.h>
181#include <bsls_util.h> // 'forward<T>(V)'
182
183#include <cstddef> // std::size_t
184
185#include <cstring> // memmove
186
187#if BSLS_COMPILERFEATURES_SIMULATE_CPP11_FEATURES
188// Include version that can be compiled with C++03
189// Generated on Thu Oct 21 10:11:37 2021
190// Command line: sim_cpp11_features.pl bslalg_dequeprimitives.h
191# define COMPILING_BSLALG_DEQUEPRIMITIVES_H
193# undef COMPILING_BSLALG_DEQUEPRIMITIVES_H
194#else
195
196
197
198namespace {
199 // Workaround for windows. The windows compiler refuses to recognize
200 // enum declarations within a class template. TBD: verify this is
201 // still a concern with recent Windows compilers, as unnamed namespaces
202 // in header files are not a great workaround.
203
204 enum {
205 // These constants are used in the overloads below, when the last
206 // argument is of type 'bsl::integral_constant<int, N>', indicating
207 // that 'VALUE_TYPE' has the traits for which the enumerator equal to
208 // 'N' is named.
209
210 NIL_TRAITS = 0,
211 BITWISE_MOVEABLE_TRAITS = 1,
212 BITWISE_COPYABLE_TRAITS = 2,
213 NON_NIL_TRAITS = 3
214 };
215
216} // close unnamed namespace
217
218namespace bslalg {
219
220template <class VALUE_TYPE, int BLOCK_LENGTH, class ALLOCATOR>
221class DequePrimitives_DequeElementGuard;
222
223template <class VALUE_TYPE, int BLOCK_LENGTH>
224class DequePrimitives_DequeMoveGuard;
225
226template <class VALUE_TYPE, int BLOCK_LENGTH, class ALLOCATOR>
227class DequePrimitives_ExternalDequeElementGuard;
228
229template <class VALUE_TYPE, int BLOCK_LENGTH>
230class DequePrimitives_DequeEndpointProctor;
231
232 // ======================
233 // struct DequePrimitives
234 // ======================
235
236/// This `struct` provides a namespace for a suite of utility functions that
237/// operate on deques parameterized by the `VALUE_TYPE` and `BLOCK_LENGTH`.
238/// Depending on the traits of `VALUE_TYPE`, the default and copy
239/// constructors, destructor, assignment operators, etcetera may not be
240/// invoked, and instead the operation can be optimized using a no-op,
241/// bitwise move, or bitwise copy.
242template <class VALUE_TYPE, int BLOCK_LENGTH>
244
245 // PUBLIC TYPES
246 typedef std::size_t size_type;
248
249 private:
250 // PRIVATE TYPES
254
255 public:
256 // CLASS METHODS
257
258 /// TBD: fix comment
259 /// Call the destructor on each of the elements of a deque of
260 /// parameterized `VALUE_TYPE` in the specified range `[begin .. end)`.
261 /// The behavior is undefined unless `begin <= end`. Note that this
262 /// does not deallocate any memory (except memory deallocated by the
263 /// element destructor calls).
264 template <class ALLOCATOR>
265 static void destruct(Iterator begin, Iterator end, ALLOCATOR allocator);
266
267 /// Call the destructor on each of the elements of a deque of
268 /// parameterized `VALUE_TYPE` in the specified range `[begin .. end)`.
269 /// The behavior is undefined unless `begin <= end`. Note that this
270 /// does not deallocate any memory (except memory deallocated by the
271 /// element destructor calls). Note that the last argument is for
272 /// removing overload ambiguities and is not used.
273 template <class ALLOCATOR>
274 static void destruct(
275 Iterator begin,
276 Iterator end,
277 ALLOCATOR allocator,
279 template <class ALLOCATOR>
280 static void destruct(
281 Iterator begin,
282 Iterator end,
283 ALLOCATOR allocator,
285
286 /// Call the destructor on each of the elements of a deque of
287 /// parameterized `VALUE_TYPE` in the specified range `[first .. last)`.
288 /// Shift the elements to fill up the empty space after the erasure,
289 /// using the smaller of the range defined by `[fromBegin .. first)` and
290 /// `[last .. fromEnd)` after the erasure. Load in the specified
291 /// `toBegin` and `toEnd` the new boundaries of the deque after erasure
292 /// and return an iterator pointing to the element immediately following
293 /// the removed elements. The behavior is undefined unless
294 /// `fromBegin <= first <= last <= fromEnd`.
295 template <class ALLOCATOR>
296 static Iterator erase(Iterator *toBegin,
297 Iterator *toEnd,
298 Iterator fromBegin,
299 Iterator first,
300 Iterator last,
301 Iterator fromEnd,
302 ALLOCATOR allocator);
303
304 /// Call the destructor on each of the elements of a deque of
305 /// parameterized `VALUE_TYPE` in the specified range `[first .. last)`.
306 /// Shift the elements from the smaller of the specified range
307 /// `[fromBegin .. first)` and `[last .. fromEnd)` to fill up the empty
308 /// spaces after the erasure. Load in the specified `toBegin` and
309 /// `toEnd` the new boundaries of the deque after erasure and return an
310 /// iterator pointing to the element immediately following the removed
311 /// elements. The behavior is undefined unless
312 /// `fromBegin <= first <= last <= fromEnd`. Note that the last
313 /// argument is for removing overload ambiguities and is not used.
314 template <class ALLOCATOR>
315 static Iterator erase(
316 Iterator *toBegin,
317 Iterator *toEnd,
318 Iterator fromBegin,
319 Iterator first,
320 Iterator last,
321 Iterator fromEnd,
322 ALLOCATOR allocator,
324 template <class ALLOCATOR>
325 static Iterator erase(
326 Iterator *toBegin,
327 Iterator *toEnd,
328 Iterator fromBegin,
329 Iterator first,
330 Iterator last,
331 Iterator fromEnd,
332 ALLOCATOR allocator,
334
335 /// Insert the specified `numElements` copies of the specified `value`
336 /// at the specified `position`, by moving the elements in the range
337 /// `[position .. fromEnd)` forward by `numElements` position. Pass the
338 /// specified `allocator` to the copy constructor if appropriate. Load
339 /// into the specified `toEnd` an iterator to the end of the deque after
340 /// insertion (i.e., `fromEnd + numElements`). The behavior is
341 /// undefined unless `fromEnd + numElements` is a valid iterator (i.e.,
342 /// the block pointer array holds enough room after the `fromEnd`
343 /// position to insert `numElements`).
344 template <class ALLOCATOR>
345 static void insertAndMoveToBack(Iterator *toEnd,
346 Iterator fromEnd,
347 Iterator position,
348 size_type numElements,
349 const VALUE_TYPE& value,
350 ALLOCATOR allocator);
351
352 /// Insert the specified `numElements` copies of the specified `value`
353 /// at the specified `position`, by moving the elements in the range
354 /// `[position .. fromEnd)` forward by `numElements` position. Pass the
355 /// specified `allocator` to the copy constructor if appropriate. Load
356 /// into the specified `toEnd` an iterator to the end of the deque after
357 /// insertion (i.e., `fromEnd + numElements`). The behavior is
358 /// undefined unless `fromEnd + numElements` is a valid iterator (i.e.,
359 /// the block pointer array holds enough room after the `fromEnd`
360 /// position to insert `numElements`). Note that the last argument is
361 /// for removing overload ambiguities and is not used.
362 template <class ALLOCATOR>
363 static void insertAndMoveToBack(
364 Iterator *toEnd,
365 Iterator fromEnd,
366 Iterator position,
367 size_type numElements,
368 const VALUE_TYPE& value,
369 ALLOCATOR allocator,
371 template <class ALLOCATOR>
372 static void insertAndMoveToBack(
373 Iterator *toEnd,
374 Iterator fromEnd,
375 Iterator position,
376 size_type numElements,
377 const VALUE_TYPE& value,
378 ALLOCATOR allocator,
380 template <class ALLOCATOR>
381 static void insertAndMoveToBack(
382 Iterator *toEnd,
383 Iterator fromEnd,
384 Iterator position,
385 size_type numElements,
386 const VALUE_TYPE& value,
387 ALLOCATOR allocator,
389
390 /// Insert the specified `numElements` in the range `[first .. last)` at
391 /// the specified `position`, by moving the elements in the range
392 /// `[position .. fromEnd)` forward by `numElements` position. Pass the
393 /// specified `allocator` to the copy constructor if appropriate. Load
394 /// into the specified `toEnd` an iterator to the end of the data after
395 /// insertion (i.e., `fromEnd + numElements`). The behavior is
396 /// undefined unless `fromEnd + numElements` is a valid iterator (i.e.,
397 /// the block pointer array holds enough room after the `fromEnd`
398 /// position to insert `numElements`).
399 template <class FWD_ITER, class ALLOCATOR>
400 static void insertAndMoveToBack(Iterator *toEnd,
401 Iterator fromEnd,
402 Iterator position,
403 FWD_ITER first,
404 FWD_ITER last,
405 size_type numElements,
406 ALLOCATOR allocator);
407
408 /// Insert the specified move-insertable `value` at the specified
409 /// `position` by moving the elements in the range
410 /// `[position .. fromEnd)` forward by 1 position; pass the specified
411 /// `allocator` to the move constructor if appropriate. Load into the
412 /// specified `toEnd` an iterator one past the inserted element (i.e.,
413 /// `fromEnd + 1`). The behavior is undefined unless `fromEnd + 1` is a
414 /// valid iterator (i.e., the block pointer array holds enough room
415 /// after the `fromEnd` position to insert 1 element).
416 template <class ALLOCATOR>
417 static void moveInsertAndMoveToBack(
418 Iterator *toEnd,
419 Iterator fromEnd,
420 Iterator position,
422 ALLOCATOR allocator);
423
424 /// Insert the specified move-insertable `value` at the specified
425 /// `position` by moving the elements in the range
426 /// `[position .. fromEnd)` forward by 1 position; pass the specified
427 /// `allocator` to the move constructor if appropriate. Load into the
428 /// specified `toEnd` an iterator one past the inserted element (i.e.,
429 /// `fromEnd + 1`). The behavior is undefined unless `fromEnd + 1` is a
430 /// valid iterator (i.e., the block pointer array holds enough room
431 /// after the `fromEnd` position to insert 1 element). Note that the
432 /// last argument is for removing overload ambiguities and is not used.
433 template <class ALLOCATOR>
434 static void moveInsertAndMoveToBack(
435 Iterator *toEnd,
436 Iterator fromEnd,
437 Iterator position,
439 ALLOCATOR allocator,
441 template <class ALLOCATOR>
442 static void moveInsertAndMoveToBack(
443 Iterator *toEnd,
444 Iterator fromEnd,
445 Iterator position,
447 ALLOCATOR allocator,
449 template <class ALLOCATOR>
450 static void moveInsertAndMoveToBack(
451 Iterator *toEnd,
452 Iterator fromEnd,
453 Iterator position,
455 ALLOCATOR allocator,
457
458 /// Insert the specified `numElements` copies of the specified `value`
459 /// at the specified `position`, by moving the elements in the range
460 /// `[fromBegin .. position)` backward by `numElements` position. Pass
461 /// the specified `allocator` to the copy constructor if appropriate.
462 /// Load into the specified `toBegin` an iterator to the beginning of
463 /// the data after insertion (i.e., `fromBegin - numElements`). The
464 /// behavior is undefined unless `fromBegin - numElements` is a valid
465 /// iterator (i.e., the block pointer array holds enough room before the
466 /// `fromBegin` position to insert `numElements`).
467 template <class ALLOCATOR>
468 static void insertAndMoveToFront(Iterator *toBegin,
469 Iterator fromBegin,
470 Iterator position,
471 size_type numElements,
472 const VALUE_TYPE& value,
473 ALLOCATOR allocator);
474
475 /// Insert the specified `numElements` copies of the specified `value`
476 /// at the specified `position`, by moving the elements in the range
477 /// `[fromBegin .. position)` backward by `numElements` position. Pass
478 /// the specified `allocator` to the copy constructor if appropriate.
479 /// Load into the specified `toBegin` an iterator to the beginning of
480 /// the data after insertion (i.e., `fromBegin - numElements`. The
481 /// behavior is undefined unless `fromBegin - numElements` is a valid
482 /// iterator (i.e., the block pointer array holds enough room before the
483 /// `fromBegin` position to insert `numElements`). Note that the last
484 /// argument is for removing overload ambiguities and is not used.
485 template <class ALLOCATOR>
486 static void insertAndMoveToFront(
487 Iterator *toBegin,
488 Iterator fromBegin,
489 Iterator position,
490 size_type numElements,
491 const VALUE_TYPE& value,
492 ALLOCATOR allocator,
494 template <class ALLOCATOR>
495 static void insertAndMoveToFront(
496 Iterator *toBegin,
497 Iterator fromBegin,
498 Iterator position,
499 size_type numElements,
500 const VALUE_TYPE& value,
501 ALLOCATOR allocator,
503 template <class ALLOCATOR>
504 static void insertAndMoveToFront(
505 Iterator *toBegin,
506 Iterator fromBegin,
507 Iterator position,
508 size_type numElements,
509 const VALUE_TYPE& value,
510 ALLOCATOR allocator,
512
513 /// Insert the specified `numElements` in the range `[first .. last)` at
514 /// the specified `position`, by moving the elements in the range
515 /// `[fromBegin .. position)` backward by `numElements` position. Pass
516 /// the specified `allocator` to the copy constructor if appropriate.
517 /// Load into the specified `toBegin` an iterator to the end of the data
518 /// after insertion (i.e., `fromBegin - numElements`). The behavior is
519 /// undefined unless `fromBegin - numElements` is a valid iterator
520 /// (i.e., the block pointer array holds enough room before the
521 /// `fromBefore` position to insert `numElements`).
522 template <class FWD_ITER, class ALLOCATOR>
523 static void insertAndMoveToFront(Iterator *toBegin,
524 Iterator fromBegin,
525 Iterator position,
526 FWD_ITER first,
527 FWD_ITER last,
528 size_type numElements,
529 ALLOCATOR allocator);
530
531 /// Insert the specified move-insertable `value` at the specified
532 /// `position` by moving the elements in the range
533 /// `[fromBegin .. position)` backward by 1 position; pass the specified
534 /// `allocator` to the move constructor if appropriate. Load into the
535 /// specified `toBegin` an iterator to the inserted element (i.e.,
536 /// `fromBegin - 1`). The behavior is undefined unless
537 /// `fromBegin - 1` is a valid iterator (i.e., the block pointer array
538 /// holds enough room before the `fromBegin` position to insert 1
539 /// element).
540 template <class ALLOCATOR>
541 static void moveInsertAndMoveToFront(
542 Iterator *toBegin,
543 Iterator fromBegin,
544 Iterator position,
546 ALLOCATOR allocator);
547
548 /// Insert the specified move-insertable `value` at the specified
549 /// `position` by moving the elements in the range
550 /// `[fromBegin .. position)` backward by 1 position; pass the specified
551 /// `allocator` to the move constructor if appropriate. Load into the
552 /// specified `toBegin` an iterator to the inserted element (i.e.,
553 /// `fromBegin - 1`). The behavior is undefined unless
554 /// `fromBegin - 1` is a valid iterator (i.e., the block pointer array
555 /// holds enough room before the `fromBegin` position to insert 1
556 /// element). Note that the last argument is for removing overload
557 /// ambiguities and is not used.
558 template <class ALLOCATOR>
559 static void moveInsertAndMoveToFront(
560 Iterator *toBegin,
561 Iterator fromBegin,
562 Iterator position,
564 ALLOCATOR allocator,
566 template <class ALLOCATOR>
567 static void moveInsertAndMoveToFront(
568 Iterator *toBegin,
569 Iterator fromBegin,
570 Iterator position,
572 ALLOCATOR allocator,
574 template <class ALLOCATOR>
575 static void moveInsertAndMoveToFront(
576 Iterator *toBegin,
577 Iterator fromBegin,
578 Iterator position,
580 ALLOCATOR allocator,
582
583#if !BSLS_COMPILERFEATURES_SIMULATE_CPP11_FEATURES
584 /// Insert at the specified `position` a newly created `VALUE_TYPE`
585 /// object, constructed by forwarding the specified `allocator` (if
586 /// required) and the specified (variable number of) `arguments` to the
587 /// corresponding constructor of `VALUE_TYPE`, and move the elements in
588 /// the range `[position .. fromEnd)` forward by 1 position. Load into
589 /// the specified `toEnd` an iterator one past the inserted element
590 /// (i.e., `fromEnd + 1`). The behavior is undefined unless
591 /// `fromEnd + 1` is a valid iterator (i.e., the block pointer array
592 /// holds enough room after the `fromEnd` position to insert 1 element).
593 template <class ALLOCATOR, class... Args>
594 static void emplaceAndMoveToBack(Iterator *toEnd,
595 Iterator fromEnd,
596 Iterator position,
597 ALLOCATOR allocator,
598 Args&&... arguments);
599
600 /// Insert at the specified `position` a newly created `VALUE_TYPE`
601 /// object, constructed by forwarding the specified `allocator` (if
602 /// required) and the specified (variable number of) `arguments` to the
603 /// corresponding constructor of `VALUE_TYPE`, and move the elements in
604 /// the range `[position .. fromEnd)` forward by 1 position. Load into
605 /// the specified `toEnd` an iterator one past the inserted element
606 /// (i.e., `fromEnd + 1`). The behavior is undefined unless
607 /// `fromEnd + 1` is a valid iterator (i.e., the block pointer array
608 /// holds enough room after the `fromEnd` position to insert 1 element).
609 /// Note that the next to last argument is for removing overload
610 /// ambiguities and is not used.
611 template <class ALLOCATOR, class... Args>
613 Iterator *toEnd,
614 Iterator fromEnd,
615 Iterator position,
616 ALLOCATOR allocator,
618 Args&&... arguments);
619 template <class ALLOCATOR, class... Args>
621 Iterator *toEnd,
622 Iterator fromEnd,
623 Iterator position,
624 ALLOCATOR allocator,
626 Args&&... arguments);
627 template <class ALLOCATOR, class... Args>
629 Iterator *toEnd,
630 Iterator fromEnd,
631 Iterator position,
632 ALLOCATOR allocator,
634 Args&&... arguments);
635
636 /// Insert at the specified `position` a newly created `VALUE_TYPE`
637 /// object, constructed by forwarding the specified `allocator` (if
638 /// required) and the specified (variable number of) `arguments` to the
639 /// corresponding constructor of `VALUE_TYPE`, and move the elements in
640 /// the range `[fromBegin .. position)` backward by 1 position. Load
641 /// into the specified `toBegin` an iterator to the inserted element
642 /// (i.e., `fromBegin - 1`). The behavior is undefined unless
643 /// `fromBegin - 1` is a valid iterator (i.e., the block pointer array
644 /// holds enough room before the `fromBegin` position to insert 1
645 /// element).
646 template <class ALLOCATOR, class... Args>
647 static void emplaceAndMoveToFront(Iterator *toBegin,
648 Iterator fromBegin,
649 Iterator position,
650 ALLOCATOR allocator,
651 Args&&... arguments);
652
653 /// Insert at the specified `position` a newly created `VALUE_TYPE`
654 /// object, constructed by forwarding the specified `allocator` (if
655 /// required) and the specified (variable number of) `arguments` to the
656 /// corresponding constructor of `VALUE_TYPE`, and move the elements in
657 /// the range `[fromBegin .. position)` backward by 1 position. Load
658 /// into the specified `toBegin` an iterator to the inserted element
659 /// (i.e., `fromBegin - 1`). The behavior is undefined unless
660 /// `fromBegin - 1` is a valid iterator (i.e., the block pointer array
661 /// holds enough room before the `fromBegin` position to insert 1
662 /// element). Note that the next to last argument is for removing
663 /// overload ambiguities and is not used.
664 template <class ALLOCATOR, class... Args>
666 Iterator *toBegin,
667 Iterator fromBegin,
668 Iterator position,
669 ALLOCATOR allocator,
671 Args&&... arguments);
672 template <class ALLOCATOR, class... Args>
674 Iterator *toBegin,
675 Iterator fromBegin,
676 Iterator position,
677 ALLOCATOR allocator,
679 Args&&... arguments);
680 template <class ALLOCATOR, class... Args>
682 Iterator *toBegin,
683 Iterator fromBegin,
684 Iterator position,
685 ALLOCATOR allocator,
687 Args&&... arguments);
688#endif
689
690 /// Move the specified `numElements` from the specified `source` to the
691 /// specified `destination` using `std::memmove`. Also load into
692 /// `destination` the value `destination - numElements` and `source` the
693 /// value `source - numElements`. The behavior is undefined unless
694 /// `destination >= source`.
695 static void moveBack(Iterator *destination,
696 Iterator *source,
697 size_type numElements);
698
699 /// Move the specified `numElements` from the specified `source` to the
700 /// specified `destination` using `std::memmove`. Also load into
701 /// `destination` the value `destination + numElements` and `source` the
702 /// the value `source + numElements`. The behavior is undefined unless
703 /// `destination <= source`.
704 static void moveFront(Iterator *destination,
705 Iterator *source,
706 size_type numElements);
707
708 /// Append the specified `numElements` copies of the specified `value`
709 /// to the deque ending at the specified `fromEnd` iterator, passing the
710 /// specified `allocator` through to the new elements, and load into the
711 /// specified `toEnd` an iterator pointing to the end of the data after
712 /// appending (i.e., `fromEnd + numElements`). The behavior is
713 /// undefined unless `fromEnd + numElements` is a valid iterator (i.e.,
714 /// the block pointer array holds enough room after the `fromEnd`
715 /// position to insert `numElements`).
716 template <class ALLOCATOR>
717 static void uninitializedFillNBack(Iterator *toEnd,
718 Iterator fromEnd,
719 size_type numElements,
720 const VALUE_TYPE& value,
721 ALLOCATOR allocator);
722
723 /// Prepend the specified `numElements` copies of the specified `value`
724 /// to the deque starting at the specified `fromBegin` iterator, passing
725 /// the specified `allocator` through to the new elements, and load into
726 /// the specified `toBegin` an iterator pointing to the end of the data
727 /// after prepending, i.e., `fromBegin - numElements`. The behavior is
728 /// undefined unless `fromBegin - numElements` is a valid iterator
729 /// (i.e., the block pointer array holds enough room before the
730 /// `fromBegin` position to insert `numElements`).
731 template <class ALLOCATOR>
732 static void uninitializedFillNFront(Iterator *toBegin,
733 Iterator fromBegin,
734 size_type numElements,
735 const VALUE_TYPE& value,
736 ALLOCATOR allocator);
737
738 /// Append the specified `numElements` value-initialized objects to the
739 /// deque ending at the specified `fromEnd` iterator, passing the
740 /// specified `allocator` through to the new elements, and load into the
741 /// specified `toEnd` an iterator pointing to the end of the data after
742 /// appending (i.e., `fromEnd + numElements`). The behavior is
743 /// undefined unless `fromEnd + numElements` is a valid iterator (i.e.,
744 /// the block pointer array holds enough room after the `fromEnd`
745 /// position to insert `numElements`).
746 template <class ALLOCATOR>
747 static void valueInititalizeN(Iterator *toEnd,
748 Iterator fromEnd,
749 size_type numElements,
750 ALLOCATOR allocator);
751};
752
753// PARTIAL SPECIALIZATION
754
755/// This is a partial specialization of `DequePrimitives` for the case when
756/// there is a single element per block.
757template <class VALUE_TYPE>
758struct DequePrimitives<VALUE_TYPE, 1> {
759
760 // PUBLIC TYPES
761 typedef std::size_t size_type;
764
765 // CLASS METHODS
766 template <class ALLOCATOR>
767 static void destruct(Iterator begin, Iterator end, ALLOCATOR allocator);
768
769 template <class ALLOCATOR>
770 static Iterator erase(Iterator *toBegin,
771 Iterator *toEnd,
772 Iterator fromBegin,
773 Iterator first,
774 Iterator last,
775 Iterator fromEnd,
776 ALLOCATOR allocator);
777
778 template <class ALLOCATOR>
779 static void insertAndMoveToBack(Iterator *toEnd,
780 Iterator fromEnd,
781 Iterator position,
782 size_type numElements,
783 const VALUE_TYPE& value,
784 ALLOCATOR allocator);
785
786 template <class FWD_ITER, class ALLOCATOR>
787 static void insertAndMoveToBack(Iterator *toEnd,
788 Iterator fromEnd,
789 Iterator position,
790 FWD_ITER first,
791 FWD_ITER last,
792 size_type numElements,
793 ALLOCATOR allocator);
794
795 template <class ALLOCATOR>
796 static void insertAndMoveToFront(Iterator *toBegin,
797 Iterator fromBegin,
798 Iterator position,
799 size_type numElements,
800 const VALUE_TYPE& value,
801 ALLOCATOR allocator);
802
803 template <class FWD_ITER, class ALLOCATOR>
804 static void insertAndMoveToFront(Iterator *toBegin,
805 Iterator fromBegin,
806 Iterator position,
807 FWD_ITER first,
808 FWD_ITER last,
809 size_type numElements,
810 ALLOCATOR allocator);
811
812 template <class ALLOCATOR>
813 static void uninitializedFillNBack(Iterator *toEnd,
814 Iterator fromEnd,
815 size_type numElements,
816 const VALUE_TYPE& value,
817 ALLOCATOR allocator);
818 template <class ALLOCATOR>
819static void uninitializedFillNBack(
820 Iterator *toEnd,
821 Iterator fromEnd,
822 size_type numElements,
823 const VALUE_TYPE& value,
824 ALLOCATOR allocator,
826 template <class ALLOCATOR>
827 static void uninitializedFillNBack(
828 Iterator *toEnd,
829 Iterator fromEnd,
830 size_type numElements,
831 const VALUE_TYPE& value,
832 ALLOCATOR allocator,
834
835 template <class ALLOCATOR>
836 static void uninitializedFillNFront(Iterator *toBegin,
837 Iterator fromBegin,
838 size_type numElements,
839 const VALUE_TYPE& value,
840 ALLOCATOR allocator);
841 template <class ALLOCATOR>
842 static void uninitializedFillNFront(
843 Iterator *toBegin,
844 Iterator fromBegin,
845 size_type numElements,
846 const VALUE_TYPE& value,
847 ALLOCATOR allocator,
849 template <class ALLOCATOR>
850 static void uninitializedFillNFront(
851 Iterator *toBegin,
852 Iterator fromBegin,
853 size_type numElements,
854 const VALUE_TYPE& value,
855 ALLOCATOR allocator,
857
858 template <class ALLOCATOR>
859 static void valueInititalizeN(Iterator *toEnd,
860 Iterator fromEnd,
861 size_type numElements,
862 ALLOCATOR allocator);
863
864 template <class ALLOCATOR>
865 static void valueInititalizeN(
866 Iterator *toEnd,
867 Iterator fromEnd,
868 size_type numElements,
869 ALLOCATOR allocator,
871
872 template <class ALLOCATOR>
873 static void valueInititalizeN(
874 Iterator *toEnd,
875 Iterator fromEnd,
876 size_type numElements,
877 ALLOCATOR allocator,
879};
880
881 // =======================================
882 // class DequePrimitives_DequeElementGuard
883 // =======================================
884
885/// This `class` provides a specialized proctor object that, upon
886/// destruction and unless the `release` method has been called, destroys
887/// the elements in a segment of a deque of parameterized `VALUE_TYPE`. The
888/// elements destroyed are delimited by the "guarded" range
889/// `[d_begin .. d_end)`.
890///
891/// See @ref bslalg_dequeprimitives
892template <class VALUE_TYPE, int BLOCK_LENGTH, class ALLOCATOR>
894
895 public:
896 // PUBLIC TYPES
898
899 private:
900 // DATA
901 Iterator d_begin; // iterator of first element in guarded range
902 Iterator d_end; // iterator beyond last element in guarded range
903 ALLOCATOR d_allocator;
904
905 private:
906 // NOT IMPLEMENTED
911
912 public:
913 // CREATORS
914
915 /// Create a deque exception guard object for the sequence of elements
916 /// of the parameterized `VALUE_TYPE` delimited by the specified range
917 /// `[begin .. end)`. The behavior is undefined unless `begin <= end`
918 /// and unless each element in the range `[begin .. end)` has been
919 /// initialized.
921 const Iterator& end,
922 ALLOCATOR allocator);
923
924 /// Call the destructor on each of the elements of the parameterized
925 /// `VALUE_TYPE` delimited by the range `[begin .. end)` and destroy
926 /// this array exception guard.
928
929 // MANIPULATORS
930
931 /// Move the begin iterator by the specified `offset`, and return the
932 /// new begin iterator.
933 Iterator& moveBegin(std::ptrdiff_t offset = -1);
934
935 /// Move the end pointer by the specified `offset`, and return the new
936 /// end pointer.
937 Iterator& moveEnd(std::ptrdiff_t offset = 1);
938
939 /// Set the range of elements guarded by this object to be empty. Note
940 /// that `d_begin == d_end` following this operation, but the specific
941 /// value is unspecified.
942 void release();
943};
944
945 // ===============================================
946 // class DequePrimitives_ExternalDequeElementGuard
947 // ===============================================
948
949/// This `class` provides a specialized proctor object that, upon
950/// destruction and unless the `release` method has been called, destroys
951/// the elements in a segment of a `bsl::deque` of parameterized type
952/// `VALUE_TYPE`. The elements destroyed are delimited by the "guarded"
953/// range `[*d_begin .. *d_end)`. Note that the range guarded by this
954/// `class` is dynamic and can be changed outside of this `class`.
955///
956/// See @ref bslalg_dequeprimitives
957template <class VALUE_TYPE, int BLOCK_LENGTH, class ALLOCATOR>
959
960 public:
961 // PUBLIC TYPES
963
964 private:
965 // DATA
966 Iterator *d_begin_p; // pointer to iterator of first element in guarded
967 // range
968
969 Iterator *d_end_p; // pointer to iterator beyond last element in
970 // guarded range
971 ALLOCATOR d_allocator;
972
973 private:
974 // NOT IMPLEMENTED
979
980 public:
981 // CREATORS
982
983 /// Create a deque exception guard object for the sequence of elements
984 /// of the parameterized `VALUE_TYPE` delimited by the specified range
985 /// `[*begin .. *end)`. The behavior is undefined unless `*begin` <=
986 /// `*end` and unless each element in the range `[*begin .. *end)` has
987 /// been initialized.
989 Iterator *end,
990 ALLOCATOR allocator);
991
992 /// Call the destructor on each of the elements of the parameterized
993 /// `VALUE_TYPE` delimited by the range `[*d_begin_p .. *d_end_p)` and
994 /// destroy this array exception guard.
996
997 // MANIPULATORS
998
999 /// Set the range of elements guarded by this object to be empty. Note
1000 /// that `d_begin_p == d_end_p == 0` following this operation.
1001 void release();
1002};
1003
1004 // ====================================
1005 // class DequePrimitives_DequeMoveGuard
1006 // ====================================
1007
1008/// This `class` provides a guard object that, upon destruction and unless
1009/// the `release` method has been called, uses `moveBack` or `moveFront` to
1010/// move the "guarded" range `[d_source_p .. d_source_p + d_size - 1]`
1011/// back to `[d_destination_p .. d_destination_p + d_size -1]`.
1012///
1013/// See @ref bslalg_dequeprimitives
1014template <class VALUE_TYPE, int BLOCK_LENGTH>
1016
1017 public:
1018 // PUBLIC TYPES
1021
1022 private:
1023 // DATA
1024 Iterator d_destination_p; // destination of the move
1025 Iterator d_source_p; // source of the move
1026 std::size_t d_size; // size of the range being guarded
1027 bool d_front; // whether to use 'moveFront'
1028
1029 private:
1030 // NOT IMPLEMENTED
1034
1035 public:
1036 // CREATORS
1037
1038 /// Create a guard object that will call `moveBack` or `moveFront`,
1039 /// depending on the specified `isFront`, on the specified `size`
1040 /// elements from `src` to `dest` upon destruction unless `release` has
1041 /// been called.
1043 Iterator src,
1044 std::size_t size,
1045 bool isFront);
1046
1047 /// Call either `moveBack` or `moveFront` depending on `d_front` upon
1048 /// destruction unless `release` has been called before this.
1050
1051 // MANIPULATORS
1052
1053 /// Set the size of the range guarded by this object to be zero.
1054 void release();
1055};
1056
1057 // ==========================================
1058 // class DequePrimitives_DequeEndpointProctor
1059 // ==========================================
1060
1061/// This class implements a proctor that, upon destruction and unless its
1062/// `release` method has previously been invoked, sets a deque endpoint
1063/// (i.e., "start" or "finish" iterator) to a position within the deque.
1064/// Both the endpoint and position are supplied at construction. See
1065/// `emplaceAndMoveToBack` and `emplaceAndMoveToFront` for use cases.
1066///
1067/// See @ref bslalg_dequeprimitives
1068template <class VALUE_TYPE, int BLOCK_LENGTH>
1070
1071 public:
1072 // PUBLIC TYPES
1074
1075 private:
1076 // DATA
1077 Iterator *d_endpoint_p; // proctored endpoint of a deque
1078 Iterator d_position; // set endpoint to this upon destruction
1079
1080 private:
1081 // NOT IMPLEMENTED
1086
1087 public:
1088 // CREATORS
1089
1090 /// Create a deque endpoint proctor that conditionally manages the
1091 /// specified `endpoint` (if non-zero) by setting `*endpoint` to the
1092 /// specified `position` (if not released -- see `release`) upon
1093 /// destruction.
1095 Iterator position);
1096
1097 /// Destroy this endpoint proctor, and set the deque endpoint it manages
1098 /// (if any) to the position supplied at construction. If no endpoint
1099 /// is currently being managed, this method has no effect.
1101
1102 // MANIPULATORS
1103
1104 /// Release from management the deque endpoint currently managed by this
1105 /// proctor. If no endpoint is currently being managed, this method has
1106 /// no effect.
1107 void release();
1108};
1109
1110// ============================================================================
1111// INLINE FUNCTION DEFINITIONS
1112// ============================================================================
1113
1114 // ---------------------
1115 // class DequePrimitives
1116 // ---------------------
1117
1118// CLASS METHODS
1119template <class VALUE_TYPE, int BLOCK_LENGTH>
1120template <class ALLOCATOR>
1121inline
1123 Iterator end,
1124 ALLOCATOR allocator)
1125{
1126 enum {
1128
1129 VALUE = IS_BITWISECOPYABLE
1130 ? BITWISE_COPYABLE_TRAITS
1131 : NIL_TRAITS
1132 };
1133
1134 return destruct(begin,
1135 end,
1136 allocator,
1138}
1139
1140template <class VALUE_TYPE, int BLOCK_LENGTH>
1141template <class ALLOCATOR>
1150
1151template <class VALUE_TYPE, int BLOCK_LENGTH>
1152template <class ALLOCATOR>
1154 Iterator begin,
1155 Iterator end,
1156 ALLOCATOR allocator,
1158{
1159 for (; !(begin == end); ++begin) {
1161 begin.valuePtr());
1162 }
1163}
1164
1165template <class VALUE_TYPE, int BLOCK_LENGTH>
1166template <class ALLOCATOR>
1167inline
1168typename
1171 Iterator *toEnd,
1172 Iterator fromBegin,
1173 Iterator first,
1174 Iterator last,
1175 Iterator fromEnd,
1176 ALLOCATOR allocator)
1177{
1178 enum {
1180
1181 VALUE = IS_BITWISECOPYABLE
1182 ? BITWISE_COPYABLE_TRAITS
1183 : NIL_TRAITS
1184 };
1185
1186 return erase(toBegin,
1187 toEnd,
1188 fromBegin,
1189 first,
1190 last,
1191 fromEnd,
1192 allocator,
1194}
1195
1196template <class VALUE_TYPE, int BLOCK_LENGTH>
1197template <class ALLOCATOR>
1198typename
1201 Iterator *toBegin,
1202 Iterator *toEnd,
1203 Iterator fromBegin,
1204 Iterator first,
1205 Iterator last,
1206 Iterator fromEnd,
1207 ALLOCATOR allocator,
1209{
1210 if (first == last) { // Nothing to delete, bail out fast
1211 *toBegin = fromBegin;
1212 *toEnd = fromEnd;
1213 return first; // RETURN
1214 }
1215
1216 size_type frontSize = first - fromBegin;
1217 size_type backSize = fromEnd - last;
1218 Iterator ret;
1219
1220 if (frontSize < backSize) {
1221 ret = last;
1222 for (; 0 < frontSize; --frontSize) {
1223 --last;
1224 --first;
1225 *last = MoveUtil::move(*first);
1226 }
1227 *toBegin = last;
1228 *toEnd = fromEnd;
1229 }
1230 else {
1231 ret = first;
1232 for (; 0 < backSize; --backSize, ++first, ++last) {
1233 *first = MoveUtil::move(*last);
1234 }
1235 *toBegin = fromBegin;
1236 *toEnd = first;
1237 }
1238 destruct(first, last, allocator);
1239 return ret;
1240}
1241
1242template <class VALUE_TYPE, int BLOCK_LENGTH>
1243template <class ALLOCATOR>
1244typename
1247 Iterator *toBegin,
1248 Iterator *toEnd,
1249 Iterator fromBegin,
1250 Iterator first,
1251 Iterator last,
1252 Iterator fromEnd,
1253 ALLOCATOR,
1255{
1256 size_type frontSize = first - fromBegin;
1257 size_type backSize = fromEnd - last;
1258 Iterator ret;
1259
1260 if (frontSize < backSize) {
1261 ret = last;
1262 moveBack(&last, &first, frontSize);
1263 *toBegin = last;
1264 *toEnd = fromEnd;
1265 }
1266 else {
1267 ret = first;
1268 moveFront(&first, &last, backSize);
1269 *toBegin = fromBegin;
1270 *toEnd = first;
1271 }
1272 // 'destruct' is no-op for types with 'BITWISE_COPYABLE_TRAITS'.
1273 return ret;
1274}
1275
1276template <class VALUE_TYPE, int BLOCK_LENGTH>
1277template <class ALLOCATOR>
1278inline
1279void
1282 Iterator fromEnd,
1283 Iterator position,
1284 size_type numElements,
1285 const VALUE_TYPE& value,
1286 ALLOCATOR allocator)
1287{
1288 enum {
1291
1292 VALUE = IS_BITWISECOPYABLE
1293 ? BITWISE_COPYABLE_TRAITS : IS_BITWISEMOVEABLE
1294 ? BITWISE_MOVEABLE_TRAITS : NIL_TRAITS
1295 };
1296
1297 insertAndMoveToBack(toEnd,
1298 fromEnd,
1299 position,
1300 numElements,
1301 value,
1302 allocator,
1304}
1305
1306template <class VALUE_TYPE, int BLOCK_LENGTH>
1307template <class ALLOCATOR>
1308void
1310 Iterator *toEnd,
1311 Iterator fromEnd,
1312 Iterator position,
1313 size_type numElements,
1314 const VALUE_TYPE& value,
1315 ALLOCATOR allocator,
1317{
1318 size_type backSize = fromEnd - position;
1319 Iterator end = fromEnd;
1320 Iterator dest = end + numElements;
1321
1324 BSLS_UTIL_ADDRESSOF(space.object()),
1326 value);
1328 temp(BSLS_UTIL_ADDRESSOF(space.object()));
1329
1330 // TBD: this does the same thing as the old code - don't like that we
1331 // circumvent the whole allocator thing, but for now, let's keep it
1332 // consistent.
1333 // ConstructorProxy<VALUE_TYPE>
1334 // tempValue(value, bslma::Default::allocator());
1335
1336 // No guard needed since all the operations won't throw due to the
1337 // bitwise-copyable trait
1338 moveBack(&dest, &end, backSize);
1339 uninitializedFillNFront(&dest, dest, numElements, space.object(),
1340 allocator);
1341
1342 *toEnd = fromEnd + numElements;
1343}
1344
1345template <class VALUE_TYPE, int BLOCK_LENGTH>
1346template <class ALLOCATOR>
1347void
1349 Iterator *toEnd,
1350 Iterator fromEnd,
1351 Iterator position,
1352 size_type numElements,
1353 const VALUE_TYPE& value,
1354 ALLOCATOR allocator,
1356{
1358 BLOCK_LENGTH,
1359 ALLOCATOR> ExtGuard;
1360
1361
1362 size_type backSize = fromEnd - position;
1363 Iterator end = fromEnd;
1364 Iterator dest = end + numElements;
1365
1366 // In case of aliasing, make a copy of the value.
1369 BSLS_UTIL_ADDRESSOF(space.object()),
1371 value);
1373 temp(BSLS_UTIL_ADDRESSOF(space.object()));
1374
1375 // TBD: this does the same thing as the old code - don't like that we
1376 // circumvent the whole allocator thing, but for now, let's keep it
1377 // consistent.
1378 // ConstructorProxy<VALUE_TYPE>
1379 // tempValue(value, bslma::Default::allocator());
1380
1381 // Setup a reverse guard that will reverse the moveBack operation in case
1382 // of an exception.
1383 MoveGuard guard(end, dest, backSize, false);
1384
1385 moveBack(&dest, &end, backSize);
1386
1387 // Create a guard for 'uninitializedFillNBack' because it can throw under
1388 // 'bitwisemoveable' trait. Need to use this special guard because
1389 // uninitializedFillNFront is not exception safe.
1390 Iterator dest2(dest);
1391 ExtGuard eguard(&dest, &dest2, allocator);
1392
1393 uninitializedFillNFront(&dest, dest, numElements, space.object(),
1394 allocator);
1395 eguard.release();
1396 guard.release();
1397 *toEnd = fromEnd + numElements;
1398}
1399
1400template <class VALUE_TYPE, int BLOCK_LENGTH>
1401template <class ALLOCATOR>
1402void
1404 Iterator *toEnd,
1405 Iterator fromEnd,
1406 Iterator position,
1407 size_type numElements,
1408 const VALUE_TYPE& value,
1409 ALLOCATOR allocator,
1411{
1412 typedef DequePrimitives_DequeElementGuard<VALUE_TYPE,
1413 BLOCK_LENGTH,
1414 ALLOCATOR> ElementGuard;
1415
1416 size_type backSize = fromEnd - position;
1417 Iterator end = fromEnd;
1418 Iterator dest = end + numElements;
1419 size_type numDest;
1420
1421 // In case of aliasing, make a copy of the value.
1422
1426 value);
1428 temp(BSLS_UTIL_ADDRESSOF(space.object()));
1429
1430 // TBD: this does the same thing as the old code - don't like that we
1431 // circumvent the whole allocator thing, but for now, let's keep it
1432 // consistent.
1433 // ConstructorProxy<VALUE_TYPE> tempValue(value,
1434 // bslma::Default::allocator());
1435
1436 ElementGuard guard(dest, dest, allocator);
1437 if (backSize >= numElements) {
1438 for (numDest = numElements; 0 < numDest; --numDest) {
1439 --dest;
1440 --end;
1442 dest.valuePtr(),
1443 *end);
1444 guard.moveBegin(-1);
1445 }
1446 for (backSize -= numElements; 0 < backSize; --backSize) {
1447 --dest;
1448 --end;
1449 *dest = *end;
1450 }
1451 for (numDest = numElements; 0 < numDest; --numDest, ++position) {
1452 *position = space.object();
1453 }
1454 } else {
1455 for (numDest = backSize; 0 < numDest; --numDest) {
1456 --dest;
1457 --end;
1459 dest.valuePtr(),
1460 *end);
1461 guard.moveBegin(-1);
1462 }
1463 for (numDest = numElements; backSize < numDest; --numDest) {
1464 --dest;
1466 dest.valuePtr(),
1467 space.object());
1468
1469 guard.moveBegin(-1);
1470 }
1471 for (; 0 < numDest; --numDest, ++position) {
1472 *position = space.object();
1473 }
1474 }
1475 guard.release();
1476
1477 *toEnd = fromEnd + numElements;
1478}
1479
1480template <class VALUE_TYPE, int BLOCK_LENGTH>
1481template <class FWD_ITER, class ALLOCATOR>
1482void
1485 Iterator fromEnd,
1486 Iterator position,
1487 FWD_ITER first,
1488 FWD_ITER /*last*/,
1489 size_type numElements,
1490 ALLOCATOR allocator)
1491{
1492 typedef DequePrimitives_DequeElementGuard<VALUE_TYPE,
1493 BLOCK_LENGTH,
1494 ALLOCATOR> ElementGuard;
1495
1496 size_type backSize = fromEnd - position;
1497 Iterator end = fromEnd;
1498 Iterator dest = end + numElements;
1499 size_type numDest;
1500
1501 ElementGuard guard(dest, dest, allocator);
1502 if (backSize >= numElements) {
1503 for (numDest = numElements; 0 < numDest; --numDest) {
1504 --dest;
1505 --end;
1507 dest.valuePtr(),
1508 *end);
1509 guard.moveBegin(-1);
1510 }
1511 for (numDest = backSize; numElements < numDest; --numDest) {
1512 --dest;
1513 --end;
1514 *dest = *end;
1515 }
1516 for (; 0 < numDest; ++first, ++position, --numDest) {
1517 *position = *first;
1518 }
1519 } else {
1520 for (numDest = backSize; 0 < numDest; --numDest) {
1521 --dest;
1522 --end;
1524 dest.valuePtr(),
1525 *end);
1526 guard.moveBegin(-1);
1527 }
1528 for (numDest = backSize; 0 < numDest; --numDest, ++position, ++first) {
1529 *position = *first;
1530 }
1531 // Second guard needed because we're guarding from a different range.
1532 ElementGuard guard2(position, position, allocator);
1533 for (numDest = numElements; backSize < numDest; ++first, ++position,
1534 --numDest) {
1536 position.valuePtr(),
1537 *first);
1538 guard2.moveEnd(1);
1539 }
1540 guard2.release();
1541 }
1542 guard.release();
1543 *toEnd = fromEnd + numElements;
1544}
1545
1546template <class VALUE_TYPE, int BLOCK_LENGTH>
1547template <class ALLOCATOR>
1548inline
1549void
1551 Iterator *toEnd,
1552 Iterator fromEnd,
1553 Iterator position,
1555 ALLOCATOR allocator)
1556{
1557 enum {
1560
1561 VALUE = IS_BITWISECOPYABLE
1562 ? BITWISE_COPYABLE_TRAITS : IS_BITWISEMOVEABLE
1563 ? BITWISE_MOVEABLE_TRAITS : NIL_TRAITS
1564 };
1565
1566 VALUE_TYPE& lvalue = value;
1567
1568 moveInsertAndMoveToBack(toEnd,
1569 fromEnd,
1570 position,
1571 MoveUtil::move(lvalue),
1572 allocator,
1574}
1575
1576template <class VALUE_TYPE, int BLOCK_LENGTH>
1577template <class ALLOCATOR>
1578void
1580 Iterator *toEnd,
1581 Iterator fromEnd,
1582 Iterator position,
1584 ALLOCATOR allocator,
1586{
1587 const size_type backSize = fromEnd - position;
1588 Iterator end = fromEnd;
1589 Iterator dest = end + 1;
1590
1591 // No guard needed since no operations will throw with
1592 // 'BITWISE_COPYABLE_TRAITS'.
1593
1594 moveBack(&dest, &end, backSize);
1595 --dest;
1596
1597 VALUE_TYPE& lvalue = value;
1599 dest.valuePtr(),
1600 MoveUtil::move(lvalue));
1601
1602 *toEnd = fromEnd + 1;
1603}
1604
1605template <class VALUE_TYPE, int BLOCK_LENGTH>
1606template <class ALLOCATOR>
1607void
1609 Iterator *toEnd,
1610 Iterator fromEnd,
1611 Iterator position,
1613 ALLOCATOR allocator,
1615{
1616 const size_type backSize = fromEnd - position;
1617 Iterator end = fromEnd;
1618 Iterator dest = end + 1;
1619
1620 // Create a reverse guard that will undo the 'moveBack' operation in case
1621 // of an exception.
1622
1623 MoveGuard guard(end, dest, backSize, false);
1624
1625 moveBack(&dest, &end, backSize);
1626 --dest;
1627
1628 VALUE_TYPE& lvalue = value;
1630 dest.valuePtr(),
1631 MoveUtil::move(lvalue));
1632
1633 guard.release();
1634
1635 *toEnd = fromEnd + 1;
1636}
1637
1638template <class VALUE_TYPE, int BLOCK_LENGTH>
1639template <class ALLOCATOR>
1640void
1642 Iterator *toEnd,
1643 Iterator fromEnd,
1644 Iterator position,
1646 ALLOCATOR allocator,
1648{
1649 typedef DequePrimitives_DequeElementGuard<VALUE_TYPE,
1650 BLOCK_LENGTH,
1651 ALLOCATOR> ElementGuard;
1652
1653 size_type backSize = fromEnd - position;
1654 Iterator end = fromEnd;
1655 Iterator dest = end + 1;
1656
1657 BSLS_ASSERT_SAFE(backSize >= 1);
1658
1659 ElementGuard guard(dest, dest, allocator);
1660
1661 // 1. move-construct back-most element being bumped 1 slot
1662
1663 --dest;
1664 --end;
1666 allocator,
1667 dest.valuePtr(),
1668 MoveUtil::move_if_noexcept(*end));
1669 guard.moveBegin(-1);
1670
1671 // 2. move-assign other existing elements being bumped back 1 slot
1672
1673 for (backSize -= 1; 0 < backSize; --backSize) {
1674 --dest;
1675 --end;
1676 *dest = MoveUtil::move_if_noexcept(*end);
1677 }
1678
1679 // 3. move-assign new element
1680
1681 VALUE_TYPE& lvalue = value;
1682 *position = MoveUtil::move(lvalue);
1683
1684 guard.release();
1685
1686 *toEnd = fromEnd + 1;
1687}
1688
1689template <class VALUE_TYPE, int BLOCK_LENGTH>
1690template <class ALLOCATOR>
1691inline
1692void
1695 Iterator fromBegin,
1696 Iterator position,
1697 size_type numElements,
1698 const VALUE_TYPE& value,
1699 ALLOCATOR allocator)
1700{
1701 enum {
1704
1705 VALUE = IS_BITWISECOPYABLE
1706 ? BITWISE_COPYABLE_TRAITS : IS_BITWISEMOVEABLE
1707 ? BITWISE_MOVEABLE_TRAITS : NIL_TRAITS
1708 };
1709
1710 insertAndMoveToFront(toBegin,
1711 fromBegin,
1712 position,
1713 numElements,
1714 value,
1715 allocator,
1717}
1718
1719template <class VALUE_TYPE, int BLOCK_LENGTH>
1720template <class ALLOCATOR>
1721void
1723 Iterator *toBegin,
1724 Iterator fromBegin,
1725 Iterator position,
1726 size_type numElements,
1727 const VALUE_TYPE& value,
1728 ALLOCATOR allocator,
1730{
1731 size_type frontSize = position - fromBegin;
1732 Iterator begin = fromBegin;
1733 Iterator dest = begin - numElements;
1734
1735 // In case of aliasing, make a copy of the value.
1739 value);
1741 temp(BSLS_UTIL_ADDRESSOF(space.object()));
1742
1743 // TBD: this does the same thing as the old code - don't like that we
1744 // circumvent the whole allocator thing, but for now, let's keep it
1745 // consistent.
1746 // ConstructorProxy<VALUE_TYPE>
1747 // tempValue(value, bslma::Default::allocator());
1748
1749 // No guard needed since all the operations won't throw due to the
1750 // bitwise-copyable trait
1751 moveFront(&dest, &begin, frontSize);
1752 uninitializedFillNBack(&dest, dest, numElements, space.object(),
1753 allocator);
1754
1755 *toBegin = fromBegin - numElements;
1756}
1757
1758template <class VALUE_TYPE, int BLOCK_LENGTH>
1759template <class ALLOCATOR>
1760void
1762 Iterator *toBegin,
1763 Iterator fromBegin,
1764 Iterator position,
1765 size_type numElements,
1766 const VALUE_TYPE& value,
1767 ALLOCATOR allocator,
1769{
1771 BLOCK_LENGTH,
1772 ALLOCATOR> ExtGuard;
1773 size_type frontSize = position - fromBegin;
1774 Iterator begin = fromBegin;
1775 Iterator dest = begin - numElements;
1776
1777 // In case of aliasing, make a copy of the value.
1781 value);
1783 temp(BSLS_UTIL_ADDRESSOF(space.object()));
1784
1785 // TBD: this does the same thing as the old code - don't like that we
1786 // circumvent the whole allocator thing, but for now, let's keep it
1787 // consistent.
1788 // ConstructorProxy<VALUE_TYPE>
1789 // tempValue(value, bslma::Default::allocator());
1790
1791 // Create a reverse guard that will reverse the moveFront operation in case
1792 // of an exception.
1793 MoveGuard guard(begin, dest, frontSize, true);
1794
1795 moveFront(&dest, &begin, frontSize);
1796
1797 // Create a guard for 'uninitializedFillNBack' because it can throw under
1798 // 'bitwisemoveable' trait. Need to use this special guard because
1799 // uninitializedFillNBack is not exception safe.
1800 Iterator dest2(dest);
1801 ExtGuard eguard(&dest2, &dest, allocator);
1802
1803 uninitializedFillNBack(&dest, dest, numElements, space.object(),
1804 allocator);
1805
1806 eguard.release();
1807 guard.release();
1808 *toBegin = fromBegin - numElements;
1809}
1810
1811template <class VALUE_TYPE, int BLOCK_LENGTH>
1812template <class ALLOCATOR>
1813void
1815 Iterator *toBegin,
1816 Iterator fromBegin,
1817 Iterator position,
1818 size_type numElements,
1819 const VALUE_TYPE& value,
1820 ALLOCATOR allocator,
1822{
1823 typedef DequePrimitives_DequeElementGuard<VALUE_TYPE,
1824 BLOCK_LENGTH,
1825 ALLOCATOR> ElementGuard;
1826
1827 size_type frontSize = position - fromBegin;
1828 Iterator begin = fromBegin;
1829 Iterator dest = begin - numElements;
1830 size_type numDest;
1831
1832 // In case of aliasing, make a copy of the value.
1836 value);
1838 temp(BSLS_UTIL_ADDRESSOF(space.object()));
1839
1840 // TBD: this does the same thing as the old code - don't like that we
1841 // circumvent the whole allocator thing, but for now, let's keep it
1842 // consistent.
1843 // ConstructorProxy<VALUE_TYPE>
1844 // tempValue(value, bslma::Default::allocator());
1845
1846 ElementGuard guard(dest, dest, allocator);
1847 if (frontSize >= numElements) {
1848 for (numDest = numElements; 0 < numDest; --numDest, ++dest, ++begin) {
1850 dest.valuePtr(),
1851 *begin);
1852 guard.moveEnd(1);
1853 }
1854 for (frontSize -= numElements; 0 < frontSize;
1855 --frontSize, ++dest, ++begin) {
1856 *dest = *begin;
1857 }
1858 for (numDest = numElements; 0 < numDest; --numDest, ++dest) {
1859 *dest = space.object();
1860 }
1861 } else {
1862 for (numDest = frontSize; 0 < numDest; --numDest, ++dest, ++begin) {
1864 dest.valuePtr(),
1865 *begin);
1866 guard.moveEnd(1);
1867 }
1868 for (numDest = numElements; frontSize < numDest; --numDest, ++dest) {
1870 dest.valuePtr(),
1871 space.object());
1872 guard.moveEnd(1);
1873 }
1874 for (; 0 < numDest; --numDest, ++dest) {
1875 *dest = space.object();
1876 }
1877 }
1878 guard.release();
1879 *toBegin = fromBegin - numElements;
1880}
1881
1882template <class VALUE_TYPE, int BLOCK_LENGTH>
1883template <class FWD_ITER, class ALLOCATOR>
1884void
1887 Iterator fromBegin,
1888 Iterator position,
1889 FWD_ITER first,
1890 FWD_ITER /*last*/,
1891 size_type numElements,
1892 ALLOCATOR allocator)
1893{
1894 typedef DequePrimitives_DequeElementGuard<VALUE_TYPE,
1895 BLOCK_LENGTH,
1896 ALLOCATOR> ElementGuard;
1897
1898 size_type frontSize = position - fromBegin;
1899 Iterator begin = fromBegin;
1900 Iterator dest = begin - numElements;
1901 size_type numDest;
1902
1903 ElementGuard guard(dest, dest, allocator);
1904 if (frontSize >= numElements) {
1905 for (numDest = numElements; 0 < numDest; --numDest, ++dest, ++begin) {
1907 dest.valuePtr(),
1908 *begin);
1909 guard.moveEnd(1);
1910 }
1911 for (frontSize -= numElements; 0 < frontSize;
1912 --frontSize, ++dest, ++begin) {
1913 *dest = *begin;
1914 }
1915 for (numDest = numElements; 0 < numDest; --numDest, ++dest, ++first) {
1916 *dest = *first;
1917 }
1918 } else {
1919 for (numDest = frontSize; 0 < numDest; --numDest, ++dest, ++begin) {
1921 dest.valuePtr(),
1922 *begin);
1923 guard.moveEnd(1);
1924 }
1925 for (numDest = numElements; frontSize < numDest;
1926 --numDest, ++dest, ++first) {
1928 dest.valuePtr(),
1929 *first);
1930 guard.moveEnd(1);
1931 }
1932 for (; 0 < numDest; --numDest, ++dest, ++first) {
1933 *dest = *first;
1934 }
1935 }
1936 guard.release();
1937 *toBegin = fromBegin - numElements;
1938}
1939
1940template <class VALUE_TYPE, int BLOCK_LENGTH>
1941template <class ALLOCATOR>
1942inline
1943void
1945 Iterator *toBegin,
1946 Iterator fromBegin,
1947 Iterator position,
1949 ALLOCATOR allocator)
1950{
1951 enum {
1954
1955 VALUE = IS_BITWISECOPYABLE
1956 ? BITWISE_COPYABLE_TRAITS : IS_BITWISEMOVEABLE
1957 ? BITWISE_MOVEABLE_TRAITS : NIL_TRAITS
1958 };
1959
1960 VALUE_TYPE& lvalue = value;
1961
1962 moveInsertAndMoveToFront(toBegin,
1963 fromBegin,
1964 position,
1965 MoveUtil::move(lvalue),
1966 allocator,
1968}
1969
1970template <class VALUE_TYPE, int BLOCK_LENGTH>
1971template <class ALLOCATOR>
1972void
1974 Iterator *toBegin,
1975 Iterator fromBegin,
1976 Iterator position,
1978 ALLOCATOR allocator,
1980{
1981 const size_type frontSize = position - fromBegin;
1982 Iterator begin = fromBegin;
1983 Iterator dest = begin - 1;
1984
1985 // No guard needed since no operations will throw with
1986 // 'BITWISE_COPYABLE_TRAITS'.
1987
1988 moveFront(&dest, &begin, frontSize);
1989
1990 VALUE_TYPE& lvalue = value;
1992 dest.valuePtr(),
1993 MoveUtil::move(lvalue));
1994
1995 *toBegin = fromBegin - 1;
1996}
1997
1998template <class VALUE_TYPE, int BLOCK_LENGTH>
1999template <class ALLOCATOR>
2000void
2002 Iterator *toBegin,
2003 Iterator fromBegin,
2004 Iterator position,
2006 ALLOCATOR allocator,
2008{
2009 const size_type frontSize = position - fromBegin;
2010 Iterator begin = fromBegin;
2011 Iterator dest = begin - 1;
2012
2013 // Create a reverse guard that will undo the 'moveFront' operation in case
2014 // of an exception.
2015
2016 MoveGuard guard(begin, dest, frontSize, true);
2017
2018 moveFront(&dest, &begin, frontSize);
2019
2020 VALUE_TYPE& lvalue = value;
2022 dest.valuePtr(),
2023 MoveUtil::move(lvalue));
2024
2025 guard.release();
2026
2027 *toBegin = fromBegin - 1;
2028}
2029
2030template <class VALUE_TYPE, int BLOCK_LENGTH>
2031template <class ALLOCATOR>
2032void
2034 Iterator *toBegin,
2035 Iterator fromBegin,
2036 Iterator position,
2038 ALLOCATOR allocator,
2040{
2041 typedef DequePrimitives_DequeElementGuard<VALUE_TYPE,
2042 BLOCK_LENGTH,
2043 ALLOCATOR> ElementGuard;
2044
2045 size_type frontSize = position - fromBegin;
2046 Iterator begin = fromBegin;
2047 Iterator dest = begin - 1;
2048
2049 BSLS_ASSERT_SAFE(frontSize >= 1);
2050
2051 ElementGuard guard(dest, dest, allocator);
2052
2053 // 1. move-construct front-most element being bumped 1 slot
2054
2056 allocator,
2057 dest.valuePtr(),
2058 MoveUtil::move_if_noexcept(*begin));
2059 guard.moveEnd(1);
2060 ++dest;
2061 ++begin;
2062
2063 // 2. move-assign other existing elements being bumped forward 1 slot
2064
2065 for (frontSize -= 1; 0 < frontSize; --frontSize, ++dest, ++begin) {
2066 *dest = MoveUtil::move_if_noexcept(*begin);
2067 }
2068
2069 // 3. move-assign the new element
2070
2071 VALUE_TYPE& lvalue = value;
2072 *dest = MoveUtil::move(lvalue);
2073
2074 guard.release();
2075
2076 *toBegin = fromBegin - 1;
2077}
2078
2079#if !BSLS_COMPILERFEATURES_SIMULATE_CPP11_FEATURES
2080template <class VALUE_TYPE, int BLOCK_LENGTH>
2081template <class ALLOCATOR, class... Args>
2082inline
2083void
2085 Iterator *toEnd,
2086 Iterator fromEnd,
2087 Iterator position,
2088 ALLOCATOR allocator,
2089 Args&&... arguments)
2090{
2091 enum {
2094
2095 VALUE = IS_BITWISECOPYABLE
2096 ? BITWISE_COPYABLE_TRAITS : IS_BITWISEMOVEABLE
2097 ? BITWISE_MOVEABLE_TRAITS : NIL_TRAITS
2098 };
2099
2100 emplaceAndMoveToBackDispatch(
2101 toEnd,
2102 fromEnd,
2103 position,
2104 allocator,
2106 BSLS_COMPILERFEATURES_FORWARD(Args, arguments)...);
2107}
2108
2109template <class VALUE_TYPE, int BLOCK_LENGTH>
2110template <class ALLOCATOR, class... Args>
2111void
2113 Iterator *toEnd,
2114 Iterator fromEnd,
2115 Iterator position,
2116 ALLOCATOR allocator,
2118 Args&&... arguments)
2119{
2120 const size_type backSize = fromEnd - position;
2121 Iterator end = fromEnd;
2122 Iterator dest = end + 1;
2123
2124 // No guard needed since no operations will throw with
2125 // 'BITWISE_COPYABLE_TRAITS'.
2126
2127 moveBack(&dest, &end, backSize);
2128 --dest;
2129
2131 allocator,
2132 dest.valuePtr(),
2133 BSLS_COMPILERFEATURES_FORWARD(Args, arguments)...);
2134
2135 *toEnd = fromEnd + 1;
2136}
2137
2138template <class VALUE_TYPE, int BLOCK_LENGTH>
2139template <class ALLOCATOR, class... Args>
2140void
2142 Iterator *toEnd,
2143 Iterator fromEnd,
2144 Iterator position,
2145 ALLOCATOR allocator,
2147 Args&&... arguments)
2148{
2149 const size_type backSize = fromEnd - position;
2150 Iterator end = fromEnd;
2151 Iterator dest = end + 1;
2152
2153 // Create a reverse guard that will undo the 'moveBack' operation in case
2154 // of an exception.
2155
2156 MoveGuard guard(end, dest, backSize, false);
2157
2158 moveBack(&dest, &end, backSize);
2159 --dest;
2160
2162 allocator,
2163 dest.valuePtr(),
2164 BSLS_COMPILERFEATURES_FORWARD(Args, arguments)...);
2165
2166 guard.release();
2167
2168 *toEnd = fromEnd + 1;
2169}
2170
2171template <class VALUE_TYPE, int BLOCK_LENGTH>
2172template <class ALLOCATOR, class... Args>
2173void
2175 Iterator *toEnd,
2176 Iterator fromEnd,
2177 Iterator position,
2178 ALLOCATOR allocator,
2180 Args&&... arguments)
2181{
2182 typedef DequePrimitives_DequeElementGuard<VALUE_TYPE,
2183 BLOCK_LENGTH,
2184 ALLOCATOR> ElementGuard;
2185
2186 typedef DequePrimitives_DequeEndpointProctor<VALUE_TYPE,
2187 BLOCK_LENGTH> EndpointProctor;
2188
2189 size_type backSize = fromEnd - position;
2190 Iterator end = fromEnd;
2191 Iterator dest = end + 1;
2192
2193 BSLS_ASSERT_SAFE(backSize >= 1);
2194
2195 ElementGuard guard(dest, dest, allocator);
2196
2197 // 1. move-construct back-most element being bumped 1 slot
2198
2199 --dest;
2200 --end;
2202 allocator,
2203 dest.valuePtr(),
2204 MoveUtil::move_if_noexcept(*end));
2205 guard.moveBegin(-1);
2206
2207 // 2. move-assign other existing elements being bumped back 1 slot
2208
2209 size_type n = 0; // additional elements to guard following 'for' loop
2210 for (backSize -= 1; 0 < backSize; --backSize) {
2211 --dest;
2212 --end;
2213 *dest = MoveUtil::move_if_noexcept(*end);
2214 ++n;
2215 }
2216 guard.moveBegin(-n); // in case the emplacement (below) throws
2217
2218 // 3. destroy element in emplacement slot
2219
2221
2222 // 4. emplace the new element
2223
2224 // If emplacement throws, lop off the '[position .. *toEnd)' portion of the
2225 // deque because a hole was just created that cannot be repopulated.
2226
2227 EndpointProctor endpointProctor(toEnd, position);
2228
2230 allocator,
2231 position.valuePtr(),
2232 BSLS_COMPILERFEATURES_FORWARD(Args, arguments)...);
2233
2234 endpointProctor.release();
2235 guard.release();
2236
2237 *toEnd = fromEnd + 1;
2238}
2239
2240template <class VALUE_TYPE, int BLOCK_LENGTH>
2241template <class ALLOCATOR, class... Args>
2242inline
2243void
2245 Iterator *toBegin,
2246 Iterator fromBegin,
2247 Iterator position,
2248 ALLOCATOR allocator,
2249 Args&&... arguments)
2250{
2251 enum {
2254
2255 VALUE = IS_BITWISECOPYABLE
2256 ? BITWISE_COPYABLE_TRAITS : IS_BITWISEMOVEABLE
2257 ? BITWISE_MOVEABLE_TRAITS : NIL_TRAITS
2258 };
2259
2260 emplaceAndMoveToFrontDispatch(
2261 toBegin,
2262 fromBegin,
2263 position,
2264 allocator,
2266 BSLS_COMPILERFEATURES_FORWARD(Args, arguments)...);
2267}
2268
2269template <class VALUE_TYPE, int BLOCK_LENGTH>
2270template <class ALLOCATOR, class... Args>
2271void
2273 Iterator *toBegin,
2274 Iterator fromBegin,
2275 Iterator position,
2276 ALLOCATOR allocator,
2278 Args&&... arguments)
2279{
2280 const size_type frontSize = position - fromBegin;
2281 Iterator begin = fromBegin;
2282 Iterator dest = begin - 1;
2283
2284 // No guard needed since no operations will throw with
2285 // 'BITWISE_COPYABLE_TRAITS'.
2286
2287 moveFront(&dest, &begin, frontSize);
2288
2290 allocator,
2291 dest.valuePtr(),
2292 BSLS_COMPILERFEATURES_FORWARD(Args, arguments)...);
2293
2294 *toBegin = fromBegin - 1;
2295}
2296
2297template <class VALUE_TYPE, int BLOCK_LENGTH>
2298template <class ALLOCATOR, class... Args>
2299void
2301 Iterator *toBegin,
2302 Iterator fromBegin,
2303 Iterator position,
2304 ALLOCATOR allocator,
2306 Args&&... arguments)
2307{
2308 const size_type frontSize = position - fromBegin;
2309 Iterator begin = fromBegin;
2310 Iterator dest = begin - 1;
2311
2312 // Create a reverse guard that will undo the 'moveFront' operation in case
2313 // of an exception.
2314
2315 MoveGuard guard(begin, dest, frontSize, true);
2316
2317 moveFront(&dest, &begin, frontSize);
2318
2320 allocator,
2321 dest.valuePtr(),
2322 BSLS_COMPILERFEATURES_FORWARD(Args, arguments)...);
2323
2324 guard.release();
2325
2326 *toBegin = fromBegin - 1;
2327}
2328
2329template <class VALUE_TYPE, int BLOCK_LENGTH>
2330template <class ALLOCATOR, class... Args>
2331void
2333 Iterator *toBegin,
2334 Iterator fromBegin,
2335 Iterator position,
2336 ALLOCATOR allocator,
2338 Args&&... arguments)
2339{
2340 typedef DequePrimitives_DequeElementGuard<VALUE_TYPE,
2341 BLOCK_LENGTH,
2342 ALLOCATOR> ElementGuard;
2343
2344 typedef DequePrimitives_DequeEndpointProctor<VALUE_TYPE,
2345 BLOCK_LENGTH> EndpointProctor;
2346
2347 size_type frontSize = position - fromBegin;
2348 Iterator begin = fromBegin;
2349 Iterator dest = begin - 1;
2350
2351 BSLS_ASSERT_SAFE(frontSize >= 1);
2352
2353 ElementGuard guard(dest, dest, allocator);
2354
2355 // 1. move-construct front-most element being bumped 1 slot
2356
2358 allocator,
2359 dest.valuePtr(),
2360 MoveUtil::move_if_noexcept(*begin));
2361 guard.moveEnd(1);
2362 ++dest;
2363 ++begin;
2364
2365 // 2. move-assign other existing elements being bumped forward 1 slot
2366
2367 size_type n = 0; // additional elements to guard following 'for' loop
2368 for (frontSize -= 1; 0 < frontSize; --frontSize, ++dest, ++begin) {
2369 *dest = MoveUtil::move_if_noexcept(*begin);
2370 ++n;
2371 }
2372 guard.moveEnd(n); // in case the emplacement (below) throws
2373
2374 // 3. destroy element in emplacement slot
2375
2377
2378 // 4. emplace the new element
2379
2380 // If emplacement throws, lop off the '[*toBegin .. position)' portion the
2381 // the deque because a hole was just created that cannot be repopulated.
2382
2383 EndpointProctor endpointProctor(toBegin, position);
2384
2386 allocator,
2387 dest.valuePtr(),
2388 BSLS_COMPILERFEATURES_FORWARD(Args, arguments)...);
2389
2390 endpointProctor.release();
2391 guard.release();
2392
2393 *toBegin = fromBegin - 1;
2394}
2395#endif
2396
2397template <class VALUE_TYPE, int BLOCK_LENGTH>
2400 Iterator *source,
2401 size_type numElements)
2402{
2403 if (destination->offsetInBlock() > numElements
2404 && source->offsetInBlock() > numElements) {
2405 // There is enough room to move everything at once.
2406
2407 *destination -= numElements;
2408 *source -= numElements;
2409 std::memmove((void *)destination->valuePtr(),
2410 source->valuePtr(),
2411 numElements * sizeof(VALUE_TYPE));
2412
2413 return; // RETURN
2414 }
2415
2416 // Moving the blocks involving segments of 3 different lengths, as
2417 // illustrated below. We need to distinguish whether destination or the
2418 // source have more space remaining, and adjust the algorithm accordingly.
2419 //..
2420 // [--- n ---] - segment 'n'
2421 // [--- n'---] - segment with equal length as 'n'.
2422 // [--- n ---I-- m --] - two segments, with length 'n' and 'm'.
2423 // - - - - - - - -
2424 // | | | | | | | | | - a block in the deque pointed by a 'blockPtr'
2425 // - - - - - - - -
2426 //..
2427 //
2428 // Scenario 1: Source has less element than destination has space
2429 // ==============================================================
2430 // Under this scenario, we have to move all elements from the source block
2431 // to the destination block first (segment 1), then fill the destination
2432 // block with the remaining elements (segment 2). After, we alternate
2433 // between segments 3 and 2.
2434 //..
2435 // [--- 3 ---I- 2'-] [- 1 -] [- 2 -I- 1'-]
2436 // - - - - - - - - - - - - - - - - - - - - - - - -
2437 // |d|e|f|g|h|i|j|k| |a|b|c|/| | | | | | | | | | | | | |
2438 // - - - - - - - - - - - - - - - - - - - - - - - -
2439 // ^ ^
2440 // source ____| destination _____|
2441 //..
2442 //
2443 // Scenario 2: Source has more elements than destination has space
2444 // ================================================================
2445 // Under this scenario, we can only move some elements (the number of
2446 // elements that can fit in the destination block) from the source block to
2447 // the destination block first (segment 1), then move the remaining
2448 // elements (segment 2) from the source block. After, we alternate between
2449 // segments 3 and 2.
2450 //..
2451 // [---- 3 ----]
2452 // [---- 3' ---] [-2-I- 1 -] [2' ] [- 1 -]
2453 // - - - - - - - - - - - - - - - - - - - - - - - -
2454 // |d|e|f|g|h|i|j|k| |a|b|c|d|e|/| | | | | | | | | | | |
2455 // - - - - - - - - - - - - - - - - - - - - - - - -
2456 // ^ ^
2457 // source _____| destination _|
2458 //
2459 // 1) Copy segment 1
2460 // 2) Copy segment 2
2461 // 3) Copy segment 3
2462 // 4) Repeat 2, 3 until there's less than 1 'BLOCK_LENGTH' left
2463 // 5) Copy the remaining items over
2464 //..
2465
2466 size_type firstSegment, secondSegment;
2467 if (source->offsetInBlock() > destination->offsetInBlock()) {
2468 firstSegment = destination->offsetInBlock();
2469 secondSegment = source->offsetInBlock() - firstSegment;
2470 }
2471 else {
2472 firstSegment = source->offsetInBlock();
2473 secondSegment = destination->offsetInBlock() - firstSegment;
2474 }
2475
2476 size_type thirdSegment = BLOCK_LENGTH - secondSegment;
2477
2478 *destination -= firstSegment;
2479 *source -= firstSegment;
2480 numElements -= firstSegment;
2481
2482 std::memmove((void *)destination->valuePtr(),
2483 source->valuePtr(),
2484 firstSegment * sizeof(VALUE_TYPE));
2485
2486 for (; numElements >= BLOCK_LENGTH; numElements -= BLOCK_LENGTH) {
2487
2488 *destination -= secondSegment;
2489 *source -= secondSegment;
2490
2491 std::memmove((void *)destination->valuePtr(),
2492 source->valuePtr(),
2493 secondSegment * sizeof(VALUE_TYPE));
2494
2495 *destination -= thirdSegment;
2496 *source -= thirdSegment;
2497
2498 std::memmove((void *)destination->valuePtr(),
2499 source->valuePtr(),
2500 thirdSegment * sizeof(VALUE_TYPE));
2501 }
2502
2503 size_type remaining = numElements > secondSegment
2504 ? secondSegment
2505 : numElements;
2506
2507 *destination -= remaining;
2508 *source -= remaining;
2509 numElements -= remaining;
2510
2511 std::memmove((void *)destination->valuePtr(),
2512 source->valuePtr(),
2513 remaining * sizeof(VALUE_TYPE));
2514
2515 *destination -= numElements;
2516 *source -= numElements;
2517
2518 std::memmove((void *)destination->valuePtr(),
2519 source->valuePtr(),
2520 numElements * sizeof(VALUE_TYPE));
2521}
2522
2523template <class VALUE_TYPE, int BLOCK_LENGTH>
2526 Iterator *source,
2527 size_type numElements)
2528{
2529 if (destination->remainingInBlock() > numElements
2530 && source->remainingInBlock() > numElements) {
2531 // There is enough room to move everything at once
2532
2533 std::memmove((void *)destination->valuePtr(),
2534 source->valuePtr(),
2535 numElements * sizeof(VALUE_TYPE));
2536 *destination += numElements;
2537 *source += numElements;
2538
2539 return; // RETURN
2540 }
2541
2542 // Moving the blocks involving segments of 3 different lengths, as
2543 // illustrated below. We need to distinguish whether destination or the
2544 // source have more space remaining, and adjust the algorithm accordingly.
2545 //..
2546 // [--- n ---] - segment 'n'
2547 // [--- n'---] - segment with equal length as 'n'
2548 // [--- n ---I-- m --] - two segments, with length 'n' and 'm'.
2549 // - - - - - - - -
2550 // | | | | | | | | | - a block in the deque pointed by a 'blockPtr'
2551 // - - - - - - - -
2552 //..
2553 //
2554 // Scenario 1: Source has more elements than destination has space
2555 // ===============================================================
2556 // Under this scenario, we can only move some elements (the number of
2557 // elements that can fit in the destination block) from the source block to
2558 // the destination block first (segment 1), then move the remaining
2559 // elements (segment 2) from the source block. After, we alternate between
2560 // segments 3 and 2.
2561 //..
2562 // [---- 3 ----]
2563 // [- 1 -] [ 2'] [- 1'-I-2-] [---- 3'----]
2564 // - - - - - - - - - - - - - - - - - - - - - - - -
2565 // | | | | | | | | | | | | |a|a|b|c|d| |e|f|g|h|i|j|k|l|
2566 // - - - - - - - - - - - - - - - - - - - - - - - -
2567 // ^ ^
2568 // |_ destination |____ source
2569 //..
2570 //
2571 // Scenario 2: Source has less elements than destination has space
2572 // ===============================================================
2573 // Under this scenario, we have to move all elements from the source block
2574 // to the destination block first (segment 1), then fill the destination
2575 // block with the remaining elements (segment 2). After, we alternate
2576 // between segments 3 and 2.
2577 //..
2578 // [- 1'-I- 2 -] [--- 3'---I- 1 -] [- 2'-I--- 3 ---]
2579 // - - - - - - - - - - - - - - - - - - - - - - - -
2580 // | | | | | | | | | | | | | | |a|b|c| |d|e|f|g|h|i|j|k|
2581 // - - - - - - - - - - - - - - - - - - - - - - - -
2582 // ^ ^
2583 // |_ destination |____ source
2584 //
2585 // 1) Copy segment 1
2586 // 2) Copy segment 2
2587 // 3) Copy segment 3
2588 // 4) Repeat 2, 3 until there's less than 1 'BLOCK_LENGTH' left
2589 // 5) Copy the remaining items over
2590 //..
2591
2592 size_type firstSegment, secondSegment;
2593 if (source->remainingInBlock() > destination->remainingInBlock()) {
2594 firstSegment = destination->remainingInBlock();
2595 secondSegment = source->remainingInBlock() - firstSegment;
2596 }
2597 else {
2598 firstSegment = source->remainingInBlock();
2599 secondSegment = destination->remainingInBlock() - firstSegment;
2600 }
2601
2602 size_type thirdSegment = BLOCK_LENGTH - secondSegment;
2603
2604 std::memmove((void *)destination->valuePtr(),
2605 source->valuePtr(),
2606 firstSegment * sizeof(VALUE_TYPE));
2607
2608 *destination += firstSegment;
2609 *source += firstSegment;
2610 numElements -= firstSegment;
2611
2612 for (; numElements >= BLOCK_LENGTH; numElements -= BLOCK_LENGTH) {
2613
2614 std::memmove((void *)destination->valuePtr(),
2615 source->valuePtr(),
2616 secondSegment * sizeof(VALUE_TYPE));
2617
2618 *destination += secondSegment;
2619 *source += secondSegment;
2620
2621 std::memmove((void *)destination->valuePtr(),
2622 source->valuePtr(),
2623 thirdSegment * sizeof(VALUE_TYPE));
2624
2625 *destination += thirdSegment;
2626 *source += thirdSegment;
2627 }
2628
2629 size_type remaining = numElements > secondSegment
2630 ? secondSegment
2631 : numElements;
2632
2633 std::memmove((void *)destination->valuePtr(),
2634 source->valuePtr(),
2635 remaining * sizeof(VALUE_TYPE));
2636
2637 *destination += remaining;
2638 *source += remaining;
2639 numElements -= remaining;
2640
2641 std::memmove((void *)destination->valuePtr(),
2642 source->valuePtr(),
2643 numElements * sizeof(VALUE_TYPE));
2644
2645 *destination += numElements;
2646 *source += numElements;
2647}
2648
2649template <class VALUE_TYPE, int BLOCK_LENGTH>
2650template <class ALLOCATOR>
2651void
2654 Iterator fromEnd,
2655 size_type numElements,
2656 const VALUE_TYPE& value,
2657 ALLOCATOR allocator)
2658{
2659 if (fromEnd.remainingInBlock() > numElements) {
2661 numElements,
2662 value,
2663 allocator);
2664 fromEnd += numElements;
2665 *toEnd = fromEnd;
2666 return; // RETURN
2667 }
2668
2669 size_type firstRemaining = fromEnd.remainingInBlock();
2670
2672 firstRemaining,
2673 value,
2674 allocator);
2675
2676 numElements -= firstRemaining;
2677 fromEnd += firstRemaining;
2678 *toEnd = fromEnd;
2679
2680 for ( ; numElements >= BLOCK_LENGTH; numElements -= BLOCK_LENGTH) {
2682 BLOCK_LENGTH,
2683 value,
2684 allocator);
2685 fromEnd.nextBlock();
2686 toEnd->nextBlock();
2687 }
2688
2690 numElements,
2691 value,
2692 allocator);
2693
2694 fromEnd += numElements;
2695 *toEnd = fromEnd;
2696}
2697
2698template <class VALUE_TYPE, int BLOCK_LENGTH>
2699template <class ALLOCATOR>
2700void
2703 Iterator fromEnd,
2704 size_type numElements,
2705 ALLOCATOR allocator)
2706{
2707 if (fromEnd.remainingInBlock() > numElements) {
2709 numElements,
2710 allocator);
2711 fromEnd += numElements;
2712 *toEnd = fromEnd;
2713 return; // RETURN
2714 }
2715
2716 size_type firstRemaining = fromEnd.remainingInBlock();
2717
2719 firstRemaining,
2720 allocator);
2721
2722 numElements -= firstRemaining;
2723 fromEnd += firstRemaining;
2724 *toEnd = fromEnd;
2725
2726 for ( ; numElements >= BLOCK_LENGTH; numElements -= BLOCK_LENGTH) {
2728 BLOCK_LENGTH,
2729 allocator);
2730 fromEnd.nextBlock();
2731 toEnd->nextBlock();
2732 }
2733
2735 numElements,
2736 allocator);
2737
2738 fromEnd += numElements;
2739 *toEnd = fromEnd;
2740}
2741
2742template <class VALUE_TYPE, int BLOCK_LENGTH>
2743template <class ALLOCATOR>
2744void
2747 Iterator fromBegin,
2748 size_type numElements,
2749 const VALUE_TYPE& value,
2750 ALLOCATOR allocator)
2751{
2752 if (fromBegin.offsetInBlock() > numElements) {
2753 fromBegin -= numElements;
2754
2756 numElements,
2757 value,
2758 allocator);
2759 *toBegin = fromBegin;
2760 return; // RETURN
2761 }
2762
2763 size_type firstRemaining = fromBegin.offsetInBlock();
2764
2765 fromBegin -= firstRemaining;
2766 numElements -= firstRemaining;
2767
2769 firstRemaining,
2770 value,
2771 allocator);
2772
2773 *toBegin = fromBegin; // in case of exception
2774
2775 for ( ; numElements >= BLOCK_LENGTH; numElements -= BLOCK_LENGTH) {
2776 fromBegin.previousBlock();
2778 BLOCK_LENGTH,
2779 value,
2780 allocator);
2781 *toBegin = fromBegin;
2782 }
2783
2784 fromBegin -= numElements;
2786 numElements,
2787 value,
2788 allocator);
2789
2790 *toBegin = fromBegin;
2791}
2792
2793 // ------------------------------------
2794 // class DequePrimitives<VALUE_TYPE, 1>
2795 // ------------------------------------
2796
2797// CLASS METHODS
2798template <class VALUE_TYPE>
2799template <class ALLOCATOR>
2802 Iterator *toEnd,
2803 Iterator fromBegin,
2804 Iterator first,
2805 Iterator last,
2806 Iterator fromEnd,
2807 ALLOCATOR allocator)
2808{
2809 size_type frontSize = first - fromBegin;
2810 size_type backSize = fromEnd - last;
2811 Iterator ret;
2812
2813 if (frontSize < backSize) {
2814 ret = last;
2815 for (; 0 < frontSize; --frontSize) {
2816 --last;
2817 --first;
2818 *last = *first;
2819 }
2820 *toBegin = last;
2821 *toEnd = fromEnd;
2822 }
2823 else {
2824 ret = first;
2825 for (; 0 < backSize; --backSize, ++first, ++last) {
2826 *first = *last;
2827 }
2828 *toBegin = fromBegin;
2829 *toEnd = first;
2830 }
2831 destruct(first, last, allocator);
2832 return ret;
2833}
2834
2835template <class VALUE_TYPE>
2836template <class ALLOCATOR>
2838 Iterator end,
2839 ALLOCATOR allocator)
2840{
2841 for (; !(begin == end); ++begin) {
2843 begin.valuePtr());
2844 }
2845}
2846
2847template <class VALUE_TYPE>
2848template <class ALLOCATOR>
2849void
2852 Iterator fromBegin,
2853 Iterator position,
2854 size_type numElements,
2855 const VALUE_TYPE& value,
2856 ALLOCATOR allocator)
2857{
2858 typedef DequePrimitives_DequeElementGuard<VALUE_TYPE,
2859 1,
2860 ALLOCATOR> ElementGuard;
2861
2862 size_type frontSize = position - fromBegin;
2863 Iterator begin = fromBegin;
2864 Iterator dest = begin - numElements;
2865 size_type numDest;
2866
2870 value);
2872 temp(BSLS_UTIL_ADDRESSOF(space.object()));
2873
2874 // TBD: this does the same thing as the old code - don't like that we
2875 // circumvent the whole allocator thing, but for now, let's keep it
2876 // consistent.
2877 // ConstructorProxy<VALUE_TYPE>
2878 // tempValue(value, bslma::Default::allocator());
2879
2880 ElementGuard guard(dest, dest, allocator);
2881 if (frontSize >= numElements) {
2882 for (numDest = numElements; 0 < numDest; --numDest, ++dest, ++begin) {
2884 dest.valuePtr(),
2885 *begin);
2886 guard.moveEnd(1);
2887 }
2888 for (frontSize -= numElements; 0 < frontSize;
2889 --frontSize, ++dest, ++begin) {
2890 *dest = *begin;
2891 }
2892 for (numDest = numElements; 0 < numDest; --numDest, ++dest) {
2893 *dest = space.object();
2894 }
2895 } else {
2896 for (numDest = frontSize; 0 < numDest; --numDest, ++dest, ++begin) {
2898 dest.valuePtr(),
2899 *begin);
2900 guard.moveEnd(1);
2901 }
2902 for (numDest = numElements; frontSize < numDest; --numDest, ++dest) {
2904 dest.valuePtr(),
2905 space.object());
2906 guard.moveEnd(1);
2907 }
2908 for (; 0 < numDest; --numDest, ++dest) {
2909 *dest = space.object();
2910 }
2911 }
2912 guard.release();
2913 *toBegin = fromBegin - numElements;
2914}
2915
2916template <class VALUE_TYPE>
2917template <class FWD_ITER, class ALLOCATOR>
2918void
2921 Iterator fromBegin,
2922 Iterator position,
2923 FWD_ITER first,
2924 FWD_ITER /*last*/,
2925 size_type numElements,
2926 ALLOCATOR allocator)
2927{
2928 typedef DequePrimitives_DequeElementGuard<VALUE_TYPE,
2929 1,
2930 ALLOCATOR> ElementGuard;
2931
2932 size_type frontSize = position - fromBegin;
2933 Iterator begin = fromBegin;
2934 Iterator dest = begin - numElements;
2935 size_type numDest;
2936
2937 ElementGuard guard(dest, dest, allocator);
2938 if (frontSize >= numElements) {
2939 for (numDest = numElements; 0 < numDest; --numDest, ++dest, ++begin) {
2941 dest.valuePtr(),
2942 *begin);
2943 guard.moveEnd(1);
2944 }
2945 for (frontSize -= numElements; 0 < frontSize;
2946 --frontSize, ++dest, ++begin) {
2947 *dest = *begin;
2948 }
2949 for (numDest = numElements; 0 < numDest; --numDest, ++dest, ++first) {
2950 *dest = *first;
2951 }
2952 } else {
2953 for (numDest = frontSize; 0 < numDest; --numDest, ++dest, ++begin) {
2955 dest.valuePtr(),
2956 *begin);
2957 guard.moveEnd(1);
2958 }
2959 for (numDest = numElements; frontSize < numDest;
2960 --numDest, ++dest, ++first) {
2962 dest.valuePtr(),
2963 *first);
2964 guard.moveEnd(1);
2965 }
2966 for (; 0 < numDest; --numDest, ++dest, ++first) {
2967 *dest = *first;
2968 }
2969 }
2970 guard.release();
2971 *toBegin = fromBegin - numElements;
2972}
2973
2974template <class VALUE_TYPE>
2975template <class ALLOCATOR>
2976void
2978 Iterator *toEnd,
2979 Iterator fromEnd,
2980 Iterator position,
2981 size_type numElements,
2982 const VALUE_TYPE& value,
2983 ALLOCATOR allocator)
2984{
2985 typedef DequePrimitives_DequeElementGuard<VALUE_TYPE,
2986 1,
2987 ALLOCATOR> ElementGuard;
2988
2989 size_type backSize = fromEnd - position;
2990 Iterator end = fromEnd;
2991 Iterator dest = end + numElements;
2992 size_type numDest;
2993
2997 value);
2999 temp(BSLS_UTIL_ADDRESSOF(space.object()));
3000
3001 // TBD: this does the same thing as the old code - don't like that we
3002 // circumvent the whole allocator thing, but for now, let's keep it
3003 // consistent.
3004 // ConstructorProxy<VALUE_TYPE>
3005 // tempValue(value, bslma::Default::allocator());
3006
3007 ElementGuard guard(dest, dest, allocator);
3008 if (backSize >= numElements) {
3009 for (numDest = numElements; 0 < numDest; --numDest) {
3010 --dest;
3011 --end;
3013 dest.valuePtr(),
3014 *end);
3015 guard.moveBegin(-1);
3016 }
3017 for (backSize -= numElements; 0 < backSize; --backSize) {
3018 --dest;
3019 --end;
3020 *dest = *end;
3021 }
3022 for (numDest = numElements; 0 < numDest; --numDest, ++position) {
3023 *position = space.object();
3024 }
3025 } else {
3026 for (numDest = backSize; 0 < numDest; --numDest) {
3027 --dest;
3028 --end;
3030 dest.valuePtr(),
3031 *end);
3032 guard.moveBegin(-1);
3033 }
3034 for (numDest = numElements; backSize < numDest; --numDest) {
3035 --dest;
3037 dest.valuePtr(),
3038 space.object());
3039 guard.moveBegin(-1);
3040 }
3041 for (; 0 < numDest; --numDest, ++position) {
3042 *position = space.object();
3043 }
3044 }
3045 guard.release();
3046 *toEnd = fromEnd + numElements;
3047}
3048
3049template <class VALUE_TYPE>
3050template <class FWD_ITER, class ALLOCATOR>
3051void
3053 Iterator fromEnd,
3054 Iterator position,
3055 FWD_ITER first,
3056 FWD_ITER /*last*/,
3057 size_type numElements,
3058 ALLOCATOR allocator)
3059{
3060 typedef DequePrimitives_DequeElementGuard<VALUE_TYPE,
3061 1,
3062 ALLOCATOR> ElementGuard;
3063
3064 size_type backSize = fromEnd - position;
3065 Iterator end = fromEnd;
3066 Iterator dest = end + numElements;
3067 size_type numDest;
3068
3069 ElementGuard guard(dest, dest, allocator);
3070 if (backSize >= numElements) {
3071 for (numDest = numElements; 0 < numDest; --numDest) {
3072 --dest;
3073 --end;
3075 dest.valuePtr(),
3076 *end);
3077 guard.moveBegin(-1);
3078 }
3079 for (numDest = backSize; numElements < numDest; --numDest) {
3080 --dest;
3081 --end;
3082 *dest = *end;
3083 }
3084 for (; 0 < numDest; ++first, ++position, --numDest) {
3085 *position = *first;
3086 }
3087 } else {
3088 for (numDest = backSize; 0 < numDest; --numDest) {
3089 --dest;
3090 --end;
3092 dest.valuePtr(),
3093 *end);
3094 guard.moveBegin(-1);
3095 }
3096 for (numDest = backSize; 0 < numDest; --numDest, ++position, ++first) {
3097 *position = *first;
3098 }
3099 ElementGuard guard2(position, position, allocator);
3100 for (numDest = numElements; backSize < numDest; ++first, ++position,
3101 --numDest) {
3103 position.valuePtr(),
3104 *first);
3105 guard2.moveEnd(1);
3106 }
3107 guard2.release();
3108 }
3109 guard.release();
3110 *toEnd = fromEnd + numElements;
3111}
3112
3113template <class VALUE_TYPE>
3114template <class ALLOCATOR>
3115inline
3116void
3118 Iterator *toBegin,
3119 Iterator fromBegin,
3120 size_type numElements,
3121 const VALUE_TYPE& value,
3122 ALLOCATOR allocator)
3123{
3124 enum {
3125 IS_FUNCTION_POINTER = bslmf::IsFunctionPointer<VALUE_TYPE>::value,
3128
3129 IS_FUNDAMENTAL_OR_POINTER = IS_FUNDAMENTAL ||
3130 (IS_POINTER && !IS_FUNCTION_POINTER),
3131
3133
3134 VALUE = IS_FUNDAMENTAL_OR_POINTER || IS_BITWISECOPYABLE ?
3135 NON_NIL_TRAITS
3136 : NIL_TRAITS
3137 };
3138
3139 uninitializedFillNFront(toBegin,
3140 fromBegin,
3141 numElements,
3142 value,
3143 allocator,
3145}
3146
3147template <class VALUE_TYPE>
3148template <class ALLOCATOR>
3149void
3151 Iterator *toBegin,
3152 Iterator fromBegin,
3153 size_type numElements,
3154 const VALUE_TYPE& value,
3155 ALLOCATOR allocator,
3157{
3158 typedef DequePrimitives_DequeElementGuard<VALUE_TYPE,
3159 1,
3160 ALLOCATOR> ElementGuard;
3161
3162 ElementGuard guard(fromBegin, fromBegin, allocator);
3163 for (; 0 < numElements; --numElements) {
3164 --fromBegin;
3166 fromBegin.valuePtr(),
3167 value);
3168 guard.moveBegin(-1);
3169 }
3170 guard.release();
3171 *toBegin = fromBegin;
3172}
3173
3174template <class VALUE_TYPE>
3175template <class ALLOCATOR>
3176void
3178 Iterator *toBegin,
3179 Iterator fromBegin,
3180 size_type numElements,
3181 const VALUE_TYPE& value,
3182 ALLOCATOR allocator,
3184{
3185 *toBegin = fromBegin; // necessary in case 'numElements = 0'
3186 for ( ; 0 < numElements; --numElements) {
3187 --fromBegin;
3189 1,
3190 value,
3191 allocator);
3192 *toBegin = fromBegin; // in case of exception
3193 }
3194}
3195
3196template <class VALUE_TYPE>
3197template <class ALLOCATOR>
3198inline
3199void
3201 Iterator *toEnd,
3202 Iterator fromEnd,
3203 size_type numElements,
3204 const VALUE_TYPE& value,
3205 ALLOCATOR allocator)
3206{
3207 enum {
3208 IS_FUNCTION_POINTER = bslmf::IsFunctionPointer<VALUE_TYPE>::value,
3211
3212 IS_FUNDAMENTAL_OR_POINTER = IS_FUNDAMENTAL ||
3213 (IS_POINTER && !IS_FUNCTION_POINTER),
3214
3216
3217 VALUE = IS_FUNDAMENTAL_OR_POINTER || IS_BITWISECOPYABLE ?
3218 NON_NIL_TRAITS
3219 : NIL_TRAITS
3220 };
3221
3222 uninitializedFillNBack(toEnd,
3223 fromEnd,
3224 numElements,
3225 value,
3226 allocator,
3228}
3229
3230template <class VALUE_TYPE>
3231template <class ALLOCATOR>
3232void
3234 Iterator *toEnd,
3235 Iterator fromEnd,
3236 size_type numElements,
3237 const VALUE_TYPE& value,
3238 ALLOCATOR allocator,
3240{
3241 typedef DequePrimitives_DequeElementGuard<VALUE_TYPE,
3242 1,
3243 ALLOCATOR> ElementGuard;
3244
3245 ElementGuard guard(fromEnd, fromEnd, allocator);
3246 for (; 0 < numElements; --numElements) {
3248 fromEnd.valuePtr(),
3249 value);
3250 ++fromEnd;
3251 guard.moveEnd(1);
3252 }
3253 guard.release();
3254 *toEnd = fromEnd;
3255}
3256
3257template <class VALUE_TYPE>
3258template <class ALLOCATOR>
3259void
3261 Iterator *toEnd,
3262 Iterator fromEnd,
3263 size_type numElements,
3264 const VALUE_TYPE& value,
3265 ALLOCATOR allocator,
3267{
3268 *toEnd = fromEnd; // necessary in case 'numElements = 0'
3269 for ( ; 0 < numElements; --numElements) {
3271 1,
3272 value,
3273 allocator);
3274 ++fromEnd;
3275 *toEnd = fromEnd;
3276 }
3277}
3278
3279template <class VALUE_TYPE>
3280template <class ALLOCATOR>
3281inline
3282void
3284 Iterator fromEnd,
3285 size_type numElements,
3286 ALLOCATOR allocator)
3287{
3288 enum {
3289 IS_FUNCTION_POINTER = bslmf::IsFunctionPointer<VALUE_TYPE>::value,
3292
3293 IS_FUNDAMENTAL_OR_POINTER = IS_FUNDAMENTAL ||
3294 (IS_POINTER && !IS_FUNCTION_POINTER),
3295
3297
3298 VALUE = IS_FUNDAMENTAL_OR_POINTER || IS_BITWISECOPYABLE ?
3299 NON_NIL_TRAITS
3300 : NIL_TRAITS
3301 };
3302
3303 valueInititalizeN(toEnd,
3304 fromEnd,
3305 numElements,
3306 allocator,
3308}
3309
3310template <class VALUE_TYPE>
3311template <class ALLOCATOR>
3312void
3314 Iterator *toEnd,
3315 Iterator fromEnd,
3316 size_type numElements,
3317 ALLOCATOR allocator,
3319{
3320 typedef DequePrimitives_DequeElementGuard<VALUE_TYPE,
3321 1,
3322 ALLOCATOR> ElementGuard;
3323
3324 ElementGuard guard(fromEnd, fromEnd, allocator);
3325 for (; 0 < numElements; --numElements) {
3327 fromEnd.valuePtr());
3328 ++fromEnd;
3329 guard.moveEnd(1);
3330 }
3331 guard.release();
3332 *toEnd = fromEnd;
3333}
3334
3335template <class VALUE_TYPE>
3336template <class ALLOCATOR>
3337void
3339 Iterator *toEnd,
3340 Iterator fromEnd,
3341 size_type numElements,
3342 ALLOCATOR allocator,
3344{
3345 *toEnd = fromEnd; // necessary in case 'numElements = 0'
3346 for ( ; 0 < numElements; --numElements) {
3348 1,
3349 allocator);
3350 ++fromEnd;
3351 *toEnd = fromEnd;
3352 }
3353}
3354
3355 // ---------------------------------------
3356 // class DequePrimitives_DequeElementGuard
3357 // ---------------------------------------
3358
3359// CREATORS
3360template <class VALUE_TYPE, int BLOCK_LENGTH, class ALLOCATOR>
3361inline
3364 const Iterator& end,
3365 ALLOCATOR allocator)
3366: d_begin(begin)
3367, d_end(end)
3368, d_allocator(allocator)
3369{
3370}
3371
3372template <class VALUE_TYPE, int BLOCK_LENGTH, class ALLOCATOR>
3373inline
3381
3382// MANIPULATORS
3383template <class VALUE_TYPE, int BLOCK_LENGTH, class ALLOCATOR>
3384inline
3386<VALUE_TYPE, BLOCK_LENGTH, ALLOCATOR>::Iterator&
3388 ::moveBegin(std::ptrdiff_t offset)
3389{
3390 d_begin += offset;
3391 return d_begin;
3392}
3393
3394template <class VALUE_TYPE, int BLOCK_LENGTH, class ALLOCATOR>
3395inline
3397<VALUE_TYPE, BLOCK_LENGTH, ALLOCATOR>::Iterator&
3399 ::moveEnd(std::ptrdiff_t offset)
3400{
3401 d_end += offset;
3402 return d_end;
3403}
3404
3405template <class VALUE_TYPE, int BLOCK_LENGTH, class ALLOCATOR>
3406inline
3412
3413 // -----------------------------------------------
3414 // class DequePrimitives_ExternalDequeElementGuard
3415 // -----------------------------------------------
3416
3417// CREATORS
3418template <class VALUE_TYPE, int BLOCK_LENGTH, class ALLOCATOR>
3419inline
3422 Iterator *end,
3423 ALLOCATOR allocator)
3424: d_begin_p(begin)
3425, d_end_p(end)
3426, d_allocator(allocator)
3427{
3428}
3429
3430template <class VALUE_TYPE, int BLOCK_LENGTH, class ALLOCATOR>
3431inline
3434{
3435 if (d_begin_p != d_end_p) {
3437 *d_end_p,
3438 d_allocator);
3439 }
3440}
3441
3442// MANIPULATORS
3443template <class VALUE_TYPE, int BLOCK_LENGTH, class ALLOCATOR>
3444inline
3445void
3448{
3449 d_begin_p = d_end_p = 0;
3450}
3451
3452 // ------------------------------------
3453 // class DequePrimitives_DequeMoveGuard
3454 // ------------------------------------
3455
3456// CREATORS
3457template <class VALUE_TYPE, int BLOCK_LENGTH>
3458inline
3461 Iterator src,
3462 std::size_t size,
3463 bool isFront)
3464: d_destination_p(dest)
3465, d_source_p(src)
3466, d_size(size)
3467, d_front(isFront)
3468{
3469}
3470
3471template <class VALUE_TYPE, int BLOCK_LENGTH>
3472inline
3475{
3476 if (d_size != 0) {
3477 // We need to reverse 'moveFront'.
3478 if (d_front) {
3479 d_destination_p += d_size;
3480 d_source_p += d_size;
3481 DequePrimitives::moveBack(&d_destination_p, &d_source_p, d_size);
3482 }
3483 // We need to reverse 'moveBack'.
3484 else {
3485 d_destination_p -= d_size;
3486 d_source_p -= d_size;
3487 DequePrimitives::moveFront(&d_destination_p, &d_source_p, d_size);
3488 }
3489 }
3490}
3491
3492// MANIPULATORS
3493template <class VALUE_TYPE, int BLOCK_LENGTH>
3494inline
3499
3500 // ------------------------------------------
3501 // class DequePrimitives_DequeEndpointProctor
3502 // ------------------------------------------
3503
3504// CREATORS
3505template <class VALUE_TYPE, int BLOCK_LENGTH>
3506inline
3509 Iterator position)
3510: d_endpoint_p(endpoint)
3511, d_position(position)
3512{
3513}
3514
3515template <class VALUE_TYPE, int BLOCK_LENGTH>
3516inline
3519{
3520 if (0 != d_endpoint_p) {
3521 *d_endpoint_p = d_position;
3522 }
3523}
3524
3525// MANIPULATORS
3526template <class VALUE_TYPE, int BLOCK_LENGTH>
3527inline
3532
3533} // close package namespace
3534
3535#ifndef BDE_OPENSOURCE_PUBLICATION // BACKWARD_COMPATIBILITY
3536// ============================================================================
3537// BACKWARD COMPATIBILITY
3538// ============================================================================
3539
3540#ifdef bslalg_DequePrimitives
3541#undef bslalg_DequePrimitives
3542#endif
3543/// This alias is defined for backward compatibility.
3544#define bslalg_DequePrimitives bslalg::DequePrimitives
3545#endif // BDE_OPENSOURCE_PUBLICATION -- BACKWARD_COMPATIBILITY
3546
3547
3548
3549#endif // End C++11 code
3550
3551#endif
3552
3553// ----------------------------------------------------------------------------
3554// Copyright 2013 Bloomberg Finance L.P.
3555//
3556// Licensed under the Apache License, Version 2.0 (the "License");
3557// you may not use this file except in compliance with the License.
3558// You may obtain a copy of the License at
3559//
3560// http://www.apache.org/licenses/LICENSE-2.0
3561//
3562// Unless required by applicable law or agreed to in writing, software
3563// distributed under the License is distributed on an "AS IS" BASIS,
3564// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
3565// See the License for the specific language governing permissions and
3566// limitations under the License.
3567// ----------------------------- END-OF-FILE ----------------------------------
3568
3569/** @} */
3570/** @} */
3571/** @} */
Definition bslalg_dequeiterator.h:337
VALUE_TYPE * valuePtr() const
Definition bslalg_dequeiterator.h:805
Definition bslalg_dequeiterator.h:157
void previousBlock()
Definition bslalg_dequeiterator.h:497
std::size_t offsetInBlock() const
Definition bslalg_dequeiterator.h:604
std::size_t remainingInBlock() const
Definition bslalg_dequeiterator.h:612
VALUE_TYPE * valuePtr() const
Definition bslalg_dequeiterator.h:620
void nextBlock()
Set this iterator to point to the first element of the next block.
Definition bslalg_dequeiterator.h:489
Definition bslalg_dequeprimitives.h:893
Iterator & moveEnd(std::ptrdiff_t offset=1)
Definition bslalg_dequeprimitives.h:3399
Iterator & moveBegin(std::ptrdiff_t offset=-1)
Definition bslalg_dequeprimitives.h:3388
void release()
Definition bslalg_dequeprimitives.h:3408
~DequePrimitives_DequeElementGuard()
Definition bslalg_dequeprimitives.h:3375
DequeIterator< VALUE_TYPE, BLOCK_LENGTH > Iterator
Definition bslalg_dequeprimitives.h:897
Definition bslalg_dequeprimitives.h:1069
void release()
Definition bslalg_dequeprimitives.h:3528
~DequePrimitives_DequeEndpointProctor()
Definition bslalg_dequeprimitives.h:3518
DequeIterator< VALUE_TYPE, BLOCK_LENGTH > Iterator
Definition bslalg_dequeprimitives.h:1073
Definition bslalg_dequeprimitives.h:1015
void release()
Set the size of the range guarded by this object to be zero.
Definition bslalg_dequeprimitives.h:3495
~DequePrimitives_DequeMoveGuard()
Definition bslalg_dequeprimitives.h:3474
bslalg::DequePrimitives< VALUE_TYPE, BLOCK_LENGTH > DequePrimitives
Definition bslalg_dequeprimitives.h:1020
DequeIterator< VALUE_TYPE, BLOCK_LENGTH > Iterator
Definition bslalg_dequeprimitives.h:1019
Definition bslalg_dequeprimitives.h:958
~DequePrimitives_ExternalDequeElementGuard()
Definition bslalg_dequeprimitives.h:3433
void release()
Definition bslalg_dequeprimitives.h:3447
DequeIterator< VALUE_TYPE, BLOCK_LENGTH > Iterator
Definition bslalg_dequeprimitives.h:962
Definition bslma_destructorproctor.h:259
Definition bslmf_movableref.h:751
#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_UTIL_ADDRESSOF(OBJ)
Definition bsls_util.h:289
Definition bdlc_flathashmap.h:1805
static void construct(ALLOCATOR_TYPE &basicAllocator, ELEMENT_TYPE *elementAddr, Args &&... arguments)
Definition bslma_allocatortraits.h:1472
static void destroy(ALLOCATOR_TYPE &basicAllocator, ELEMENT_TYPE *elementAddr)
Definition bslma_allocatortraits.h:1494
Definition bslmf_integralconstant.h:244
static void defaultConstruct(typename bsl::allocator_traits< ALLOCATOR >::pointer begin, size_type numElements, ALLOCATOR allocator)
Definition bslalg_arrayprimitives.h:2064
static void uninitializedFillN(typename bsl::allocator_traits< ALLOCATOR >::pointer begin, size_type numElements, const typename bsl::allocator_traits< ALLOCATOR >::value_type &value, ALLOCATOR allocator)
Definition bslalg_arrayprimitives.h:1905
Definition bslalg_dequeimputil.h:124
static Iterator erase(Iterator *toBegin, Iterator *toEnd, Iterator fromBegin, Iterator first, Iterator last, Iterator fromEnd, ALLOCATOR allocator)
DequeImpUtil< VALUE_TYPE, 1 > ImpUtil
Definition bslalg_dequeprimitives.h:762
std::size_t size_type
Definition bslalg_dequeprimitives.h:761
DequeIterator< VALUE_TYPE, 1 > Iterator
Definition bslalg_dequeprimitives.h:763
Definition bslalg_dequeprimitives.h:243
static void moveBack(Iterator *destination, Iterator *source, size_type numElements)
Definition bslalg_dequeprimitives.h:2399
static void insertAndMoveToBack(Iterator *toEnd, Iterator fromEnd, Iterator position, size_type numElements, const VALUE_TYPE &value, ALLOCATOR allocator)
Definition bslalg_dequeprimitives.h:1281
static void insertAndMoveToFront(Iterator *toBegin, Iterator fromBegin, Iterator position, size_type numElements, const VALUE_TYPE &value, ALLOCATOR allocator)
Definition bslalg_dequeprimitives.h:1694
static void emplaceAndMoveToFrontDispatch(Iterator *toBegin, Iterator fromBegin, Iterator position, ALLOCATOR allocator, bsl::integral_constant< int, BITWISE_COPYABLE_TRAITS >, Args &&... arguments)
Definition bslalg_dequeprimitives.h:2272
static void uninitializedFillNFront(Iterator *toBegin, Iterator fromBegin, size_type numElements, const VALUE_TYPE &value, ALLOCATOR allocator)
Definition bslalg_dequeprimitives.h:2746
static void uninitializedFillNBack(Iterator *toEnd, Iterator fromEnd, size_type numElements, const VALUE_TYPE &value, ALLOCATOR allocator)
Definition bslalg_dequeprimitives.h:2653
static void moveInsertAndMoveToFront(Iterator *toBegin, Iterator fromBegin, Iterator position, bslmf::MovableRef< VALUE_TYPE > value, ALLOCATOR allocator)
Definition bslalg_dequeprimitives.h:1944
static void emplaceAndMoveToBack(Iterator *toEnd, Iterator fromEnd, Iterator position, ALLOCATOR allocator, Args &&... arguments)
Definition bslalg_dequeprimitives.h:2084
static void emplaceAndMoveToBackDispatch(Iterator *toEnd, Iterator fromEnd, Iterator position, ALLOCATOR allocator, bsl::integral_constant< int, BITWISE_COPYABLE_TRAITS >, Args &&... arguments)
Definition bslalg_dequeprimitives.h:2112
std::size_t size_type
Definition bslalg_dequeprimitives.h:246
static void emplaceAndMoveToFront(Iterator *toBegin, Iterator fromBegin, Iterator position, ALLOCATOR allocator, Args &&... arguments)
Definition bslalg_dequeprimitives.h:2244
DequeIterator< VALUE_TYPE, BLOCK_LENGTH > Iterator
Definition bslalg_dequeprimitives.h:247
static void valueInititalizeN(Iterator *toEnd, Iterator fromEnd, size_type numElements, ALLOCATOR allocator)
Definition bslalg_dequeprimitives.h:2702
static void moveInsertAndMoveToBack(Iterator *toEnd, Iterator fromEnd, Iterator position, bslmf::MovableRef< VALUE_TYPE > value, ALLOCATOR allocator)
Definition bslalg_dequeprimitives.h:1550
static Iterator erase(Iterator *toBegin, Iterator *toEnd, Iterator fromBegin, Iterator first, Iterator last, Iterator fromEnd, ALLOCATOR allocator)
Definition bslalg_dequeprimitives.h:1170
static void destruct(Iterator begin, Iterator end, ALLOCATOR allocator)
Definition bslalg_dequeprimitives.h:1122
static void moveFront(Iterator *destination, Iterator *source, size_type numElements)
Definition bslalg_dequeprimitives.h:2525
static void construct(TARGET_TYPE *address, const ALLOCATOR &allocator)
Definition bslma_constructionutil.h:1243
static Allocator * allocator(Allocator *basicAllocator=0)
Definition bslma_default.h:897
Definition bslmf_isbitwisecopyable.h:298
Definition bslmf_isbitwisemoveable.h:718
Definition bslmf_functionpointertraits.h:153
Definition bslmf_isfundamental.h:303
Definition bslmf_ispointer.h:225
Definition bslmf_movableref.h:791
Definition bsls_objectbuffer.h:276
TYPE & object()
Definition bsls_objectbuffer.h:351