BDE 4.39.x 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// clang-format off
189// Include version that can be compiled with C++03
190// Generated on Mon Jan 13 08:31:35 2025
191// Command line: sim_cpp11_features.pl bslalg_dequeprimitives.h
192
193# define COMPILING_BSLALG_DEQUEPRIMITIVES_H
195# undef COMPILING_BSLALG_DEQUEPRIMITIVES_H
196
197// clang-format on
198#else
199
200
201
202namespace bslalg {
203
204template <class VALUE_TYPE, int BLOCK_LENGTH, class ALLOCATOR>
205class DequePrimitives_DequeElementGuard;
206
207template <class VALUE_TYPE, int BLOCK_LENGTH>
208class DequePrimitives_DequeMoveGuard;
209
210template <class VALUE_TYPE, int BLOCK_LENGTH, class ALLOCATOR>
211class DequePrimitives_ExternalDequeElementGuard;
212
213template <class VALUE_TYPE, int BLOCK_LENGTH>
214class DequePrimitives_DequeEndpointProctor;
215
216/// These constants are used in the overloads below, when the last argument is
217/// of type 'bsl::integral_constant<int, N>', indicating that 'VALUE_TYPE' has
218/// the traits for which the enumerator equal to 'N' is named.
219/// Workaround for windows. The windows compiler refuses to recognize enum
220/// declarations within a class template.
221enum {
227
228 // ======================
229 // struct DequePrimitives
230 // ======================
231
232/// This `struct` provides a namespace for a suite of utility functions that
233/// operate on deques parameterized by the `VALUE_TYPE` and `BLOCK_LENGTH`.
234/// Depending on the traits of `VALUE_TYPE`, the default and copy
235/// constructors, destructor, assignment operators, etcetera may not be
236/// invoked, and instead the operation can be optimized using a no-op,
237/// bitwise move, or bitwise copy.
238///
239/// See @ref bslalg_dequeprimitives
240template <class VALUE_TYPE, int BLOCK_LENGTH>
242
243 // PUBLIC TYPES
244 typedef std::size_t size_type;
246
247 private:
248 // PRIVATE TYPES
252
253 public:
254 // CLASS METHODS
255
256 /// TBD: fix comment
257 /// Call the destructor on each of the elements of a deque of
258 /// parameterized `VALUE_TYPE` in the specified range `[begin .. end)`.
259 ///
260 /// \pre The behavior is undefined unless `begin <= end`.
261 /// \note 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 ///
270 /// \pre The behavior is undefined unless `begin <= end`.
271 /// \note Note that this
272 /// does not deallocate any memory (except memory deallocated by the element destructor calls).
273 ///
274 /// \note Note that the last argument is for
275 /// removing overload ambiguities and is not used.
276 template <class ALLOCATOR>
277 static void destruct(
278 Iterator begin,
279 Iterator end,
280 ALLOCATOR allocator,
282 template <class ALLOCATOR>
283 static void destruct(Iterator begin,
284 Iterator end,
285 ALLOCATOR allocator,
287 int,
289
290 /// Call the destructor on each of the elements of a deque of
291 /// parameterized `VALUE_TYPE` in the specified range `[first .. last)`.
292 /// Shift the elements to fill up the empty space after the erasure,
293 /// using the smaller of the range defined by `[fromBegin .. first)` and
294 /// `[last .. fromEnd)` after the erasure. Load in the specified
295 /// `toBegin` and `toEnd` the new boundaries of the deque after erasure
296 /// and return an iterator pointing to the element immediately following the removed elements.
297 ///
298 /// \pre The behavior is undefined unless
299 /// `fromBegin <= first <= last <= fromEnd`.
300 template <class ALLOCATOR>
301 static Iterator erase(Iterator *toBegin,
302 Iterator *toEnd,
303 Iterator fromBegin,
304 Iterator first,
305 Iterator last,
306 Iterator fromEnd,
307 ALLOCATOR allocator);
308
309 /// Call the destructor on each of the elements of a deque of
310 /// parameterized `VALUE_TYPE` in the specified range `[first .. last)`.
311 /// Shift the elements from the smaller of the specified range
312 /// `[fromBegin .. first)` and `[last .. fromEnd)` to fill up the empty
313 /// spaces after the erasure. Load in the specified `toBegin` and
314 /// `toEnd` the new boundaries of the deque after erasure and return an
315 /// iterator pointing to the element immediately following the removed elements.
316 ///
317 /// \pre The behavior is undefined unless `fromBegin <= first <= last <= fromEnd`.
318 ///
319 /// \note Note that the last
320 /// argument is for removing overload ambiguities and is not used.
321 template <class ALLOCATOR>
322 static Iterator erase(
323 Iterator *toBegin,
324 Iterator *toEnd,
325 Iterator fromBegin,
326 Iterator first,
327 Iterator last,
328 Iterator fromEnd,
329 ALLOCATOR allocator,
331 template <class ALLOCATOR>
332 static Iterator erase(Iterator *toBegin,
333 Iterator *toEnd,
334 Iterator fromBegin,
335 Iterator first,
336 Iterator last,
337 Iterator fromEnd,
338 ALLOCATOR allocator,
340 int,
342
343 /// Insert the specified `numElements` copies of the specified `value`
344 /// at the specified `position`, by moving the elements in the range
345 /// `[position .. fromEnd)` forward by `numElements` position. Pass the
346 /// specified `allocator` to the copy constructor if appropriate. Load
347 /// into the specified `toEnd` an iterator to the end of the deque after
348 /// insertion (i.e., `fromEnd + numElements`).
349 ///
350 /// \pre The behavior is undefined unless `fromEnd + numElements` is a valid iterator (i.e.,
351 /// the block pointer array holds enough room after the `fromEnd`
352 /// position to insert `numElements`).
353 template <class ALLOCATOR>
354 static void insertAndMoveToBack(Iterator *toEnd,
355 Iterator fromEnd,
356 Iterator position,
357 size_type numElements,
358 const VALUE_TYPE& value,
359 ALLOCATOR allocator);
360
361 /// Insert the specified `numElements` copies of the specified `value`
362 /// at the specified `position`, by moving the elements in the range
363 /// `[position .. fromEnd)` forward by `numElements` position. Pass the
364 /// specified `allocator` to the copy constructor if appropriate. Load
365 /// into the specified `toEnd` an iterator to the end of the deque after
366 /// insertion (i.e., `fromEnd + numElements`).
367 ///
368 /// \pre The behavior is undefined unless `fromEnd + numElements` is a valid iterator (i.e.,
369 /// the block pointer array holds enough room after the `fromEnd` position to insert `numElements`).
370 ///
371 /// \note Note that the last argument is
372 /// for removing overload ambiguities and is not used.
373 template <class ALLOCATOR>
374 static void
376 Iterator fromEnd,
377 Iterator position,
378 size_type numElements,
379 const VALUE_TYPE& value,
380 ALLOCATOR allocator,
382 int,
384 template <class ALLOCATOR>
385 static void
387 Iterator fromEnd,
388 Iterator position,
389 size_type numElements,
390 const VALUE_TYPE& value,
391 ALLOCATOR allocator,
393 int,
395 template <class ALLOCATOR>
396 static void insertAndMoveToBack(
397 Iterator *toEnd,
398 Iterator fromEnd,
399 Iterator position,
400 size_type numElements,
401 const VALUE_TYPE& value,
402 ALLOCATOR allocator,
404
405 /// Insert the specified `numElements` in the range `[first .. last)` at
406 /// the specified `position`, by moving the elements in the range
407 /// `[position .. fromEnd)` forward by `numElements` position. Pass the
408 /// specified `allocator` to the copy constructor if appropriate. Load
409 /// into the specified `toEnd` an iterator to the end of the data after
410 /// insertion (i.e., `fromEnd + numElements`).
411 ///
412 /// \pre The behavior is undefined unless `fromEnd + numElements` is a valid iterator (i.e.,
413 /// the block pointer array holds enough room after the `fromEnd`
414 /// position to insert `numElements`).
415 template <class FWD_ITER, class SENTINEL, class ALLOCATOR>
416 static void insertAndMoveToBack(Iterator *toEnd,
417 Iterator fromEnd,
418 Iterator position,
419 FWD_ITER first,
420 SENTINEL last,
421 size_type numElements,
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., `fromEnd + 1`).
429 ///
430 /// \pre The behavior is undefined unless `fromEnd + 1` is a
431 /// valid iterator (i.e., the block pointer array holds enough room
432 /// after the `fromEnd` position to insert 1 element).
433 template <class ALLOCATOR>
434 static void moveInsertAndMoveToBack(
435 Iterator *toEnd,
436 Iterator fromEnd,
437 Iterator position,
439 ALLOCATOR allocator);
440
441 /// Insert the specified move-insertable `value` at the specified
442 /// `position` by moving the elements in the range
443 /// `[position .. fromEnd)` forward by 1 position; pass the specified
444 /// `allocator` to the move constructor if appropriate. Load into the
445 /// specified `toEnd` an iterator one past the inserted element (i.e., `fromEnd + 1`).
446 ///
447 /// \pre The behavior is undefined unless `fromEnd + 1` is a
448 /// valid iterator (i.e., the block pointer array holds enough room after the `fromEnd` position to insert 1 element).
449 ///
450 /// \note Note that the
451 /// last argument is for removing overload ambiguities and is not used.
452 template <class ALLOCATOR>
453 static void moveInsertAndMoveToBack(
454 Iterator *toEnd,
455 Iterator fromEnd,
456 Iterator position,
458 ALLOCATOR allocator,
460 int,
462 template <class ALLOCATOR>
463 static void moveInsertAndMoveToBack(
464 Iterator *toEnd,
465 Iterator fromEnd,
466 Iterator position,
468 ALLOCATOR allocator,
470 int,
472 template <class ALLOCATOR>
473 static void moveInsertAndMoveToBack(
474 Iterator *toEnd,
475 Iterator fromEnd,
476 Iterator position,
478 ALLOCATOR allocator,
480
481 /// Insert the specified `numElements` copies of the specified `value`
482 /// at the specified `position`, by moving the elements in the range
483 /// `[fromBegin .. position)` backward by `numElements` position. Pass
484 /// the specified `allocator` to the copy constructor if appropriate.
485 /// Load into the specified `toBegin` an iterator to the beginning of
486 /// the data after insertion (i.e., `fromBegin - numElements`).
487 ///
488 /// \pre The behavior is undefined unless `fromBegin - numElements` is a valid
489 /// iterator (i.e., the block pointer array holds enough room before the
490 /// `fromBegin` position to insert `numElements`).
491 template <class ALLOCATOR>
492 static void insertAndMoveToFront(Iterator *toBegin,
493 Iterator fromBegin,
494 Iterator position,
495 size_type numElements,
496 const VALUE_TYPE& value,
497 ALLOCATOR allocator);
498
499 /// Insert the specified `numElements` copies of the specified `value`
500 /// at the specified `position`, by moving the elements in the range
501 /// `[fromBegin .. position)` backward by `numElements` position. Pass
502 /// the specified `allocator` to the copy constructor if appropriate.
503 /// Load into the specified `toBegin` an iterator to the beginning of
504 /// the data after insertion (i.e., `fromBegin - numElements`.
505 ///
506 /// \pre The behavior is undefined unless `fromBegin - numElements` is a valid
507 /// iterator (i.e., the block pointer array holds enough room before the `fromBegin` position to insert `numElements`).
508 ///
509 /// \note Note that the last
510 /// argument is for removing overload ambiguities and is not used.
511 template <class ALLOCATOR>
512 static void
514 Iterator fromBegin,
515 Iterator position,
516 size_type numElements,
517 const VALUE_TYPE& value,
518 ALLOCATOR allocator,
520 int,
522 template <class ALLOCATOR>
523 static void
525 Iterator fromBegin,
526 Iterator position,
527 size_type numElements,
528 const VALUE_TYPE& value,
529 ALLOCATOR allocator,
531 int,
533 template <class ALLOCATOR>
534 static void insertAndMoveToFront(
535 Iterator *toBegin,
536 Iterator fromBegin,
537 Iterator position,
538 size_type numElements,
539 const VALUE_TYPE& value,
540 ALLOCATOR allocator,
542
543 /// Insert the specified `numElements` in the range `[first .. last)` at
544 /// the specified `position`, by moving the elements in the range
545 /// `[fromBegin .. position)` backward by `numElements` position. Pass
546 /// the specified `allocator` to the copy constructor if appropriate.
547 /// Load into the specified `toBegin` an iterator to the end of the data
548 /// after insertion (i.e., `fromBegin - numElements`).
549 ///
550 /// \pre The behavior is undefined unless `fromBegin - numElements` is a valid iterator
551 /// (i.e., the block pointer array holds enough room before the
552 /// `fromBefore` position to insert `numElements`).
553 template <class FWD_ITER, class SENTINEL, class ALLOCATOR>
554 static void insertAndMoveToFront(Iterator *toBegin,
555 Iterator fromBegin,
556 Iterator position,
557 FWD_ITER first,
558 SENTINEL last,
559 size_type numElements,
560 ALLOCATOR allocator);
561
562 /// Insert the specified move-insertable `value` at the specified
563 /// `position` by moving the elements in the range
564 /// `[fromBegin .. position)` backward by 1 position; pass the specified
565 /// `allocator` to the move constructor if appropriate. Load into the
566 /// specified `toBegin` an iterator to the inserted element (i.e., `fromBegin - 1`).
567 ///
568 /// \pre The behavior is undefined unless
569 /// `fromBegin - 1` is a valid iterator (i.e., the block pointer array
570 /// holds enough room before the `fromBegin` position to insert 1
571 /// element).
572 template <class ALLOCATOR>
573 static void moveInsertAndMoveToFront(
574 Iterator *toBegin,
575 Iterator fromBegin,
576 Iterator position,
578 ALLOCATOR allocator);
579
580 /// Insert the specified move-insertable `value` at the specified
581 /// `position` by moving the elements in the range
582 /// `[fromBegin .. position)` backward by 1 position; pass the specified
583 /// `allocator` to the move constructor if appropriate. Load into the
584 /// specified `toBegin` an iterator to the inserted element (i.e., `fromBegin - 1`).
585 ///
586 /// \pre The behavior is undefined unless
587 /// `fromBegin - 1` is a valid iterator (i.e., the block pointer array
588 /// holds enough room before the `fromBegin` position to insert 1 element).
589 ///
590 /// \note Note that the last argument is for removing overload
591 /// ambiguities and is not used.
592 template <class ALLOCATOR>
593 static void moveInsertAndMoveToFront(
594 Iterator *toBegin,
595 Iterator fromBegin,
596 Iterator position,
598 ALLOCATOR allocator,
600 int,
602 template <class ALLOCATOR>
603 static void moveInsertAndMoveToFront(
604 Iterator *toBegin,
605 Iterator fromBegin,
606 Iterator position,
608 ALLOCATOR allocator,
610 int,
612 template <class ALLOCATOR>
613 static void moveInsertAndMoveToFront(
614 Iterator *toBegin,
615 Iterator fromBegin,
616 Iterator position,
618 ALLOCATOR allocator,
620
621#if !BSLS_COMPILERFEATURES_SIMULATE_CPP11_FEATURES
622 /// Insert at the specified `position` a newly created `VALUE_TYPE`
623 /// object, constructed by forwarding the specified `allocator` (if
624 /// required) and the specified (variable number of) `arguments` to the
625 /// corresponding constructor of `VALUE_TYPE`, and move the elements in
626 /// the range `[position .. fromEnd)` forward by 1 position. Load into
627 /// the specified `toEnd` an iterator one past the inserted element (i.e., `fromEnd + 1`).
628 ///
629 /// \pre The behavior is undefined unless
630 /// `fromEnd + 1` is a valid iterator (i.e., the block pointer array
631 /// holds enough room after the `fromEnd` position to insert 1 element).
632 template <class ALLOCATOR, class... Args>
633 static void emplaceAndMoveToBack(Iterator *toEnd,
634 Iterator fromEnd,
635 Iterator position,
636 ALLOCATOR allocator,
637 Args&&... arguments);
638
639 /// Insert at the specified `position` a newly created `VALUE_TYPE`
640 /// object, constructed by forwarding the specified `allocator` (if
641 /// required) and the specified (variable number of) `arguments` to the
642 /// corresponding constructor of `VALUE_TYPE`, and move the elements in
643 /// the range `[position .. fromEnd)` forward by 1 position. Load into
644 /// the specified `toEnd` an iterator one past the inserted element (i.e., `fromEnd + 1`).
645 ///
646 /// \pre The behavior is undefined unless
647 /// `fromEnd + 1` is a valid iterator (i.e., the block pointer array
648 /// holds enough room after the `fromEnd` position to insert 1 element).
649 ///
650 /// \note Note that the next to last argument is for removing overload
651 /// ambiguities and is not used.
652 template <class ALLOCATOR, class... Args>
654 Iterator *toEnd,
655 Iterator fromEnd,
656 Iterator position,
657 ALLOCATOR allocator,
660 Args&&... arguments);
661 template <class ALLOCATOR, class... Args>
663 Iterator *toEnd,
664 Iterator fromEnd,
665 Iterator position,
666 ALLOCATOR allocator,
669 Args&&... arguments);
670 template <class ALLOCATOR, class... Args>
672 Iterator *toEnd,
673 Iterator fromEnd,
674 Iterator position,
675 ALLOCATOR allocator,
677 Args&&... arguments);
678
679 /// Insert at the specified `position` a newly created `VALUE_TYPE`
680 /// object, constructed by forwarding the specified `allocator` (if
681 /// required) and the specified (variable number of) `arguments` to the
682 /// corresponding constructor of `VALUE_TYPE`, and move the elements in
683 /// the range `[fromBegin .. position)` backward by 1 position. Load
684 /// into the specified `toBegin` an iterator to the inserted element (i.e., `fromBegin - 1`).
685 ///
686 /// \pre The behavior is undefined unless
687 /// `fromBegin - 1` is a valid iterator (i.e., the block pointer array
688 /// holds enough room before the `fromBegin` position to insert 1
689 /// element).
690 template <class ALLOCATOR, class... Args>
691 static void emplaceAndMoveToFront(Iterator *toBegin,
692 Iterator fromBegin,
693 Iterator position,
694 ALLOCATOR allocator,
695 Args&&... arguments);
696
697 /// Insert at the specified `position` a newly created `VALUE_TYPE`
698 /// object, constructed by forwarding the specified `allocator` (if
699 /// required) and the specified (variable number of) `arguments` to the
700 /// corresponding constructor of `VALUE_TYPE`, and move the elements in
701 /// the range `[fromBegin .. position)` backward by 1 position. Load
702 /// into the specified `toBegin` an iterator to the inserted element (i.e., `fromBegin - 1`).
703 ///
704 /// \pre The behavior is undefined unless
705 /// `fromBegin - 1` is a valid iterator (i.e., the block pointer array
706 /// holds enough room before the `fromBegin` position to insert 1 element).
707 ///
708 /// \note Note that the next to last argument is for removing
709 /// overload ambiguities and is not used.
710 template <class ALLOCATOR, class... Args>
712 Iterator *toBegin,
713 Iterator fromBegin,
714 Iterator position,
715 ALLOCATOR allocator,
718 Args&&... arguments);
719 template <class ALLOCATOR, class... Args>
721 Iterator *toBegin,
722 Iterator fromBegin,
723 Iterator position,
724 ALLOCATOR allocator,
727 Args&&... arguments);
728 template <class ALLOCATOR, class... Args>
730 Iterator *toBegin,
731 Iterator fromBegin,
732 Iterator position,
733 ALLOCATOR allocator,
735 Args&&... arguments);
736#endif
737
738 /// Move the specified `numElements` from the specified `source` to the
739 /// specified `destination` using `std::memmove`. Also load into
740 /// `destination` the value `destination - numElements` and `source` the value `source - numElements`.
741 ///
742 /// \pre The behavior is undefined unless
743 /// `destination >= source`.
744 static void moveBack(Iterator *destination,
745 Iterator *source,
746 size_type numElements);
747
748 /// Move the specified `numElements` from the specified `source` to the
749 /// specified `destination` using `std::memmove`. Also load into
750 /// `destination` the value `destination + numElements` and `source` the the value `source + numElements`.
751 ///
752 /// \pre The behavior is undefined unless
753 /// `destination <= source`.
754 static void moveFront(Iterator *destination,
755 Iterator *source,
756 size_type numElements);
757
758 /// Append the specified `numElements` copies of the specified `value`
759 /// to the deque ending at the specified `fromEnd` iterator, passing the
760 /// specified `allocator` through to the new elements, and load into the
761 /// specified `toEnd` an iterator pointing to the end of the data after
762 /// appending (i.e., `fromEnd + numElements`).
763 ///
764 /// \pre The behavior is undefined unless `fromEnd + numElements` is a valid iterator (i.e.,
765 /// the block pointer array holds enough room after the `fromEnd`
766 /// position to insert `numElements`).
767 template <class ALLOCATOR>
768 static void uninitializedFillNBack(Iterator *toEnd,
769 Iterator fromEnd,
770 size_type numElements,
771 const VALUE_TYPE& value,
772 ALLOCATOR allocator);
773
774 /// Prepend the specified `numElements` copies of the specified `value`
775 /// to the deque starting at the specified `fromBegin` iterator, passing
776 /// the specified `allocator` through to the new elements, and load into
777 /// the specified `toBegin` an iterator pointing to the end of the data
778 /// after prepending, i.e., `fromBegin - numElements`.
779 ///
780 /// \pre The behavior is undefined unless `fromBegin - numElements` is a valid iterator
781 /// (i.e., the block pointer array holds enough room before the
782 /// `fromBegin` position to insert `numElements`).
783 template <class ALLOCATOR>
784 static void uninitializedFillNFront(Iterator *toBegin,
785 Iterator fromBegin,
786 size_type numElements,
787 const VALUE_TYPE& value,
788 ALLOCATOR allocator);
789
790 /// Append the specified `numElements` value-initialized objects to the
791 /// deque ending at the specified `fromEnd` iterator, passing the
792 /// specified `allocator` through to the new elements, and load into the
793 /// specified `toEnd` an iterator pointing to the end of the data after
794 /// appending (i.e., `fromEnd + numElements`).
795 ///
796 /// \pre The behavior is undefined unless `fromEnd + numElements` is a valid iterator (i.e.,
797 /// the block pointer array holds enough room after the `fromEnd`
798 /// position to insert `numElements`).
799 template <class ALLOCATOR>
800 static void valueInititalizeN(Iterator *toEnd,
801 Iterator fromEnd,
802 size_type numElements,
803 ALLOCATOR allocator);
804};
805
806// PARTIAL SPECIALIZATION
807
808/// This is a partial specialization of `DequePrimitives` for the case when
809/// there is a single element per block.
810template <class VALUE_TYPE>
811struct DequePrimitives<VALUE_TYPE, 1> {
812
813 // PUBLIC TYPES
814 typedef std::size_t size_type;
817
818 // CLASS METHODS
819 template <class ALLOCATOR>
820 static void destruct(Iterator begin, Iterator end, ALLOCATOR allocator);
821
822 template <class ALLOCATOR>
823 static Iterator erase(Iterator *toBegin,
824 Iterator *toEnd,
825 Iterator fromBegin,
826 Iterator first,
827 Iterator last,
828 Iterator fromEnd,
829 ALLOCATOR allocator);
830
831 template <class ALLOCATOR>
832 static void insertAndMoveToBack(Iterator *toEnd,
833 Iterator fromEnd,
834 Iterator position,
835 size_type numElements,
836 const VALUE_TYPE& value,
837 ALLOCATOR allocator);
838
839 template <class FWD_ITER, class SENTINEL, class ALLOCATOR>
840 static void insertAndMoveToBack(Iterator *toEnd,
841 Iterator fromEnd,
842 Iterator position,
843 FWD_ITER first,
844 SENTINEL last,
845 size_type numElements,
846 ALLOCATOR allocator);
847
848 template <class ALLOCATOR>
849 static void insertAndMoveToFront(Iterator *toBegin,
850 Iterator fromBegin,
851 Iterator position,
852 size_type numElements,
853 const VALUE_TYPE& value,
854 ALLOCATOR allocator);
855
856 template <class FWD_ITER, class SENTINEL, class ALLOCATOR>
857 static void insertAndMoveToFront(Iterator *toBegin,
858 Iterator fromBegin,
859 Iterator position,
860 FWD_ITER first,
861 SENTINEL last,
862 size_type numElements,
863 ALLOCATOR allocator);
864
865 template <class ALLOCATOR>
866 static void uninitializedFillNBack(Iterator *toEnd,
867 Iterator fromEnd,
868 size_type numElements,
869 const VALUE_TYPE& value,
870 ALLOCATOR allocator);
871 template <class ALLOCATOR>
872 static void uninitializedFillNBack(
873 Iterator *toEnd,
874 Iterator fromEnd,
875 size_type numElements,
876 const VALUE_TYPE& value,
877 ALLOCATOR allocator,
880 template <class ALLOCATOR>
881 static void uninitializedFillNBack(
882 Iterator *toEnd,
883 Iterator fromEnd,
884 size_type numElements,
885 const VALUE_TYPE& value,
886 ALLOCATOR allocator,
888
889 template <class ALLOCATOR>
890 static void uninitializedFillNFront(Iterator *toBegin,
891 Iterator fromBegin,
892 size_type numElements,
893 const VALUE_TYPE& value,
894 ALLOCATOR allocator);
895 template <class ALLOCATOR>
896 static void uninitializedFillNFront(
897 Iterator *toBegin,
898 Iterator fromBegin,
899 size_type numElements,
900 const VALUE_TYPE& value,
901 ALLOCATOR allocator,
903 template <class ALLOCATOR>
904 static void uninitializedFillNFront(
905 Iterator *toBegin,
906 Iterator fromBegin,
907 size_type numElements,
908 const VALUE_TYPE& value,
909 ALLOCATOR allocator,
911
912 template <class ALLOCATOR>
913 static void valueInititalizeN(Iterator *toEnd,
914 Iterator fromEnd,
915 size_type numElements,
916 ALLOCATOR allocator);
917
918 template <class ALLOCATOR>
919 static void valueInititalizeN(
920 Iterator *toEnd,
921 Iterator fromEnd,
922 size_type numElements,
923 ALLOCATOR allocator,
925
926 template <class ALLOCATOR>
927 static void valueInititalizeN(
928 Iterator *toEnd,
929 Iterator fromEnd,
930 size_type numElements,
931 ALLOCATOR allocator,
933};
934
935 // =======================================
936 // class DequePrimitives_DequeElementGuard
937 // =======================================
938
939/// This `class` provides a specialized proctor object that, upon
940/// destruction and unless the `release` method has been called, destroys
941/// the elements in a segment of a deque of parameterized `VALUE_TYPE`. The
942/// elements destroyed are delimited by the "guarded" range
943/// `[d_begin .. d_end)`.
944///
945/// See @ref bslalg_dequeprimitives
946template <class VALUE_TYPE, int BLOCK_LENGTH, class ALLOCATOR>
948
949 public:
950 // PUBLIC TYPES
952
953 private:
954 // DATA
955 Iterator d_begin; // iterator of first element in guarded range
956 Iterator d_end; // iterator beyond last element in guarded range
957 ALLOCATOR d_allocator;
958
959 private:
960 // NOT IMPLEMENTED
965
966 public:
967 // CREATORS
968
969 /// Create a deque exception guard object for the sequence of elements
970 /// of the parameterized `VALUE_TYPE` delimited by the specified range `[begin .. end)`.
971 ///
972 /// \pre The behavior is undefined unless `begin <= end`
973 /// and unless each element in the range `[begin .. end)` has been
974 /// initialized.
976 const Iterator& end,
977 ALLOCATOR allocator);
978
979 /// Call the destructor on each of the elements of the parameterized
980 /// `VALUE_TYPE` delimited by the range `[begin .. end)` and destroy
981 /// this array exception guard.
983
984 // MANIPULATORS
985
986 /// Move the begin iterator by the specified `offset`, and return the
987 /// new begin iterator.
988 Iterator& moveBegin(std::ptrdiff_t offset = -1);
989
990 /// Move the end pointer by the specified `offset`, and return the new
991 /// end pointer.
992 Iterator& moveEnd(std::ptrdiff_t offset = 1);
993
994 /// Set the range of elements guarded by this object to be empty.
995 ///
996 /// \note Note that `d_begin == d_end` following this operation, but the specific
997 /// value is unspecified.
998 void release();
999};
1000
1001 // ===============================================
1002 // class DequePrimitives_ExternalDequeElementGuard
1003 // ===============================================
1004
1005/// This `class` provides a specialized proctor object that, upon
1006/// destruction and unless the `release` method has been called, destroys
1007/// the elements in a segment of a `bsl::deque` of parameterized type
1008/// `VALUE_TYPE`. The elements destroyed are delimited by the "guarded" range `[*d_begin .. *d_end)`.
1009///
1010/// \note Note that the range guarded by this
1011/// `class` is dynamic and can be changed outside of this `class`.
1012///
1013/// See @ref bslalg_dequeprimitives
1014template <class VALUE_TYPE, int BLOCK_LENGTH, class ALLOCATOR>
1016
1017 public:
1018 // PUBLIC TYPES
1020
1021 private:
1022 // DATA
1023 Iterator *d_begin_p; // pointer to iterator of first element in guarded
1024 // range
1025
1026 Iterator *d_end_p; // pointer to iterator beyond last element in
1027 // guarded range
1028 ALLOCATOR d_allocator;
1029
1030 private:
1031 // NOT IMPLEMENTED
1036
1037 public:
1038 // CREATORS
1039
1040 /// Create a deque exception guard object for the sequence of elements
1041 /// of the parameterized `VALUE_TYPE` delimited by the specified range `[*begin .. *end)`.
1042 ///
1043 /// \pre The behavior is undefined unless `*begin` <=
1044 /// `*end` and unless each element in the range `[*begin .. *end)` has
1045 /// been initialized.
1047 Iterator *end,
1048 ALLOCATOR allocator);
1049
1050 /// Call the destructor on each of the elements of the parameterized
1051 /// `VALUE_TYPE` delimited by the range `[*d_begin_p .. *d_end_p)` and
1052 /// destroy this array exception guard.
1054
1055 // MANIPULATORS
1056
1057 /// Set the range of elements guarded by this object to be empty.
1058 ///
1059 /// \note Note that `d_begin_p == d_end_p == 0` following this operation.
1060 void release();
1061};
1062
1063 // ====================================
1064 // class DequePrimitives_DequeMoveGuard
1065 // ====================================
1066
1067/// This `class` provides a guard object that, upon destruction and unless
1068/// the `release` method has been called, uses `moveBack` or `moveFront` to
1069/// move the "guarded" range `[d_source_p .. d_source_p + d_size - 1]`
1070/// back to `[d_destination_p .. d_destination_p + d_size -1]`.
1071///
1072/// See @ref bslalg_dequeprimitives
1073template <class VALUE_TYPE, int BLOCK_LENGTH>
1075
1076 public:
1077 // PUBLIC TYPES
1080
1081 private:
1082 // DATA
1083 Iterator d_destination_p; // destination of the move
1084 Iterator d_source_p; // source of the move
1085 std::size_t d_size; // size of the range being guarded
1086 bool d_front; // whether to use 'moveFront'
1087
1088 private:
1089 // NOT IMPLEMENTED
1093
1094 public:
1095 // CREATORS
1096
1097 /// Create a guard object that will call `moveBack` or `moveFront`,
1098 /// depending on the specified `isFront`, on the specified `size`
1099 /// elements from `src` to `dest` upon destruction unless `release` has
1100 /// been called.
1102 Iterator src,
1103 std::size_t size,
1104 bool isFront);
1105
1106 /// Call either `moveBack` or `moveFront` depending on `d_front` upon
1107 /// destruction unless `release` has been called before this.
1109
1110 // MANIPULATORS
1111
1112 /// Set the size of the range guarded by this object to be zero.
1113 void release();
1114};
1115
1116 // ==========================================
1117 // class DequePrimitives_DequeEndpointProctor
1118 // ==========================================
1119
1120/// This class implements a proctor that, upon destruction and unless its
1121/// `release` method has previously been invoked, sets a deque endpoint
1122/// (i.e., "start" or "finish" iterator) to a position within the deque.
1123/// Both the endpoint and position are supplied at construction. See
1124/// `emplaceAndMoveToBack` and `emplaceAndMoveToFront` for use cases.
1125///
1126/// See @ref bslalg_dequeprimitives
1127template <class VALUE_TYPE, int BLOCK_LENGTH>
1129
1130 public:
1131 // PUBLIC TYPES
1133
1134 private:
1135 // DATA
1136 Iterator *d_endpoint_p; // proctored endpoint of a deque
1137 Iterator d_position; // set endpoint to this upon destruction
1138
1139 private:
1140 // NOT IMPLEMENTED
1145
1146 public:
1147 // CREATORS
1148
1149 /// Create a deque endpoint proctor that conditionally manages the
1150 /// specified `endpoint` (if non-zero) by setting `*endpoint` to the
1151 /// specified `position` (if not released -- see `release`) upon
1152 /// destruction.
1154 Iterator position);
1155
1156 /// Destroy this endpoint proctor, and set the deque endpoint it manages
1157 /// (if any) to the position supplied at construction. If no endpoint
1158 /// is currently being managed, this method has no effect.
1160
1161 // MANIPULATORS
1162
1163 /// Release from management the deque endpoint currently managed by this
1164 /// proctor. If no endpoint is currently being managed, this method has
1165 /// no effect.
1166 void release();
1167};
1168
1169// ============================================================================
1170// INLINE FUNCTION DEFINITIONS
1171// ============================================================================
1172
1173 // ---------------------
1174 // class DequePrimitives
1175 // ---------------------
1176
1177// CLASS METHODS
1178template <class VALUE_TYPE, int BLOCK_LENGTH>
1179template <class ALLOCATOR>
1180inline
1182 Iterator end,
1183 ALLOCATOR allocator)
1184{
1185 enum {
1187
1188 VALUE = IS_BITWISECOPYABLE
1191 };
1192
1193 return destruct(begin,
1194 end,
1195 allocator,
1197}
1198
1199template <class VALUE_TYPE, int BLOCK_LENGTH>
1200template <class ALLOCATOR>
1209
1210template <class VALUE_TYPE, int BLOCK_LENGTH>
1211template <class ALLOCATOR>
1213 Iterator begin,
1214 Iterator end,
1215 ALLOCATOR allocator,
1217{
1218 for (; !(begin == end); ++begin) {
1220 begin.valuePtr());
1221 }
1222}
1223
1224template <class VALUE_TYPE, int BLOCK_LENGTH>
1225template <class ALLOCATOR>
1226inline
1227typename
1230 Iterator *toEnd,
1231 Iterator fromBegin,
1232 Iterator first,
1233 Iterator last,
1234 Iterator fromEnd,
1235 ALLOCATOR allocator)
1236{
1237 enum {
1239
1240 VALUE = IS_BITWISECOPYABLE
1243 };
1244
1245 return erase(toBegin,
1246 toEnd,
1247 fromBegin,
1248 first,
1249 last,
1250 fromEnd,
1251 allocator,
1253}
1254
1255template <class VALUE_TYPE, int BLOCK_LENGTH>
1256template <class ALLOCATOR>
1259 Iterator *toBegin,
1260 Iterator *toEnd,
1261 Iterator fromBegin,
1262 Iterator first,
1263 Iterator last,
1264 Iterator fromEnd,
1265 ALLOCATOR allocator,
1267{
1268 if (first == last) { // Nothing to delete, bail out fast
1269 *toBegin = fromBegin;
1270 *toEnd = fromEnd;
1271 return first; // RETURN
1272 }
1273
1274 size_type frontSize = first - fromBegin;
1275 size_type backSize = fromEnd - last;
1276 Iterator ret;
1277
1278 if (frontSize < backSize) {
1279 ret = last;
1280 for (; 0 < frontSize; --frontSize) {
1281 --last;
1282 --first;
1283 *last = MoveUtil::move(*first);
1284 }
1285 *toBegin = last;
1286 *toEnd = fromEnd;
1287 }
1288 else {
1289 ret = first;
1290 for (; 0 < backSize; --backSize, ++first, ++last) {
1291 *first = MoveUtil::move(*last);
1292 }
1293 *toBegin = fromBegin;
1294 *toEnd = first;
1295 }
1296 destruct(first, last, allocator);
1297 return ret;
1298}
1299
1300template <class VALUE_TYPE, int BLOCK_LENGTH>
1301template <class ALLOCATOR>
1304 Iterator *toBegin,
1305 Iterator *toEnd,
1306 Iterator fromBegin,
1307 Iterator first,
1308 Iterator last,
1309 Iterator fromEnd,
1310 ALLOCATOR,
1313{
1314 size_type frontSize = first - fromBegin;
1315 size_type backSize = fromEnd - last;
1316 Iterator ret;
1317
1318 if (frontSize < backSize) {
1319 ret = last;
1320 moveBack(&last, &first, frontSize);
1321 *toBegin = last;
1322 *toEnd = fromEnd;
1323 }
1324 else {
1325 ret = first;
1326 moveFront(&first, &last, backSize);
1327 *toBegin = fromBegin;
1328 *toEnd = first;
1329 }
1330 // 'destruct' is no-op for types with 'BITWISE_COPYABLE_TRAITS'.
1331 return ret;
1332}
1333
1334template <class VALUE_TYPE, int BLOCK_LENGTH>
1335template <class ALLOCATOR>
1336inline
1337void
1340 Iterator fromEnd,
1341 Iterator position,
1342 size_type numElements,
1343 const VALUE_TYPE& value,
1344 ALLOCATOR allocator)
1345{
1346 enum {
1349
1350 VALUE = IS_BITWISECOPYABLE
1352 : IS_BITWISEMOVEABLE
1355 };
1356
1357 insertAndMoveToBack(toEnd,
1358 fromEnd,
1359 position,
1360 numElements,
1361 value,
1362 allocator,
1364}
1365
1366template <class VALUE_TYPE, int BLOCK_LENGTH>
1367template <class ALLOCATOR>
1369 Iterator *toEnd,
1370 Iterator fromEnd,
1371 Iterator position,
1372 size_type numElements,
1373 const VALUE_TYPE& value,
1374 ALLOCATOR allocator,
1377{
1378 size_type backSize = fromEnd - position;
1379 Iterator end = fromEnd;
1380 Iterator dest = end + numElements;
1381
1384 BSLS_UTIL_ADDRESSOF(space.object()),
1386 value);
1388 temp(BSLS_UTIL_ADDRESSOF(space.object()));
1389
1390 // TBD: this does the same thing as the old code - don't like that we
1391 // circumvent the whole allocator thing, but for now, let's keep it
1392 // consistent.
1393 // ConstructorProxy<VALUE_TYPE>
1394 // tempValue(value, bslma::Default::allocator());
1395
1396 // No guard needed since all the operations won't throw due to the
1397 // bitwise-copyable trait
1398 moveBack(&dest, &end, backSize);
1399 uninitializedFillNFront(&dest, dest, numElements, space.object(),
1400 allocator);
1401
1402 *toEnd = fromEnd + numElements;
1403}
1404
1405template <class VALUE_TYPE, int BLOCK_LENGTH>
1406template <class ALLOCATOR>
1408 Iterator *toEnd,
1409 Iterator fromEnd,
1410 Iterator position,
1411 size_type numElements,
1412 const VALUE_TYPE& value,
1413 ALLOCATOR allocator,
1416{
1418 BLOCK_LENGTH,
1419 ALLOCATOR> ExtGuard;
1420
1421
1422 size_type backSize = fromEnd - position;
1423 Iterator end = fromEnd;
1424 Iterator dest = end + numElements;
1425
1426 // In case of aliasing, make a copy of the value.
1429 BSLS_UTIL_ADDRESSOF(space.object()),
1431 value);
1433 temp(BSLS_UTIL_ADDRESSOF(space.object()));
1434
1435 // TBD: this does the same thing as the old code - don't like that we
1436 // circumvent the whole allocator thing, but for now, let's keep it
1437 // consistent.
1438 // ConstructorProxy<VALUE_TYPE>
1439 // tempValue(value, bslma::Default::allocator());
1440
1441 // Setup a reverse guard that will reverse the moveBack operation in case
1442 // of an exception.
1443 MoveGuard guard(end, dest, backSize, false);
1444
1445 moveBack(&dest, &end, backSize);
1446
1447 // Create a guard for 'uninitializedFillNBack' because it can throw under
1448 // 'bitwisemoveable' trait. Need to use this special guard because
1449 // uninitializedFillNFront is not exception safe.
1450 Iterator dest2(dest);
1451 ExtGuard eguard(&dest, &dest2, allocator);
1452
1453 uninitializedFillNFront(&dest, dest, numElements, space.object(),
1454 allocator);
1455 eguard.release();
1456 guard.release();
1457 *toEnd = fromEnd + numElements;
1458}
1459
1460template <class VALUE_TYPE, int BLOCK_LENGTH>
1461template <class ALLOCATOR>
1463 Iterator *toEnd,
1464 Iterator fromEnd,
1465 Iterator position,
1466 size_type numElements,
1467 const VALUE_TYPE& value,
1468 ALLOCATOR allocator,
1470{
1471 typedef DequePrimitives_DequeElementGuard<VALUE_TYPE,
1472 BLOCK_LENGTH,
1473 ALLOCATOR> ElementGuard;
1474
1475 size_type backSize = fromEnd - position;
1476 Iterator end = fromEnd;
1477 Iterator dest = end + numElements;
1478 size_type numDest;
1479
1480 // In case of aliasing, make a copy of the value.
1481
1485 value);
1487 temp(BSLS_UTIL_ADDRESSOF(space.object()));
1488
1489 // TBD: this does the same thing as the old code - don't like that we
1490 // circumvent the whole allocator thing, but for now, let's keep it
1491 // consistent.
1492 // ConstructorProxy<VALUE_TYPE> tempValue(value,
1493 // bslma::Default::allocator());
1494
1495 ElementGuard guard(dest, dest, allocator);
1496 if (backSize >= numElements) {
1497 for (numDest = numElements; 0 < numDest; --numDest) {
1498 --dest;
1499 --end;
1501 dest.valuePtr(),
1502 *end);
1503 guard.moveBegin(-1);
1504 }
1505 for (backSize -= numElements; 0 < backSize; --backSize) {
1506 --dest;
1507 --end;
1508 *dest = *end;
1509 }
1510 for (numDest = numElements; 0 < numDest; --numDest, ++position) {
1511 *position = space.object();
1512 }
1513 } else {
1514 for (numDest = backSize; 0 < numDest; --numDest) {
1515 --dest;
1516 --end;
1518 dest.valuePtr(),
1519 *end);
1520 guard.moveBegin(-1);
1521 }
1522 for (numDest = numElements; backSize < numDest; --numDest) {
1523 --dest;
1525 dest.valuePtr(),
1526 space.object());
1527
1528 guard.moveBegin(-1);
1529 }
1530 for (; 0 < numDest; --numDest, ++position) {
1531 *position = space.object();
1532 }
1533 }
1534 guard.release();
1535
1536 *toEnd = fromEnd + numElements;
1537}
1538
1539template <class VALUE_TYPE, int BLOCK_LENGTH>
1540template <class FWD_ITER, class SENTINEL, class ALLOCATOR>
1541void
1544 Iterator fromEnd,
1545 Iterator position,
1546 FWD_ITER first,
1547 SENTINEL /*last*/,
1548 size_type numElements,
1549 ALLOCATOR allocator)
1550{
1551 typedef DequePrimitives_DequeElementGuard<VALUE_TYPE,
1552 BLOCK_LENGTH,
1553 ALLOCATOR> ElementGuard;
1554
1555 size_type backSize = fromEnd - position;
1556 Iterator end = fromEnd;
1557 Iterator dest = end + numElements;
1558 size_type numDest;
1559
1560 ElementGuard guard(dest, dest, allocator);
1561 if (backSize >= numElements) {
1562 for (numDest = numElements; 0 < numDest; --numDest) {
1563 --dest;
1564 --end;
1566 dest.valuePtr(),
1567 *end);
1568 guard.moveBegin(-1);
1569 }
1570 for (numDest = backSize; numElements < numDest; --numDest) {
1571 --dest;
1572 --end;
1573 *dest = *end;
1574 }
1575 for (; 0 < numDest; ++first, ++position, --numDest) {
1576 *position = *first;
1577 }
1578 } else {
1579 for (numDest = backSize; 0 < numDest; --numDest) {
1580 --dest;
1581 --end;
1583 dest.valuePtr(),
1584 *end);
1585 guard.moveBegin(-1);
1586 }
1587 for (numDest = backSize; 0 < numDest; --numDest, ++position, ++first) {
1588 *position = *first;
1589 }
1590 // Second guard needed because we're guarding from a different range.
1591 ElementGuard guard2(position, position, allocator);
1592 for (numDest = numElements; backSize < numDest; ++first, ++position,
1593 --numDest) {
1595 position.valuePtr(),
1596 *first);
1597 guard2.moveEnd(1);
1598 }
1599 guard2.release();
1600 }
1601 guard.release();
1602 *toEnd = fromEnd + numElements;
1603}
1604
1605template <class VALUE_TYPE, int BLOCK_LENGTH>
1606template <class ALLOCATOR>
1607inline
1608void
1610 Iterator *toEnd,
1611 Iterator fromEnd,
1612 Iterator position,
1614 ALLOCATOR allocator)
1615{
1616 enum {
1619
1620 VALUE = IS_BITWISECOPYABLE
1622 : IS_BITWISEMOVEABLE
1625 };
1626
1627 VALUE_TYPE& lvalue = value;
1628
1629 moveInsertAndMoveToBack(toEnd,
1630 fromEnd,
1631 position,
1632 MoveUtil::move(lvalue),
1633 allocator,
1635}
1636
1637template <class VALUE_TYPE, int BLOCK_LENGTH>
1638template <class ALLOCATOR>
1640 Iterator *toEnd,
1641 Iterator fromEnd,
1642 Iterator position,
1644 ALLOCATOR allocator,
1647{
1648 const size_type backSize = fromEnd - position;
1649 Iterator end = fromEnd;
1650 Iterator dest = end + 1;
1651
1652 // No guard needed since no operations will throw with
1653 // 'BITWISE_COPYABLE_TRAITS'.
1654
1655 moveBack(&dest, &end, backSize);
1656 --dest;
1657
1658 VALUE_TYPE& lvalue = value;
1660 dest.valuePtr(),
1661 MoveUtil::move(lvalue));
1662
1663 *toEnd = fromEnd + 1;
1664}
1665
1666template <class VALUE_TYPE, int BLOCK_LENGTH>
1667template <class ALLOCATOR>
1669 Iterator *toEnd,
1670 Iterator fromEnd,
1671 Iterator position,
1673 ALLOCATOR allocator,
1676{
1677 const size_type backSize = fromEnd - position;
1678 Iterator end = fromEnd;
1679 Iterator dest = end + 1;
1680
1681 // Create a reverse guard that will undo the 'moveBack' operation in case
1682 // of an exception.
1683
1684 MoveGuard guard(end, dest, backSize, false);
1685
1686 moveBack(&dest, &end, backSize);
1687 --dest;
1688
1689 VALUE_TYPE& lvalue = value;
1691 dest.valuePtr(),
1692 MoveUtil::move(lvalue));
1693
1694 guard.release();
1695
1696 *toEnd = fromEnd + 1;
1697}
1698
1699template <class VALUE_TYPE, int BLOCK_LENGTH>
1700template <class ALLOCATOR>
1702 Iterator *toEnd,
1703 Iterator fromEnd,
1704 Iterator position,
1706 ALLOCATOR allocator,
1708{
1709 typedef DequePrimitives_DequeElementGuard<VALUE_TYPE,
1710 BLOCK_LENGTH,
1711 ALLOCATOR> ElementGuard;
1712
1713 size_type backSize = fromEnd - position;
1714 Iterator end = fromEnd;
1715 Iterator dest = end + 1;
1716
1717 BSLS_ASSERT_SAFE(backSize >= 1);
1718
1719 ElementGuard guard(dest, dest, allocator);
1720
1721 // 1. move-construct back-most element being bumped 1 slot
1722
1723 --dest;
1724 --end;
1726 allocator,
1727 dest.valuePtr(),
1728 MoveUtil::move_if_noexcept(*end));
1729 guard.moveBegin(-1);
1730
1731 // 2. move-assign other existing elements being bumped back 1 slot
1732
1733 for (backSize -= 1; 0 < backSize; --backSize) {
1734 --dest;
1735 --end;
1736 *dest = MoveUtil::move_if_noexcept(*end);
1737 }
1738
1739 // 3. move-assign new element
1740
1741 VALUE_TYPE& lvalue = value;
1742 *position = MoveUtil::move(lvalue);
1743
1744 guard.release();
1745
1746 *toEnd = fromEnd + 1;
1747}
1748
1749template <class VALUE_TYPE, int BLOCK_LENGTH>
1750template <class ALLOCATOR>
1751inline
1752void
1755 Iterator fromBegin,
1756 Iterator position,
1757 size_type numElements,
1758 const VALUE_TYPE& value,
1759 ALLOCATOR allocator)
1760{
1761 enum {
1764
1765 VALUE = IS_BITWISECOPYABLE
1767 : IS_BITWISEMOVEABLE
1770 };
1771
1772 insertAndMoveToFront(toBegin,
1773 fromBegin,
1774 position,
1775 numElements,
1776 value,
1777 allocator,
1779}
1780
1781template <class VALUE_TYPE, int BLOCK_LENGTH>
1782template <class ALLOCATOR>
1784 Iterator *toBegin,
1785 Iterator fromBegin,
1786 Iterator position,
1787 size_type numElements,
1788 const VALUE_TYPE& value,
1789 ALLOCATOR allocator,
1792{
1793 size_type frontSize = position - fromBegin;
1794 Iterator begin = fromBegin;
1795 Iterator dest = begin - numElements;
1796
1797 // In case of aliasing, make a copy of the value.
1801 value);
1803 temp(BSLS_UTIL_ADDRESSOF(space.object()));
1804
1805 // TBD: this does the same thing as the old code - don't like that we
1806 // circumvent the whole allocator thing, but for now, let's keep it
1807 // consistent.
1808 // ConstructorProxy<VALUE_TYPE>
1809 // tempValue(value, bslma::Default::allocator());
1810
1811 // No guard needed since all the operations won't throw due to the
1812 // bitwise-copyable trait
1813 moveFront(&dest, &begin, frontSize);
1814 uninitializedFillNBack(&dest, dest, numElements, space.object(),
1815 allocator);
1816
1817 *toBegin = fromBegin - numElements;
1818}
1819
1820template <class VALUE_TYPE, int BLOCK_LENGTH>
1821template <class ALLOCATOR>
1823 Iterator *toBegin,
1824 Iterator fromBegin,
1825 Iterator position,
1826 size_type numElements,
1827 const VALUE_TYPE& value,
1828 ALLOCATOR allocator,
1831{
1833 BLOCK_LENGTH,
1834 ALLOCATOR> ExtGuard;
1835 size_type frontSize = position - fromBegin;
1836 Iterator begin = fromBegin;
1837 Iterator dest = begin - numElements;
1838
1839 // In case of aliasing, make a copy of the value.
1843 value);
1845 temp(BSLS_UTIL_ADDRESSOF(space.object()));
1846
1847 // TBD: this does the same thing as the old code - don't like that we
1848 // circumvent the whole allocator thing, but for now, let's keep it
1849 // consistent.
1850 // ConstructorProxy<VALUE_TYPE>
1851 // tempValue(value, bslma::Default::allocator());
1852
1853 // Create a reverse guard that will reverse the moveFront operation in case
1854 // of an exception.
1855 MoveGuard guard(begin, dest, frontSize, true);
1856
1857 moveFront(&dest, &begin, frontSize);
1858
1859 // Create a guard for 'uninitializedFillNBack' because it can throw under
1860 // 'bitwisemoveable' trait. Need to use this special guard because
1861 // uninitializedFillNBack is not exception safe.
1862 Iterator dest2(dest);
1863 ExtGuard eguard(&dest2, &dest, allocator);
1864
1865 uninitializedFillNBack(&dest, dest, numElements, space.object(),
1866 allocator);
1867
1868 eguard.release();
1869 guard.release();
1870 *toBegin = fromBegin - numElements;
1871}
1872
1873template <class VALUE_TYPE, int BLOCK_LENGTH>
1874template <class ALLOCATOR>
1876 Iterator *toBegin,
1877 Iterator fromBegin,
1878 Iterator position,
1879 size_type numElements,
1880 const VALUE_TYPE& value,
1881 ALLOCATOR allocator,
1883{
1884 typedef DequePrimitives_DequeElementGuard<VALUE_TYPE,
1885 BLOCK_LENGTH,
1886 ALLOCATOR> ElementGuard;
1887
1888 size_type frontSize = position - fromBegin;
1889 Iterator begin = fromBegin;
1890 Iterator dest = begin - numElements;
1891 size_type numDest;
1892
1893 // In case of aliasing, make a copy of the value.
1897 value);
1899 temp(BSLS_UTIL_ADDRESSOF(space.object()));
1900
1901 // TBD: this does the same thing as the old code - don't like that we
1902 // circumvent the whole allocator thing, but for now, let's keep it
1903 // consistent.
1904 // ConstructorProxy<VALUE_TYPE>
1905 // tempValue(value, bslma::Default::allocator());
1906
1907 ElementGuard guard(dest, dest, allocator);
1908 if (frontSize >= numElements) {
1909 for (numDest = numElements; 0 < numDest; --numDest, ++dest, ++begin) {
1911 dest.valuePtr(),
1912 *begin);
1913 guard.moveEnd(1);
1914 }
1915 for (frontSize -= numElements; 0 < frontSize;
1916 --frontSize, ++dest, ++begin) {
1917 *dest = *begin;
1918 }
1919 for (numDest = numElements; 0 < numDest; --numDest, ++dest) {
1920 *dest = space.object();
1921 }
1922 } else {
1923 for (numDest = frontSize; 0 < numDest; --numDest, ++dest, ++begin) {
1925 dest.valuePtr(),
1926 *begin);
1927 guard.moveEnd(1);
1928 }
1929 for (numDest = numElements; frontSize < numDest; --numDest, ++dest) {
1931 dest.valuePtr(),
1932 space.object());
1933 guard.moveEnd(1);
1934 }
1935 for (; 0 < numDest; --numDest, ++dest) {
1936 *dest = space.object();
1937 }
1938 }
1939 guard.release();
1940 *toBegin = fromBegin - numElements;
1941}
1942
1943template <class VALUE_TYPE, int BLOCK_LENGTH>
1944template <class FWD_ITER, class SENTINEL, class ALLOCATOR>
1945void
1948 Iterator fromBegin,
1949 Iterator position,
1950 FWD_ITER first,
1951 SENTINEL /*last*/,
1952 size_type numElements,
1953 ALLOCATOR allocator)
1954{
1955 typedef DequePrimitives_DequeElementGuard<VALUE_TYPE,
1956 BLOCK_LENGTH,
1957 ALLOCATOR> ElementGuard;
1958
1959 size_type frontSize = position - fromBegin;
1960 Iterator begin = fromBegin;
1961 Iterator dest = begin - numElements;
1962 size_type numDest;
1963
1964 ElementGuard guard(dest, dest, allocator);
1965 if (frontSize >= numElements) {
1966 for (numDest = numElements; 0 < numDest; --numDest, ++dest, ++begin) {
1968 dest.valuePtr(),
1969 *begin);
1970 guard.moveEnd(1);
1971 }
1972 for (frontSize -= numElements; 0 < frontSize;
1973 --frontSize, ++dest, ++begin) {
1974 *dest = *begin;
1975 }
1976 for (numDest = numElements; 0 < numDest; --numDest, ++dest, ++first) {
1977 *dest = *first;
1978 }
1979 } else {
1980 for (numDest = frontSize; 0 < numDest; --numDest, ++dest, ++begin) {
1982 dest.valuePtr(),
1983 *begin);
1984 guard.moveEnd(1);
1985 }
1986 for (numDest = numElements; frontSize < numDest;
1987 --numDest, ++dest, ++first) {
1989 dest.valuePtr(),
1990 *first);
1991 guard.moveEnd(1);
1992 }
1993 for (; 0 < numDest; --numDest, ++dest, ++first) {
1994 *dest = *first;
1995 }
1996 }
1997 guard.release();
1998 *toBegin = fromBegin - numElements;
1999}
2000
2001template <class VALUE_TYPE, int BLOCK_LENGTH>
2002template <class ALLOCATOR>
2003inline
2004void
2006 Iterator *toBegin,
2007 Iterator fromBegin,
2008 Iterator position,
2010 ALLOCATOR allocator)
2011{
2012 enum {
2015
2016 VALUE = IS_BITWISECOPYABLE
2018 : IS_BITWISEMOVEABLE
2021 };
2022
2023 VALUE_TYPE& lvalue = value;
2024
2025 moveInsertAndMoveToFront(toBegin,
2026 fromBegin,
2027 position,
2028 MoveUtil::move(lvalue),
2029 allocator,
2031}
2032
2033template <class VALUE_TYPE, int BLOCK_LENGTH>
2034template <class ALLOCATOR>
2036 Iterator *toBegin,
2037 Iterator fromBegin,
2038 Iterator position,
2040 ALLOCATOR allocator,
2043{
2044 const size_type frontSize = position - fromBegin;
2045 Iterator begin = fromBegin;
2046 Iterator dest = begin - 1;
2047
2048 // No guard needed since no operations will throw with
2049 // 'BITWISE_COPYABLE_TRAITS'.
2050
2051 moveFront(&dest, &begin, frontSize);
2052
2053 VALUE_TYPE& lvalue = value;
2055 dest.valuePtr(),
2056 MoveUtil::move(lvalue));
2057
2058 *toBegin = fromBegin - 1;
2059}
2060
2061template <class VALUE_TYPE, int BLOCK_LENGTH>
2062template <class ALLOCATOR>
2064 Iterator *toBegin,
2065 Iterator fromBegin,
2066 Iterator position,
2068 ALLOCATOR allocator,
2071{
2072 const size_type frontSize = position - fromBegin;
2073 Iterator begin = fromBegin;
2074 Iterator dest = begin - 1;
2075
2076 // Create a reverse guard that will undo the 'moveFront' operation in case
2077 // of an exception.
2078
2079 MoveGuard guard(begin, dest, frontSize, true);
2080
2081 moveFront(&dest, &begin, frontSize);
2082
2083 VALUE_TYPE& lvalue = value;
2085 dest.valuePtr(),
2086 MoveUtil::move(lvalue));
2087
2088 guard.release();
2089
2090 *toBegin = fromBegin - 1;
2091}
2092
2093template <class VALUE_TYPE, int BLOCK_LENGTH>
2094template <class ALLOCATOR>
2096 Iterator *toBegin,
2097 Iterator fromBegin,
2098 Iterator position,
2100 ALLOCATOR allocator,
2102{
2103 typedef DequePrimitives_DequeElementGuard<VALUE_TYPE,
2104 BLOCK_LENGTH,
2105 ALLOCATOR> ElementGuard;
2106
2107 size_type frontSize = position - fromBegin;
2108 Iterator begin = fromBegin;
2109 Iterator dest = begin - 1;
2110
2111 BSLS_ASSERT_SAFE(frontSize >= 1);
2112
2113 ElementGuard guard(dest, dest, allocator);
2114
2115 // 1. move-construct front-most element being bumped 1 slot
2116
2118 allocator,
2119 dest.valuePtr(),
2120 MoveUtil::move_if_noexcept(*begin));
2121 guard.moveEnd(1);
2122 ++dest;
2123 ++begin;
2124
2125 // 2. move-assign other existing elements being bumped forward 1 slot
2126
2127 for (frontSize -= 1; 0 < frontSize; --frontSize, ++dest, ++begin) {
2128 *dest = MoveUtil::move_if_noexcept(*begin);
2129 }
2130
2131 // 3. move-assign the new element
2132
2133 VALUE_TYPE& lvalue = value;
2134 *dest = MoveUtil::move(lvalue);
2135
2136 guard.release();
2137
2138 *toBegin = fromBegin - 1;
2139}
2140
2141#if !BSLS_COMPILERFEATURES_SIMULATE_CPP11_FEATURES
2142template <class VALUE_TYPE, int BLOCK_LENGTH>
2143template <class ALLOCATOR, class... Args>
2144inline
2145void
2147 Iterator *toEnd,
2148 Iterator fromEnd,
2149 Iterator position,
2150 ALLOCATOR allocator,
2151 Args&&... arguments)
2152{
2153 enum {
2156
2157 VALUE = IS_BITWISECOPYABLE
2159 : IS_BITWISEMOVEABLE
2162 };
2163
2164 emplaceAndMoveToBackDispatch(
2165 toEnd,
2166 fromEnd,
2167 position,
2168 allocator,
2170 BSLS_COMPILERFEATURES_FORWARD(Args, arguments)...);
2171}
2172
2173template <class VALUE_TYPE, int BLOCK_LENGTH>
2174template <class ALLOCATOR, class... Args>
2176 Iterator *toEnd,
2177 Iterator fromEnd,
2178 Iterator position,
2179 ALLOCATOR allocator,
2182 Args&&... arguments)
2183{
2184 const size_type backSize = fromEnd - position;
2185 Iterator end = fromEnd;
2186 Iterator dest = end + 1;
2187
2188 // No guard needed since no operations will throw with
2189 // 'BITWISE_COPYABLE_TRAITS'.
2190
2191 moveBack(&dest, &end, backSize);
2192 --dest;
2193
2195 allocator,
2196 dest.valuePtr(),
2197 BSLS_COMPILERFEATURES_FORWARD(Args, arguments)...);
2198
2199 *toEnd = fromEnd + 1;
2200}
2201
2202template <class VALUE_TYPE, int BLOCK_LENGTH>
2203template <class ALLOCATOR, class... Args>
2205 Iterator *toEnd,
2206 Iterator fromEnd,
2207 Iterator position,
2208 ALLOCATOR allocator,
2211 Args&&... arguments)
2212{
2213 const size_type backSize = fromEnd - position;
2214 Iterator end = fromEnd;
2215 Iterator dest = end + 1;
2216
2217 // Create a reverse guard that will undo the 'moveBack' operation in case
2218 // of an exception.
2219
2220 MoveGuard guard(end, dest, backSize, false);
2221
2222 moveBack(&dest, &end, backSize);
2223 --dest;
2224
2226 allocator,
2227 dest.valuePtr(),
2228 BSLS_COMPILERFEATURES_FORWARD(Args, arguments)...);
2229
2230 guard.release();
2231
2232 *toEnd = fromEnd + 1;
2233}
2234
2235template <class VALUE_TYPE, int BLOCK_LENGTH>
2236template <class ALLOCATOR, class... Args>
2238 Iterator *toEnd,
2239 Iterator fromEnd,
2240 Iterator position,
2241 ALLOCATOR allocator,
2243 Args&&... arguments)
2244{
2245 typedef DequePrimitives_DequeElementGuard<VALUE_TYPE,
2246 BLOCK_LENGTH,
2247 ALLOCATOR> ElementGuard;
2248
2249 typedef DequePrimitives_DequeEndpointProctor<VALUE_TYPE,
2250 BLOCK_LENGTH> EndpointProctor;
2251
2252 size_type backSize = fromEnd - position;
2253 Iterator end = fromEnd;
2254 Iterator dest = end + 1;
2255
2256 BSLS_ASSERT_SAFE(backSize >= 1);
2257
2258 ElementGuard guard(dest, dest, allocator);
2259
2260 // 1. move-construct back-most element being bumped 1 slot
2261
2262 --dest;
2263 --end;
2265 allocator,
2266 dest.valuePtr(),
2267 MoveUtil::move_if_noexcept(*end));
2268 guard.moveBegin(-1);
2269
2270 // 2. move-assign other existing elements being bumped back 1 slot
2271
2272 size_type n = 0; // additional elements to guard following 'for' loop
2273 for (backSize -= 1; 0 < backSize; --backSize) {
2274 --dest;
2275 --end;
2276 *dest = MoveUtil::move_if_noexcept(*end);
2277 ++n;
2278 }
2279 guard.moveBegin(-n); // in case the emplacement (below) throws
2280
2281 // 3. destroy element in emplacement slot
2282
2284
2285 // 4. emplace the new element
2286
2287 // If emplacement throws, lop off the '[position .. *toEnd)' portion of the
2288 // deque because a hole was just created that cannot be repopulated.
2289
2290 EndpointProctor endpointProctor(toEnd, position);
2291
2293 allocator,
2294 position.valuePtr(),
2295 BSLS_COMPILERFEATURES_FORWARD(Args, arguments)...);
2296
2297 endpointProctor.release();
2298 guard.release();
2299
2300 *toEnd = fromEnd + 1;
2301}
2302
2303template <class VALUE_TYPE, int BLOCK_LENGTH>
2304template <class ALLOCATOR, class... Args>
2305inline
2306void
2308 Iterator *toBegin,
2309 Iterator fromBegin,
2310 Iterator position,
2311 ALLOCATOR allocator,
2312 Args&&... arguments)
2313{
2314 enum {
2317
2318 VALUE = IS_BITWISECOPYABLE
2320 : IS_BITWISEMOVEABLE
2323 };
2324
2325 emplaceAndMoveToFrontDispatch(
2326 toBegin,
2327 fromBegin,
2328 position,
2329 allocator,
2331 BSLS_COMPILERFEATURES_FORWARD(Args, arguments)...);
2332}
2333
2334template <class VALUE_TYPE, int BLOCK_LENGTH>
2335template <class ALLOCATOR, class... Args>
2337 Iterator *toBegin,
2338 Iterator fromBegin,
2339 Iterator position,
2340 ALLOCATOR allocator,
2343 Args&&... arguments)
2344{
2345 const size_type frontSize = position - fromBegin;
2346 Iterator begin = fromBegin;
2347 Iterator dest = begin - 1;
2348
2349 // No guard needed since no operations will throw with
2350 // 'BITWISE_COPYABLE_TRAITS'.
2351
2352 moveFront(&dest, &begin, frontSize);
2353
2355 allocator,
2356 dest.valuePtr(),
2357 BSLS_COMPILERFEATURES_FORWARD(Args, arguments)...);
2358
2359 *toBegin = fromBegin - 1;
2360}
2361
2362template <class VALUE_TYPE, int BLOCK_LENGTH>
2363template <class ALLOCATOR, class... Args>
2365 Iterator *toBegin,
2366 Iterator fromBegin,
2367 Iterator position,
2368 ALLOCATOR allocator,
2371 Args&&... arguments)
2372{
2373 const size_type frontSize = position - fromBegin;
2374 Iterator begin = fromBegin;
2375 Iterator dest = begin - 1;
2376
2377 // Create a reverse guard that will undo the 'moveFront' operation in case
2378 // of an exception.
2379
2380 MoveGuard guard(begin, dest, frontSize, true);
2381
2382 moveFront(&dest, &begin, frontSize);
2383
2385 allocator,
2386 dest.valuePtr(),
2387 BSLS_COMPILERFEATURES_FORWARD(Args, arguments)...);
2388
2389 guard.release();
2390
2391 *toBegin = fromBegin - 1;
2392}
2393
2394template <class VALUE_TYPE, int BLOCK_LENGTH>
2395template <class ALLOCATOR, class... Args>
2397 Iterator *toBegin,
2398 Iterator fromBegin,
2399 Iterator position,
2400 ALLOCATOR allocator,
2402 Args&&... arguments)
2403{
2404 typedef DequePrimitives_DequeElementGuard<VALUE_TYPE,
2405 BLOCK_LENGTH,
2406 ALLOCATOR> ElementGuard;
2407
2408 typedef DequePrimitives_DequeEndpointProctor<VALUE_TYPE,
2409 BLOCK_LENGTH> EndpointProctor;
2410
2411 size_type frontSize = position - fromBegin;
2412 Iterator begin = fromBegin;
2413 Iterator dest = begin - 1;
2414
2415 BSLS_ASSERT_SAFE(frontSize >= 1);
2416
2417 ElementGuard guard(dest, dest, allocator);
2418
2419 // 1. move-construct front-most element being bumped 1 slot
2420
2422 allocator,
2423 dest.valuePtr(),
2424 MoveUtil::move_if_noexcept(*begin));
2425 guard.moveEnd(1);
2426 ++dest;
2427 ++begin;
2428
2429 // 2. move-assign other existing elements being bumped forward 1 slot
2430
2431 size_type n = 0; // additional elements to guard following 'for' loop
2432 for (frontSize -= 1; 0 < frontSize; --frontSize, ++dest, ++begin) {
2433 *dest = MoveUtil::move_if_noexcept(*begin);
2434 ++n;
2435 }
2436 guard.moveEnd(n); // in case the emplacement (below) throws
2437
2438 // 3. destroy element in emplacement slot
2439
2441
2442 // 4. emplace the new element
2443
2444 // If emplacement throws, lop off the '[*toBegin .. position)' portion the
2445 // the deque because a hole was just created that cannot be repopulated.
2446
2447 EndpointProctor endpointProctor(toBegin, position);
2448
2450 allocator,
2451 dest.valuePtr(),
2452 BSLS_COMPILERFEATURES_FORWARD(Args, arguments)...);
2453
2454 endpointProctor.release();
2455 guard.release();
2456
2457 *toBegin = fromBegin - 1;
2458}
2459#endif
2460
2461template <class VALUE_TYPE, int BLOCK_LENGTH>
2464 Iterator *source,
2465 size_type numElements)
2466{
2467 if (destination->offsetInBlock() > numElements
2468 && source->offsetInBlock() > numElements) {
2469 // There is enough room to move everything at once.
2470
2471 *destination -= numElements;
2472 *source -= numElements;
2473 std::memmove((void *)destination->valuePtr(),
2474 source->valuePtr(),
2475 numElements * sizeof(VALUE_TYPE));
2476
2477 return; // RETURN
2478 }
2479
2480 // Moving the blocks involving segments of 3 different lengths, as
2481 // illustrated below. We need to distinguish whether destination or the
2482 // source have more space remaining, and adjust the algorithm accordingly.
2483 //..
2484 // [--- n ---] - segment 'n'
2485 // [--- n'---] - segment with equal length as 'n'.
2486 // [--- n ---I-- m --] - two segments, with length 'n' and 'm'.
2487 // - - - - - - - -
2488 // | | | | | | | | | - a block in the deque pointed by a 'blockPtr'
2489 // - - - - - - - -
2490 //..
2491 //
2492 // Scenario 1: Source has less element than destination has space
2493 // ==============================================================
2494 // Under this scenario, we have to move all elements from the source block
2495 // to the destination block first (segment 1), then fill the destination
2496 // block with the remaining elements (segment 2). After, we alternate
2497 // between segments 3 and 2.
2498 //..
2499 // [--- 3 ---I- 2'-] [- 1 -] [- 2 -I- 1'-]
2500 // - - - - - - - - - - - - - - - - - - - - - - - -
2501 // |d|e|f|g|h|i|j|k| |a|b|c|/| | | | | | | | | | | | | |
2502 // - - - - - - - - - - - - - - - - - - - - - - - -
2503 // ^ ^
2504 // source ____| destination _____|
2505 //..
2506 //
2507 // Scenario 2: Source has more elements than destination has space
2508 // ================================================================
2509 // Under this scenario, we can only move some elements (the number of
2510 // elements that can fit in the destination block) from the source block to
2511 // the destination block first (segment 1), then move the remaining
2512 // elements (segment 2) from the source block. After, we alternate between
2513 // segments 3 and 2.
2514 //..
2515 // [---- 3 ----]
2516 // [---- 3' ---] [-2-I- 1 -] [2' ] [- 1 -]
2517 // - - - - - - - - - - - - - - - - - - - - - - - -
2518 // |d|e|f|g|h|i|j|k| |a|b|c|d|e|/| | | | | | | | | | | |
2519 // - - - - - - - - - - - - - - - - - - - - - - - -
2520 // ^ ^
2521 // source _____| destination _|
2522 //
2523 // 1) Copy segment 1
2524 // 2) Copy segment 2
2525 // 3) Copy segment 3
2526 // 4) Repeat 2, 3 until there's less than 1 'BLOCK_LENGTH' left
2527 // 5) Copy the remaining items over
2528 //..
2529
2530 size_type firstSegment, secondSegment;
2531 if (source->offsetInBlock() > destination->offsetInBlock()) {
2532 firstSegment = destination->offsetInBlock();
2533 secondSegment = source->offsetInBlock() - firstSegment;
2534 }
2535 else {
2536 firstSegment = source->offsetInBlock();
2537 secondSegment = destination->offsetInBlock() - firstSegment;
2538 }
2539
2540 size_type thirdSegment = BLOCK_LENGTH - secondSegment;
2541
2542 *destination -= firstSegment;
2543 *source -= firstSegment;
2544 numElements -= firstSegment;
2545
2546 std::memmove((void *)destination->valuePtr(),
2547 source->valuePtr(),
2548 firstSegment * sizeof(VALUE_TYPE));
2549
2550 for (; numElements >= BLOCK_LENGTH; numElements -= BLOCK_LENGTH) {
2551
2552 *destination -= secondSegment;
2553 *source -= secondSegment;
2554
2555 std::memmove((void *)destination->valuePtr(),
2556 source->valuePtr(),
2557 secondSegment * sizeof(VALUE_TYPE));
2558
2559 *destination -= thirdSegment;
2560 *source -= thirdSegment;
2561
2562 std::memmove((void *)destination->valuePtr(),
2563 source->valuePtr(),
2564 thirdSegment * sizeof(VALUE_TYPE));
2565 }
2566
2567 size_type remaining = numElements > secondSegment
2568 ? secondSegment
2569 : numElements;
2570
2571 *destination -= remaining;
2572 *source -= remaining;
2573 numElements -= remaining;
2574
2575 std::memmove((void *)destination->valuePtr(),
2576 source->valuePtr(),
2577 remaining * sizeof(VALUE_TYPE));
2578
2579 *destination -= numElements;
2580 *source -= numElements;
2581
2582 std::memmove((void *)destination->valuePtr(),
2583 source->valuePtr(),
2584 numElements * sizeof(VALUE_TYPE));
2585}
2586
2587template <class VALUE_TYPE, int BLOCK_LENGTH>
2590 Iterator *source,
2591 size_type numElements)
2592{
2593 if (destination->remainingInBlock() > numElements
2594 && source->remainingInBlock() > numElements) {
2595 // There is enough room to move everything at once
2596
2597 std::memmove((void *)destination->valuePtr(),
2598 source->valuePtr(),
2599 numElements * sizeof(VALUE_TYPE));
2600 *destination += numElements;
2601 *source += numElements;
2602
2603 return; // RETURN
2604 }
2605
2606 // Moving the blocks involving segments of 3 different lengths, as
2607 // illustrated below. We need to distinguish whether destination or the
2608 // source have more space remaining, and adjust the algorithm accordingly.
2609 //..
2610 // [--- n ---] - segment 'n'
2611 // [--- n'---] - segment with equal length as 'n'
2612 // [--- n ---I-- m --] - two segments, with length 'n' and 'm'.
2613 // - - - - - - - -
2614 // | | | | | | | | | - a block in the deque pointed by a 'blockPtr'
2615 // - - - - - - - -
2616 //..
2617 //
2618 // Scenario 1: Source has more elements than destination has space
2619 // ===============================================================
2620 // Under this scenario, we can only move some elements (the number of
2621 // elements that can fit in the destination block) from the source block to
2622 // the destination block first (segment 1), then move the remaining
2623 // elements (segment 2) from the source block. After, we alternate between
2624 // segments 3 and 2.
2625 //..
2626 // [---- 3 ----]
2627 // [- 1 -] [ 2'] [- 1'-I-2-] [---- 3'----]
2628 // - - - - - - - - - - - - - - - - - - - - - - - -
2629 // | | | | | | | | | | | | |a|a|b|c|d| |e|f|g|h|i|j|k|l|
2630 // - - - - - - - - - - - - - - - - - - - - - - - -
2631 // ^ ^
2632 // |_ destination |____ source
2633 //..
2634 //
2635 // Scenario 2: Source has less elements than destination has space
2636 // ===============================================================
2637 // Under this scenario, we have to move all elements from the source block
2638 // to the destination block first (segment 1), then fill the destination
2639 // block with the remaining elements (segment 2). After, we alternate
2640 // between segments 3 and 2.
2641 //..
2642 // [- 1'-I- 2 -] [--- 3'---I- 1 -] [- 2'-I--- 3 ---]
2643 // - - - - - - - - - - - - - - - - - - - - - - - -
2644 // | | | | | | | | | | | | | | |a|b|c| |d|e|f|g|h|i|j|k|
2645 // - - - - - - - - - - - - - - - - - - - - - - - -
2646 // ^ ^
2647 // |_ destination |____ source
2648 //
2649 // 1) Copy segment 1
2650 // 2) Copy segment 2
2651 // 3) Copy segment 3
2652 // 4) Repeat 2, 3 until there's less than 1 'BLOCK_LENGTH' left
2653 // 5) Copy the remaining items over
2654 //..
2655
2656 size_type firstSegment, secondSegment;
2657 if (source->remainingInBlock() > destination->remainingInBlock()) {
2658 firstSegment = destination->remainingInBlock();
2659 secondSegment = source->remainingInBlock() - firstSegment;
2660 }
2661 else {
2662 firstSegment = source->remainingInBlock();
2663 secondSegment = destination->remainingInBlock() - firstSegment;
2664 }
2665
2666 size_type thirdSegment = BLOCK_LENGTH - secondSegment;
2667
2668 std::memmove((void *)destination->valuePtr(),
2669 source->valuePtr(),
2670 firstSegment * sizeof(VALUE_TYPE));
2671
2672 *destination += firstSegment;
2673 *source += firstSegment;
2674 numElements -= firstSegment;
2675
2676 for (; numElements >= BLOCK_LENGTH; numElements -= BLOCK_LENGTH) {
2677
2678 std::memmove((void *)destination->valuePtr(),
2679 source->valuePtr(),
2680 secondSegment * sizeof(VALUE_TYPE));
2681
2682 *destination += secondSegment;
2683 *source += secondSegment;
2684
2685 std::memmove((void *)destination->valuePtr(),
2686 source->valuePtr(),
2687 thirdSegment * sizeof(VALUE_TYPE));
2688
2689 *destination += thirdSegment;
2690 *source += thirdSegment;
2691 }
2692
2693 size_type remaining = numElements > secondSegment
2694 ? secondSegment
2695 : numElements;
2696
2697 std::memmove((void *)destination->valuePtr(),
2698 source->valuePtr(),
2699 remaining * sizeof(VALUE_TYPE));
2700
2701 *destination += remaining;
2702 *source += remaining;
2703 numElements -= remaining;
2704
2705 std::memmove((void *)destination->valuePtr(),
2706 source->valuePtr(),
2707 numElements * sizeof(VALUE_TYPE));
2708
2709 *destination += numElements;
2710 *source += numElements;
2711}
2712
2713template <class VALUE_TYPE, int BLOCK_LENGTH>
2714template <class ALLOCATOR>
2715void
2718 Iterator fromEnd,
2719 size_type numElements,
2720 const VALUE_TYPE& value,
2721 ALLOCATOR allocator)
2722{
2723 if (fromEnd.remainingInBlock() > numElements) {
2725 numElements,
2726 value,
2727 allocator);
2728 fromEnd += numElements;
2729 *toEnd = fromEnd;
2730 return; // RETURN
2731 }
2732
2733 size_type firstRemaining = fromEnd.remainingInBlock();
2734
2736 firstRemaining,
2737 value,
2738 allocator);
2739
2740 numElements -= firstRemaining;
2741 fromEnd += firstRemaining;
2742 *toEnd = fromEnd;
2743
2744 for ( ; numElements >= BLOCK_LENGTH; numElements -= BLOCK_LENGTH) {
2746 BLOCK_LENGTH,
2747 value,
2748 allocator);
2749 fromEnd.nextBlock();
2750 toEnd->nextBlock();
2751 }
2752
2754 numElements,
2755 value,
2756 allocator);
2757
2758 fromEnd += numElements;
2759 *toEnd = fromEnd;
2760}
2761
2762template <class VALUE_TYPE, int BLOCK_LENGTH>
2763template <class ALLOCATOR>
2764void
2767 Iterator fromEnd,
2768 size_type numElements,
2769 ALLOCATOR allocator)
2770{
2771 if (fromEnd.remainingInBlock() > numElements) {
2773 numElements,
2774 allocator);
2775 fromEnd += numElements;
2776 *toEnd = fromEnd;
2777 return; // RETURN
2778 }
2779
2780 size_type firstRemaining = fromEnd.remainingInBlock();
2781
2783 firstRemaining,
2784 allocator);
2785
2786 numElements -= firstRemaining;
2787 fromEnd += firstRemaining;
2788 *toEnd = fromEnd;
2789
2790 for ( ; numElements >= BLOCK_LENGTH; numElements -= BLOCK_LENGTH) {
2792 BLOCK_LENGTH,
2793 allocator);
2794 fromEnd.nextBlock();
2795 toEnd->nextBlock();
2796 }
2797
2799 numElements,
2800 allocator);
2801
2802 fromEnd += numElements;
2803 *toEnd = fromEnd;
2804}
2805
2806template <class VALUE_TYPE, int BLOCK_LENGTH>
2807template <class ALLOCATOR>
2808void
2811 Iterator fromBegin,
2812 size_type numElements,
2813 const VALUE_TYPE& value,
2814 ALLOCATOR allocator)
2815{
2816 if (fromBegin.offsetInBlock() > numElements) {
2817 fromBegin -= numElements;
2818
2820 numElements,
2821 value,
2822 allocator);
2823 *toBegin = fromBegin;
2824 return; // RETURN
2825 }
2826
2827 size_type firstRemaining = fromBegin.offsetInBlock();
2828
2829 fromBegin -= firstRemaining;
2830 numElements -= firstRemaining;
2831
2833 firstRemaining,
2834 value,
2835 allocator);
2836
2837 *toBegin = fromBegin; // in case of exception
2838
2839 for ( ; numElements >= BLOCK_LENGTH; numElements -= BLOCK_LENGTH) {
2840 fromBegin.previousBlock();
2842 BLOCK_LENGTH,
2843 value,
2844 allocator);
2845 *toBegin = fromBegin;
2846 }
2847
2848 fromBegin -= numElements;
2850 numElements,
2851 value,
2852 allocator);
2853
2854 *toBegin = fromBegin;
2855}
2856
2857 // ------------------------------------
2858 // class DequePrimitives<VALUE_TYPE, 1>
2859 // ------------------------------------
2860
2861// CLASS METHODS
2862template <class VALUE_TYPE>
2863template <class ALLOCATOR>
2866 Iterator *toEnd,
2867 Iterator fromBegin,
2868 Iterator first,
2869 Iterator last,
2870 Iterator fromEnd,
2871 ALLOCATOR allocator)
2872{
2873 size_type frontSize = first - fromBegin;
2874 size_type backSize = fromEnd - last;
2875 Iterator ret;
2876
2877 if (frontSize < backSize) {
2878 ret = last;
2879 for (; 0 < frontSize; --frontSize) {
2880 --last;
2881 --first;
2882 *last = *first;
2883 }
2884 *toBegin = last;
2885 *toEnd = fromEnd;
2886 }
2887 else {
2888 ret = first;
2889 for (; 0 < backSize; --backSize, ++first, ++last) {
2890 *first = *last;
2891 }
2892 *toBegin = fromBegin;
2893 *toEnd = first;
2894 }
2895 destruct(first, last, allocator);
2896 return ret;
2897}
2898
2899template <class VALUE_TYPE>
2900template <class ALLOCATOR>
2902 Iterator end,
2903 ALLOCATOR allocator)
2904{
2905 for (; !(begin == end); ++begin) {
2907 begin.valuePtr());
2908 }
2909}
2910
2911template <class VALUE_TYPE>
2912template <class ALLOCATOR>
2913void
2916 Iterator fromBegin,
2917 Iterator position,
2918 size_type numElements,
2919 const VALUE_TYPE& value,
2920 ALLOCATOR allocator)
2921{
2922 typedef DequePrimitives_DequeElementGuard<VALUE_TYPE,
2923 1,
2924 ALLOCATOR> ElementGuard;
2925
2926 size_type frontSize = position - fromBegin;
2927 Iterator begin = fromBegin;
2928 Iterator dest = begin - numElements;
2929 size_type numDest;
2930
2934 value);
2936 temp(BSLS_UTIL_ADDRESSOF(space.object()));
2937
2938 // TBD: this does the same thing as the old code - don't like that we
2939 // circumvent the whole allocator thing, but for now, let's keep it
2940 // consistent.
2941 // ConstructorProxy<VALUE_TYPE>
2942 // tempValue(value, bslma::Default::allocator());
2943
2944 ElementGuard guard(dest, dest, allocator);
2945 if (frontSize >= numElements) {
2946 for (numDest = numElements; 0 < numDest; --numDest, ++dest, ++begin) {
2948 dest.valuePtr(),
2949 *begin);
2950 guard.moveEnd(1);
2951 }
2952 for (frontSize -= numElements; 0 < frontSize;
2953 --frontSize, ++dest, ++begin) {
2954 *dest = *begin;
2955 }
2956 for (numDest = numElements; 0 < numDest; --numDest, ++dest) {
2957 *dest = space.object();
2958 }
2959 } else {
2960 for (numDest = frontSize; 0 < numDest; --numDest, ++dest, ++begin) {
2962 dest.valuePtr(),
2963 *begin);
2964 guard.moveEnd(1);
2965 }
2966 for (numDest = numElements; frontSize < numDest; --numDest, ++dest) {
2968 dest.valuePtr(),
2969 space.object());
2970 guard.moveEnd(1);
2971 }
2972 for (; 0 < numDest; --numDest, ++dest) {
2973 *dest = space.object();
2974 }
2975 }
2976 guard.release();
2977 *toBegin = fromBegin - numElements;
2978}
2979
2980template <class VALUE_TYPE>
2981template <class FWD_ITER, class SENTINEL, class ALLOCATOR>
2982void
2985 Iterator fromBegin,
2986 Iterator position,
2987 FWD_ITER first,
2988 SENTINEL /*last*/,
2989 size_type numElements,
2990 ALLOCATOR allocator)
2991{
2992 typedef DequePrimitives_DequeElementGuard<VALUE_TYPE,
2993 1,
2994 ALLOCATOR> ElementGuard;
2995
2996 size_type frontSize = position - fromBegin;
2997 Iterator begin = fromBegin;
2998 Iterator dest = begin - numElements;
2999 size_type numDest;
3000
3001 ElementGuard guard(dest, dest, allocator);
3002 if (frontSize >= numElements) {
3003 for (numDest = numElements; 0 < numDest; --numDest, ++dest, ++begin) {
3005 dest.valuePtr(),
3006 *begin);
3007 guard.moveEnd(1);
3008 }
3009 for (frontSize -= numElements; 0 < frontSize;
3010 --frontSize, ++dest, ++begin) {
3011 *dest = *begin;
3012 }
3013 for (numDest = numElements; 0 < numDest; --numDest, ++dest, ++first) {
3014 *dest = *first;
3015 }
3016 } else {
3017 for (numDest = frontSize; 0 < numDest; --numDest, ++dest, ++begin) {
3019 dest.valuePtr(),
3020 *begin);
3021 guard.moveEnd(1);
3022 }
3023 for (numDest = numElements; frontSize < numDest;
3024 --numDest, ++dest, ++first) {
3026 dest.valuePtr(),
3027 *first);
3028 guard.moveEnd(1);
3029 }
3030 for (; 0 < numDest; --numDest, ++dest, ++first) {
3031 *dest = *first;
3032 }
3033 }
3034 guard.release();
3035 *toBegin = fromBegin - numElements;
3036}
3037
3038template <class VALUE_TYPE>
3039template <class ALLOCATOR>
3040void
3042 Iterator *toEnd,
3043 Iterator fromEnd,
3044 Iterator position,
3045 size_type numElements,
3046 const VALUE_TYPE& value,
3047 ALLOCATOR allocator)
3048{
3049 typedef DequePrimitives_DequeElementGuard<VALUE_TYPE,
3050 1,
3051 ALLOCATOR> ElementGuard;
3052
3053 size_type backSize = fromEnd - position;
3054 Iterator end = fromEnd;
3055 Iterator dest = end + numElements;
3056 size_type numDest;
3057
3061 value);
3063 temp(BSLS_UTIL_ADDRESSOF(space.object()));
3064
3065 // TBD: this does the same thing as the old code - don't like that we
3066 // circumvent the whole allocator thing, but for now, let's keep it
3067 // consistent.
3068 // ConstructorProxy<VALUE_TYPE>
3069 // tempValue(value, bslma::Default::allocator());
3070
3071 ElementGuard guard(dest, dest, allocator);
3072 if (backSize >= numElements) {
3073 for (numDest = numElements; 0 < numDest; --numDest) {
3074 --dest;
3075 --end;
3077 dest.valuePtr(),
3078 *end);
3079 guard.moveBegin(-1);
3080 }
3081 for (backSize -= numElements; 0 < backSize; --backSize) {
3082 --dest;
3083 --end;
3084 *dest = *end;
3085 }
3086 for (numDest = numElements; 0 < numDest; --numDest, ++position) {
3087 *position = space.object();
3088 }
3089 } else {
3090 for (numDest = backSize; 0 < numDest; --numDest) {
3091 --dest;
3092 --end;
3094 dest.valuePtr(),
3095 *end);
3096 guard.moveBegin(-1);
3097 }
3098 for (numDest = numElements; backSize < numDest; --numDest) {
3099 --dest;
3101 dest.valuePtr(),
3102 space.object());
3103 guard.moveBegin(-1);
3104 }
3105 for (; 0 < numDest; --numDest, ++position) {
3106 *position = space.object();
3107 }
3108 }
3109 guard.release();
3110 *toEnd = fromEnd + numElements;
3111}
3112
3113template <class VALUE_TYPE>
3114template <class FWD_ITER, class SENTINEL, class ALLOCATOR>
3115void
3117 Iterator fromEnd,
3118 Iterator position,
3119 FWD_ITER first,
3120 SENTINEL /*last*/,
3121 size_type numElements,
3122 ALLOCATOR allocator)
3123{
3124 typedef DequePrimitives_DequeElementGuard<VALUE_TYPE,
3125 1,
3126 ALLOCATOR> ElementGuard;
3127
3128 size_type backSize = fromEnd - position;
3129 Iterator end = fromEnd;
3130 Iterator dest = end + numElements;
3131 size_type numDest;
3132
3133 ElementGuard guard(dest, dest, allocator);
3134 if (backSize >= numElements) {
3135 for (numDest = numElements; 0 < numDest; --numDest) {
3136 --dest;
3137 --end;
3139 dest.valuePtr(),
3140 *end);
3141 guard.moveBegin(-1);
3142 }
3143 for (numDest = backSize; numElements < numDest; --numDest) {
3144 --dest;
3145 --end;
3146 *dest = *end;
3147 }
3148 for (; 0 < numDest; ++first, ++position, --numDest) {
3149 *position = *first;
3150 }
3151 } else {
3152 for (numDest = backSize; 0 < numDest; --numDest) {
3153 --dest;
3154 --end;
3156 dest.valuePtr(),
3157 *end);
3158 guard.moveBegin(-1);
3159 }
3160 for (numDest = backSize; 0 < numDest; --numDest, ++position, ++first) {
3161 *position = *first;
3162 }
3163 ElementGuard guard2(position, position, allocator);
3164 for (numDest = numElements; backSize < numDest; ++first, ++position,
3165 --numDest) {
3167 position.valuePtr(),
3168 *first);
3169 guard2.moveEnd(1);
3170 }
3171 guard2.release();
3172 }
3173 guard.release();
3174 *toEnd = fromEnd + numElements;
3175}
3176
3177template <class VALUE_TYPE>
3178template <class ALLOCATOR>
3179inline
3180void
3182 Iterator *toBegin,
3183 Iterator fromBegin,
3184 size_type numElements,
3185 const VALUE_TYPE& value,
3186 ALLOCATOR allocator)
3187{
3188 enum {
3189 IS_FUNCTION_POINTER = bslmf::IsFunctionPointer<VALUE_TYPE>::value,
3192
3193 IS_FUNDAMENTAL_OR_POINTER = IS_FUNDAMENTAL ||
3194 (IS_POINTER && !IS_FUNCTION_POINTER),
3195
3197
3198 VALUE = IS_FUNDAMENTAL_OR_POINTER || IS_BITWISECOPYABLE
3201 };
3202
3203 uninitializedFillNFront(toBegin,
3204 fromBegin,
3205 numElements,
3206 value,
3207 allocator,
3209}
3210
3211template <class VALUE_TYPE>
3212template <class ALLOCATOR>
3214 Iterator *toBegin,
3215 Iterator fromBegin,
3216 size_type numElements,
3217 const VALUE_TYPE& value,
3218 ALLOCATOR allocator,
3220{
3221 typedef DequePrimitives_DequeElementGuard<VALUE_TYPE,
3222 1,
3223 ALLOCATOR> ElementGuard;
3224
3225 ElementGuard guard(fromBegin, fromBegin, allocator);
3226 for (; 0 < numElements; --numElements) {
3227 --fromBegin;
3229 fromBegin.valuePtr(),
3230 value);
3231 guard.moveBegin(-1);
3232 }
3233 guard.release();
3234 *toBegin = fromBegin;
3235}
3236
3237template <class VALUE_TYPE>
3238template <class ALLOCATOR>
3240 Iterator *toBegin,
3241 Iterator fromBegin,
3242 size_type numElements,
3243 const VALUE_TYPE& value,
3244 ALLOCATOR allocator,
3246{
3247 *toBegin = fromBegin; // necessary in case 'numElements = 0'
3248 for ( ; 0 < numElements; --numElements) {
3249 --fromBegin;
3251 1,
3252 value,
3253 allocator);
3254 *toBegin = fromBegin; // in case of exception
3255 }
3256}
3257
3258template <class VALUE_TYPE>
3259template <class ALLOCATOR>
3260inline
3261void
3263 Iterator *toEnd,
3264 Iterator fromEnd,
3265 size_type numElements,
3266 const VALUE_TYPE& value,
3267 ALLOCATOR allocator)
3268{
3269 enum {
3270 IS_FUNCTION_POINTER = bslmf::IsFunctionPointer<VALUE_TYPE>::value,
3273
3274 IS_FUNDAMENTAL_OR_POINTER = IS_FUNDAMENTAL ||
3275 (IS_POINTER && !IS_FUNCTION_POINTER),
3276
3278
3279 VALUE = IS_FUNDAMENTAL_OR_POINTER || IS_BITWISECOPYABLE
3282 };
3283
3284 uninitializedFillNBack(toEnd,
3285 fromEnd,
3286 numElements,
3287 value,
3288 allocator,
3290}
3291
3292template <class VALUE_TYPE>
3293template <class ALLOCATOR>
3295 Iterator *toEnd,
3296 Iterator fromEnd,
3297 size_type numElements,
3298 const VALUE_TYPE& value,
3299 ALLOCATOR allocator,
3301{
3302 typedef DequePrimitives_DequeElementGuard<VALUE_TYPE,
3303 1,
3304 ALLOCATOR> ElementGuard;
3305
3306 ElementGuard guard(fromEnd, fromEnd, allocator);
3307 for (; 0 < numElements; --numElements) {
3309 fromEnd.valuePtr(),
3310 value);
3311 ++fromEnd;
3312 guard.moveEnd(1);
3313 }
3314 guard.release();
3315 *toEnd = fromEnd;
3316}
3317
3318template <class VALUE_TYPE>
3319template <class ALLOCATOR>
3321 Iterator *toEnd,
3322 Iterator fromEnd,
3323 size_type numElements,
3324 const VALUE_TYPE& value,
3325 ALLOCATOR allocator,
3327{
3328 *toEnd = fromEnd; // necessary in case 'numElements = 0'
3329 for ( ; 0 < numElements; --numElements) {
3331 1,
3332 value,
3333 allocator);
3334 ++fromEnd;
3335 *toEnd = fromEnd;
3336 }
3337}
3338
3339template <class VALUE_TYPE>
3340template <class ALLOCATOR>
3341inline
3342void
3344 Iterator fromEnd,
3345 size_type numElements,
3346 ALLOCATOR allocator)
3347{
3348 enum {
3349 IS_FUNCTION_POINTER = bslmf::IsFunctionPointer<VALUE_TYPE>::value,
3352
3353 IS_FUNDAMENTAL_OR_POINTER = IS_FUNDAMENTAL ||
3354 (IS_POINTER && !IS_FUNCTION_POINTER),
3355
3357
3358 VALUE = IS_FUNDAMENTAL_OR_POINTER || IS_BITWISECOPYABLE
3361 };
3362
3363 valueInititalizeN(toEnd,
3364 fromEnd,
3365 numElements,
3366 allocator,
3368}
3369
3370template <class VALUE_TYPE>
3371template <class ALLOCATOR>
3373 Iterator *toEnd,
3374 Iterator fromEnd,
3375 size_type numElements,
3376 ALLOCATOR allocator,
3378{
3379 typedef DequePrimitives_DequeElementGuard<VALUE_TYPE,
3380 1,
3381 ALLOCATOR> ElementGuard;
3382
3383 ElementGuard guard(fromEnd, fromEnd, allocator);
3384 for (; 0 < numElements; --numElements) {
3386 fromEnd.valuePtr());
3387 ++fromEnd;
3388 guard.moveEnd(1);
3389 }
3390 guard.release();
3391 *toEnd = fromEnd;
3392}
3393
3394template <class VALUE_TYPE>
3395template <class ALLOCATOR>
3397 Iterator *toEnd,
3398 Iterator fromEnd,
3399 size_type numElements,
3400 ALLOCATOR allocator,
3402{
3403 *toEnd = fromEnd; // necessary in case 'numElements = 0'
3404 for ( ; 0 < numElements; --numElements) {
3406 1,
3407 allocator);
3408 ++fromEnd;
3409 *toEnd = fromEnd;
3410 }
3411}
3412
3413 // ---------------------------------------
3414 // class DequePrimitives_DequeElementGuard
3415 // ---------------------------------------
3416
3417// CREATORS
3418template <class VALUE_TYPE, int BLOCK_LENGTH, class ALLOCATOR>
3419inline
3422 const Iterator& end,
3423 ALLOCATOR allocator)
3424: d_begin(begin)
3425, d_end(end)
3426, d_allocator(allocator)
3427{
3428}
3429
3430template <class VALUE_TYPE, int BLOCK_LENGTH, class ALLOCATOR>
3431inline
3439
3440// MANIPULATORS
3441template <class VALUE_TYPE, int BLOCK_LENGTH, class ALLOCATOR>
3442inline
3444<VALUE_TYPE, BLOCK_LENGTH, ALLOCATOR>::Iterator&
3446 ::moveBegin(std::ptrdiff_t offset)
3447{
3448 d_begin += offset;
3449 return d_begin;
3450}
3451
3452template <class VALUE_TYPE, int BLOCK_LENGTH, class ALLOCATOR>
3453inline
3455<VALUE_TYPE, BLOCK_LENGTH, ALLOCATOR>::Iterator&
3457 ::moveEnd(std::ptrdiff_t offset)
3458{
3459 d_end += offset;
3460 return d_end;
3461}
3462
3463template <class VALUE_TYPE, int BLOCK_LENGTH, class ALLOCATOR>
3464inline
3470
3471 // -----------------------------------------------
3472 // class DequePrimitives_ExternalDequeElementGuard
3473 // -----------------------------------------------
3474
3475// CREATORS
3476template <class VALUE_TYPE, int BLOCK_LENGTH, class ALLOCATOR>
3477inline
3480 Iterator *end,
3481 ALLOCATOR allocator)
3482: d_begin_p(begin)
3483, d_end_p(end)
3484, d_allocator(allocator)
3485{
3486}
3487
3488template <class VALUE_TYPE, int BLOCK_LENGTH, class ALLOCATOR>
3489inline
3492{
3493 if (d_begin_p != d_end_p) {
3495 *d_end_p,
3496 d_allocator);
3497 }
3498}
3499
3500// MANIPULATORS
3501template <class VALUE_TYPE, int BLOCK_LENGTH, class ALLOCATOR>
3502inline
3503void
3506{
3507 d_begin_p = d_end_p = 0;
3508}
3509
3510 // ------------------------------------
3511 // class DequePrimitives_DequeMoveGuard
3512 // ------------------------------------
3513
3514// CREATORS
3515template <class VALUE_TYPE, int BLOCK_LENGTH>
3516inline
3519 Iterator src,
3520 std::size_t size,
3521 bool isFront)
3522: d_destination_p(dest)
3523, d_source_p(src)
3524, d_size(size)
3525, d_front(isFront)
3526{
3527}
3528
3529template <class VALUE_TYPE, int BLOCK_LENGTH>
3530inline
3533{
3534 if (d_size != 0) {
3535 // We need to reverse 'moveFront'.
3536 if (d_front) {
3537 d_destination_p += d_size;
3538 d_source_p += d_size;
3539 DequePrimitives::moveBack(&d_destination_p, &d_source_p, d_size);
3540 }
3541 // We need to reverse 'moveBack'.
3542 else {
3543 d_destination_p -= d_size;
3544 d_source_p -= d_size;
3545 DequePrimitives::moveFront(&d_destination_p, &d_source_p, d_size);
3546 }
3547 }
3548}
3549
3550// MANIPULATORS
3551template <class VALUE_TYPE, int BLOCK_LENGTH>
3552inline
3557
3558 // ------------------------------------------
3559 // class DequePrimitives_DequeEndpointProctor
3560 // ------------------------------------------
3561
3562// CREATORS
3563template <class VALUE_TYPE, int BLOCK_LENGTH>
3564inline
3567 Iterator position)
3568: d_endpoint_p(endpoint)
3569, d_position(position)
3570{
3571}
3572
3573template <class VALUE_TYPE, int BLOCK_LENGTH>
3574inline
3577{
3578 if (0 != d_endpoint_p) {
3579 *d_endpoint_p = d_position;
3580 }
3581}
3582
3583// MANIPULATORS
3584template <class VALUE_TYPE, int BLOCK_LENGTH>
3585inline
3590
3591} // close package namespace
3592
3593
3594
3595#endif // End C++11 code
3596
3597#endif
3598
3599// ----------------------------------------------------------------------------
3600// Copyright 2013 Bloomberg Finance L.P.
3601//
3602// Licensed under the Apache License, Version 2.0 (the "License");
3603// you may not use this file except in compliance with the License.
3604// You may obtain a copy of the License at
3605//
3606// http://www.apache.org/licenses/LICENSE-2.0
3607//
3608// Unless required by applicable law or agreed to in writing, software
3609// distributed under the License is distributed on an "AS IS" BASIS,
3610// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
3611// See the License for the specific language governing permissions and
3612// limitations under the License.
3613// ----------------------------- END-OF-FILE ----------------------------------
3614
3615/** @} */
3616/** @} */
3617/** @} */
Definition bslalg_dequeiterator.h:351
VALUE_TYPE * valuePtr() const
Definition bslalg_dequeiterator.h:819
Definition bslalg_dequeiterator.h:158
void previousBlock()
Definition bslalg_dequeiterator.h:511
std::size_t offsetInBlock() const
Definition bslalg_dequeiterator.h:618
std::size_t remainingInBlock() const
Definition bslalg_dequeiterator.h:626
VALUE_TYPE * valuePtr() const
Definition bslalg_dequeiterator.h:634
void nextBlock()
Set this iterator to point to the first element of the next block.
Definition bslalg_dequeiterator.h:503
Definition bslalg_dequeprimitives.h:947
Iterator & moveEnd(std::ptrdiff_t offset=1)
Definition bslalg_dequeprimitives.h:3457
Iterator & moveBegin(std::ptrdiff_t offset=-1)
Definition bslalg_dequeprimitives.h:3446
void release()
Definition bslalg_dequeprimitives.h:3466
~DequePrimitives_DequeElementGuard()
Definition bslalg_dequeprimitives.h:3433
DequeIterator< VALUE_TYPE, BLOCK_LENGTH > Iterator
Definition bslalg_dequeprimitives.h:951
Definition bslalg_dequeprimitives.h:1128
void release()
Definition bslalg_dequeprimitives.h:3586
~DequePrimitives_DequeEndpointProctor()
Definition bslalg_dequeprimitives.h:3576
DequeIterator< VALUE_TYPE, BLOCK_LENGTH > Iterator
Definition bslalg_dequeprimitives.h:1132
Definition bslalg_dequeprimitives.h:1074
void release()
Set the size of the range guarded by this object to be zero.
Definition bslalg_dequeprimitives.h:3553
~DequePrimitives_DequeMoveGuard()
Definition bslalg_dequeprimitives.h:3532
bslalg::DequePrimitives< VALUE_TYPE, BLOCK_LENGTH > DequePrimitives
Definition bslalg_dequeprimitives.h:1079
DequeIterator< VALUE_TYPE, BLOCK_LENGTH > Iterator
Definition bslalg_dequeprimitives.h:1078
Definition bslalg_dequeprimitives.h:1015
~DequePrimitives_ExternalDequeElementGuard()
Definition bslalg_dequeprimitives.h:3491
void release()
Definition bslalg_dequeprimitives.h:3505
DequeIterator< VALUE_TYPE, BLOCK_LENGTH > Iterator
Definition bslalg_dequeprimitives.h:1019
Definition bslma_destructorproctor.h:259
Definition bslmf_movableref.h:752
#define BSLS_ASSERT_SAFE(X)
Definition bsls_assert.h:1917
#define BSLS_COMPILERFEATURES_FORWARD(T, V)
Definition bsls_compilerfeatures.h:2349
#define BSLS_IDENT(str)
BSLS_IDENT() - insert string into .comment binary segment (if supported)
Definition bsls_ident.h:238
#define BSLS_UTIL_ADDRESSOF(OBJ)
Definition bsls_util.h:296
Definition bdlc_flathashmap.h:2218
@ BSLALG_DEQUEPRIMITIVES_BITWISE_COPYABLE_TRAITS
Definition bslalg_dequeprimitives.h:224
@ BSLALG_DEQUEPRIMITIVES_NON_NIL_TRAITS
Definition bslalg_dequeprimitives.h:225
@ BSLALG_DEQUEPRIMITIVES_BITWISE_MOVEABLE_TRAITS
Definition bslalg_dequeprimitives.h:223
@ BSLALG_DEQUEPRIMITIVES_NIL_TRAITS
Definition bslalg_dequeprimitives.h:222
static void construct(ALLOCATOR_TYPE &basicAllocator, ELEMENT_TYPE *elementAddr, Args &&... arguments)
Definition bslma_allocatortraits.h:1527
static void destroy(ALLOCATOR_TYPE &basicAllocator, ELEMENT_TYPE *elementAddr)
Definition bslma_allocatortraits.h:1549
Definition bslmf_integralconstant.h:261
static void defaultConstruct(typename bsl::allocator_traits< ALLOCATOR >::pointer begin, size_type numElements, ALLOCATOR allocator)
Definition bslalg_arrayprimitives.h:2129
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:1970
Definition bslalg_dequeimputil.h:126
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:815
std::size_t size_type
Definition bslalg_dequeprimitives.h:814
DequeIterator< VALUE_TYPE, 1 > Iterator
Definition bslalg_dequeprimitives.h:816
Definition bslalg_dequeprimitives.h:241
static void moveBack(Iterator *destination, Iterator *source, size_type numElements)
Definition bslalg_dequeprimitives.h:2463
static void insertAndMoveToBack(Iterator *toEnd, Iterator fromEnd, Iterator position, size_type numElements, const VALUE_TYPE &value, ALLOCATOR allocator)
Definition bslalg_dequeprimitives.h:1339
static void insertAndMoveToFront(Iterator *toBegin, Iterator fromBegin, Iterator position, size_type numElements, const VALUE_TYPE &value, ALLOCATOR allocator)
Definition bslalg_dequeprimitives.h:1754
static void uninitializedFillNFront(Iterator *toBegin, Iterator fromBegin, size_type numElements, const VALUE_TYPE &value, ALLOCATOR allocator)
Definition bslalg_dequeprimitives.h:2810
static void uninitializedFillNBack(Iterator *toEnd, Iterator fromEnd, size_type numElements, const VALUE_TYPE &value, ALLOCATOR allocator)
Definition bslalg_dequeprimitives.h:2717
static void moveInsertAndMoveToFront(Iterator *toBegin, Iterator fromBegin, Iterator position, bslmf::MovableRef< VALUE_TYPE > value, ALLOCATOR allocator)
Definition bslalg_dequeprimitives.h:2005
static void emplaceAndMoveToBack(Iterator *toEnd, Iterator fromEnd, Iterator position, ALLOCATOR allocator, Args &&... arguments)
Definition bslalg_dequeprimitives.h:2146
std::size_t size_type
Definition bslalg_dequeprimitives.h:244
static void emplaceAndMoveToFront(Iterator *toBegin, Iterator fromBegin, Iterator position, ALLOCATOR allocator, Args &&... arguments)
Definition bslalg_dequeprimitives.h:2307
DequeIterator< VALUE_TYPE, BLOCK_LENGTH > Iterator
Definition bslalg_dequeprimitives.h:245
static void valueInititalizeN(Iterator *toEnd, Iterator fromEnd, size_type numElements, ALLOCATOR allocator)
Definition bslalg_dequeprimitives.h:2766
static void moveInsertAndMoveToBack(Iterator *toEnd, Iterator fromEnd, Iterator position, bslmf::MovableRef< VALUE_TYPE > value, ALLOCATOR allocator)
Definition bslalg_dequeprimitives.h:1609
static Iterator erase(Iterator *toBegin, Iterator *toEnd, Iterator fromBegin, Iterator first, Iterator last, Iterator fromEnd, ALLOCATOR allocator)
Definition bslalg_dequeprimitives.h:1229
static void destruct(Iterator begin, Iterator end, ALLOCATOR allocator)
Definition bslalg_dequeprimitives.h:1181
static void moveFront(Iterator *destination, Iterator *source, size_type numElements)
Definition bslalg_dequeprimitives.h:2589
static void emplaceAndMoveToFrontDispatch(Iterator *toBegin, Iterator fromBegin, Iterator position, ALLOCATOR allocator, bsl::integral_constant< int, BSLALG_DEQUEPRIMITIVES_BITWISE_COPYABLE_TRAITS >, Args &&... arguments)
Definition bslalg_dequeprimitives.h:2336
static void emplaceAndMoveToBackDispatch(Iterator *toEnd, Iterator fromEnd, Iterator position, ALLOCATOR allocator, bsl::integral_constant< int, BSLALG_DEQUEPRIMITIVES_BITWISE_COPYABLE_TRAITS >, Args &&... arguments)
Definition bslalg_dequeprimitives.h:2175
static void construct(TARGET_TYPE *address, const ALLOCATOR &allocator)
Definition bslma_constructionutil.h:1244
static Allocator * allocator(Allocator *basicAllocator=0)
Definition bslma_default.h:913
Definition bslmf_isbitwisecopyable.h:298
Definition bslmf_isbitwisemoveable.h:718
Definition bslmf_functionpointertraits.h:163
Definition bslmf_isfundamental.h:303
Definition bslmf_ispointer.h:198
Definition bslmf_movableref.h:795
Definition bsls_objectbuffer.h:277
TYPE & object()
Definition bsls_objectbuffer.h:352