BDE 4.39.x Production Release
Loading...
Searching...
No Matches
bslalg_arrayprimitives.h
Go to the documentation of this file.
1/// @file bslalg_arrayprimitives.h
2///
3/// The content of this file has been pre-processed for Doxygen.
4///
5
6
7// bslalg_arrayprimitives.h -*-C++-*-
8#ifndef INCLUDED_BSLALG_ARRAYPRIMITIVES
9#define INCLUDED_BSLALG_ARRAYPRIMITIVES
10
11#include <bsls_ident.h>
12BSLS_IDENT("$Id$ $CSID$")
13
14/// @defgroup bslalg_arrayprimitives bslalg_arrayprimitives
15/// @brief Provide primitive algorithms that operate on arrays.
16/// @addtogroup bsl
17/// @{
18/// @addtogroup bslalg
19/// @{
20/// @addtogroup bslalg_arrayprimitives
21/// @{
22///
23/// <h1> Outline </h1>
24/// * <a href="#bslalg_arrayprimitives-purpose"> Purpose</a>
25/// * <a href="#bslalg_arrayprimitives-classes"> Classes </a>
26/// * <a href="#bslalg_arrayprimitives-description"> Description </a>
27/// * <a href="#bslalg_arrayprimitives-aliasing"> Aliasing </a>
28/// * <a href="#bslalg_arrayprimitives-usage"> Usage </a>
29/// * <a href="#bslalg_arrayprimitives-example-1-defining-a-vector-like-type"> Example 1: Defining a Vector-Like Type </a>
30///
31/// # Purpose {#bslalg_arrayprimitives-purpose}
32/// Provide primitive algorithms that operate on arrays.
33///
34/// # Classes {#bslalg_arrayprimitives-classes}
35///
36/// - bslalg::ArrayPrimitives: namespace for array algorithms
37///
38/// @see bslalg_dequeprimitives, bslma_constructionutil
39///
40/// # Description {#bslalg_arrayprimitives-description}
41/// This component provides utilities to initialize, move, and
42/// otherwise perform various primitive manipulations on arrays with a uniform
43/// interface, but selecting a different implementation according to the various
44/// traits possessed by the underlying type. Such primitives are exceptionally
45/// useful for implementing generic components such as containers.
46///
47/// Several algorithms are provided, with the following short synopsis
48/// describing the observable behavior and mentioning the relevant traits. See
49/// the full function-level contract for detailed description, including
50/// exception-safety guarantees. In the description below, `ADP` stands for
51/// `bslalg::ArrayDestructionPrimitives`. Note that some algorithms (e.g.,
52/// `insert`) are explained in terms of previous algorithms (e.g.,
53/// `destructiveMove`).
54/// @code
55/// Algorithm Short description of observable behavior
56/// ---------------------------- ---------------------------------------------
57/// defaultConstruct Construct each element in the target range
58/// by value-initialization, or 'std::memset' if
59/// type has a trivial default constructor.
60/// Note that this function *does* *not* perform
61/// default-initialization, the colloquial
62/// terminology "default construct" is maintained
63/// for backwards compatibility.
64///
65/// uninitializedFillN Copy construct from value for each element in
66/// the target range, or 'std::memset' if value
67/// is all 0s or 1s bits, and type is bit-wise
68/// copyable
69///
70/// copyConstruct Copy construct from each element in the
71/// original range to the corresponding element
72/// in the target range, or 'std::memcpy' if
73/// value is null and type is bit-wise copyable
74///
75/// destructiveMove Copy from each element in the original range
76/// to the corresponding element in the target
77/// and destroy objects in the original range, or
78/// 'std::memcpy' if type is bit-wise moveable
79///
80/// destructiveMoveAndInsert 'destructiveMove' from the original range to
81/// target range, leaving a hole in the middle,
82/// followed by 'defaultConstruct',
83/// 'uninitializedFillN' or 'copyConstruct' to
84/// fill hole with the appropriate values
85///
86/// destructiveMoveAndMoveInsert 'destructiveMove' from the original range to
87/// the target range, leaving a hole in the
88/// middle, followed by 'destructiveMove'
89/// from second range to fill hole
90///
91/// insert 'std::memmove' or 'copyConstruct' by some
92/// positive offset to create a hole, followed by
93/// 'uninitializedFillN', 'copyConstruct', or
94/// copy assignment to fill hole with the
95/// appropriate values
96///
97/// emplace 'std::memmove' or 'copyConstruct' by some
98/// positive offset to create a hole, followed by
99/// in-place construction, 'copyConstruct', or
100/// copy assignment to fill hole with the
101/// appropriate values
102///
103/// moveInsert 'destructiveMove' by some positive offset to
104/// create a hole, followed by 'destructiveMove'
105/// to fill hole with the appropriate values
106///
107/// erase 'ADP::destroy' elements in target range until
108/// specified position, followed by
109/// 'destructiveMove' by some negative offset
110/// from the end of the range to fill hole with
111/// the remaining values
112///
113/// rotate 'destructiveMove' to move elements into a
114/// shifting hole along parallel cyclic
115/// permutations, or 'std::memmove' for small
116/// rotations if type is bit-wise moveable
117/// @endcode
118/// The traits under consideration by this component are:
119/// @code
120/// Trait English description
121/// -------------------------------------------- -----------------------------
122/// bsl::is_trivially_default_constructible "TYPE has the trivial default
123/// constructor trait", or
124/// "TYPE has a trivial default
125/// constructor"
126///
127/// bslmf::IsBitwiseCopyable "TYPE has the bit-wise
128/// copyable trait", or
129/// "TYPE is bit-wise copyable"
130///
131/// bslmf::IsBitwiseMoveable "TYPE has the bit-wise
132/// moveable trait", or
133/// "TYPE is bit-wise moveable"
134/// @endcode
135///
136/// ## Aliasing {#bslalg_arrayprimitives-aliasing}
137///
138///
139/// There are some aliasing concerns in this component, due to the presence of
140/// the reference `const TARGET_TYPE& value` argument, which may belong to a
141/// range that will be modified during the course of the operation. All such
142/// aliasing concerns are taken care of properly. Other aliasing concerns due
143/// to the copying or a range `[first, last)` are *not* taken care of, since
144/// their intended use is for range assignments and insertions in standard
145/// containers, for which the standard explicitly says that `first` and `last`
146/// shall not be iterators into the container.
147///
148/// ## Usage {#bslalg_arrayprimitives-usage}
149///
150///
151/// In this section we show intended use of this component.
152///
153/// ### Example 1: Defining a Vector-Like Type {#bslalg_arrayprimitives-example-1-defining-a-vector-like-type}
154///
155///
156/// Suppose we want to define a STL-vector-like type. One requirement is that
157/// an object of this vector should forward its allocator to its contained
158/// elements when appropriate. Another requirement is that the vector should
159/// take advantage of the optimizations available for certain traits of the
160/// contained element type. For example, if the contained element type has the
161/// `bslmf::IsBitwiseMoveable` trait, moving an element in a vector can be done
162/// using `memcpy` instead of copy construction.
163///
164/// We can utilize the class methods provided by `bslalg::ArrayPrimitives` to
165/// satisfy the above requirements. Unlike `bslma::ConstructionUtil`, which
166/// operates on a single element, `bslalg::ArrayPrimitives` operates on arrays,
167/// which will further help simplify our implementation.
168///
169/// First, we create an elided definition of the class template `MyVector`:
170/// @code
171/// template <class TYPE, class ALLOC>
172/// class MyVector {
173/// // This class implements a vector of elements of the (template
174/// // parameter) 'TYPE', which must be copy constructible. Note that for
175/// // the brevity of the usage example, this class does not provide any
176/// // Exception-Safety guarantee.
177///
178/// // DATA
179/// TYPE *d_array_p; // pointer to the allocated array
180/// int d_capacity; // capacity of the allocated array
181/// int d_size; // number of objects
182/// ALLOC d_allocator; // allocator pointer (held, not owned)
183///
184/// public:
185/// // TYPE TRAITS
186/// BSLMF_NESTED_TRAIT_DECLARATION(
187/// MyVector,
188/// BloombergLP::bslmf::IsBitwiseMoveable);
189///
190/// // CREATORS
191/// explicit MyVector(bslma::Allocator *basicAllocator = 0)
192/// // Construct a 'MyVector' object having a size of 0 and and a
193/// // capacity of 0. Optionally specify a 'basicAllocator' used to
194/// // supply memory. If 'basicAllocator' is 0, the currently
195/// // installed default allocator is used.
196/// : d_array_p(0)
197/// , d_capacity(0)
198/// , d_size(0)
199/// , d_allocator_p(bslma::Default::allocator(basicAllocator))
200/// {
201/// }
202///
203/// MyVector(const MyVector& original,
204/// bslma::Allocator *basicAllocator = 0);
205/// // Create a 'MyVector' object having the same value as the
206/// // specified 'original' object. Optionally specify a
207/// // 'basicAllocator' used to supply memory. If 'basicAllocator' is
208/// // 0, the currently installed default allocator is used.
209///
210/// // ...
211///
212/// // MANIPULATORS
213/// void reserve(int minCapacity);
214/// // Change the capacity of this vector to at least the specified
215/// // 'minCapacity' if it is greater than the vector's current
216/// // capacity.
217///
218/// void insert(int dstIndex, int numElements, const TYPE& value);
219/// // Insert, into this vector, the specified 'numElements' of the
220/// // specified 'value' at the specified 'dstIndex'. The behavior is
221/// // undefined unless '0 <= dstIndex <= size()'.
222///
223/// // ACCESSORS
224/// const TYPE& operator[](int position) const
225/// // Return a reference providing non-modifiable access to the
226/// // element at the specified 'position' in this vector.
227/// {
228/// return d_array_p[position];
229/// }
230///
231/// int size() const
232/// // Return the size of this vector.
233/// {
234/// return d_size;
235/// }
236/// };
237/// @endcode
238/// Then, we implement the copy constructor of `MyVector`:
239/// @code
240/// template <class TYPE>
241/// MyVector<TYPE>::MyVector(const MyVector<TYPE>& original,
242/// bslma::Allocator *basicAllocator)
243/// : d_array_p(0)
244/// , d_capacity(0)
245/// , d_size(0)
246/// , d_allocator_p(bslma::Default::allocator(basicAllocator))
247/// {
248/// reserve(original.d_size);
249/// @endcode
250/// Here, we call the `bslalg::ArrayPrimitives::copyConstruct` class method to
251/// copy each element from `original.d_array_p` to `d_array_p` (When
252/// appropriate, this class method passes this vector's allocator to the copy
253/// constructor of `TYPE` or uses bit-wise copy.):
254/// @code
255/// bslalg::ArrayPrimitives::copyConstruct(
256/// d_array_p,
257/// original.d_array_p,
258/// original.d_array_p + original.d_size,
259/// d_allocator_p);
260///
261/// d_size = original.d_size;
262/// }
263/// @endcode
264/// Now, we implement the `reserve` method of `MyVector`:
265/// @code
266/// template <class TYPE>
267/// void MyVector<TYPE>::reserve(int minCapacity)
268/// {
269/// if (d_capacity >= minCapacity) return; // RETURN
270///
271/// TYPE *newArrayPtr = static_cast<TYPE*>(d_allocator_p->allocate(
272/// BloombergLP::bslma::Allocator::size_type(minCapacity * sizeof(TYPE))));
273///
274/// if (d_array_p) {
275/// @endcode
276/// Here, we call the `bslalg::ArrayPrimitives::destructiveMove` class method to
277/// copy each original element from `d_array_p` to `newArrayPtr` and then
278/// destroy all the original elements (When appropriate, this class method
279/// passes this vector's allocator to the copy constructor of `TYPE` or uses
280/// bit-wise copy.):
281/// @code
282/// bslalg::ArrayPrimitives::destructiveMove(newArrayPtr,
283/// d_array_p,
284/// d_array_p + d_size,
285/// d_allocator_p);
286/// d_allocator_p->deallocate(d_array_p);
287/// }
288///
289/// d_array_p = newArrayPtr;
290/// d_capacity = minCapacity;
291/// }
292/// @endcode
293/// Finally, we implement the `insert` method of `MyVector`:
294/// @code
295/// template <class TYPE>
296/// void
297/// MyVector<TYPE>::insert(int dstIndex, int numElements, const TYPE& value)
298/// {
299/// int newSize = d_size + numElements;
300///
301/// if (newSize > d_capacity) {
302/// int newCapacity = d_capacity == 0 ? 2 : d_capacity * 2;
303/// reserve(newCapacity);
304/// }
305/// @endcode
306/// Here, we call the `bslalg::ArrayPrimitives::insert` class method to first
307/// move each element after `dstIndex` by `numElements` and then copy construct
308/// `numElements` of `value` at `dstIndex`. (When appropriate, this class
309/// method passes this vector's allocator to the copy constructor of `TYPE` or
310/// uses bit-wise copy.):
311/// @code
312/// bslalg::ArrayPrimitives::insert(d_array_p + dstIndex,
313/// d_array_p + d_size,
314/// value,
315/// numElements,
316/// d_allocator_p);
317///
318/// d_size = newSize;
319/// }
320/// @endcode
321/// @}
322/** @} */
323/** @} */
324
325/** @addtogroup bsl
326 * @{
327 */
328/** @addtogroup bslalg
329 * @{
330 */
331/** @addtogroup bslalg_arrayprimitives
332 * @{
333 */
334
335#include <bslscm_version.h>
336
340
341#include <bslma_allocator.h>
344#include <bslma_default.h>
346#include <bslma_bslallocator.h>
347
348#include <bslmf_assert.h>
353#include <bslmf_isconvertible.h>
354#include <bslmf_isenum.h>
355#include <bslmf_isfundamental.h>
357#include <bslmf_ispointer.h>
358#include <bslmf_issame.h>
361#include <bslmf_isvoid.h>
362#include <bslmf_matchanytype.h>
363#include <bslmf_removeconst.h>
364#include <bslmf_removecv.h>
365#include <bslmf_removepointer.h>
366#include <bslmf_tag.h>
367#include <bslmf_util.h> // 'forward(V)'
368
369#include <bsls_alignmentutil.h>
370#include <bsls_assert.h>
372#include <bsls_objectbuffer.h>
373#include <bsls_performancehint.h>
374#include <bsls_platform.h>
375#include <bsls_types.h>
376#include <bsls_util.h> // 'forward<T>(V)'
377
378#include <cstddef> // 'std::size_t'
379#include <cstring> // 'memset', 'memcpy', 'memmove'
380#include <cwchar> // 'wmemset'
381
382#ifndef BDE_DONT_ALLOW_TRANSITIVE_INCLUDES
384#endif
385
386#if BSLS_COMPILERFEATURES_SIMULATE_CPP11_FEATURES
387// clang-format off
388// Include version that can be compiled with C++03
389// Generated on Mon Jan 13 08:31:35 2025
390// Command line: sim_cpp11_features.pl bslalg_arrayprimitives.h
391
392# define COMPILING_BSLALG_ARRAYPRIMITIVES_H
394# undef COMPILING_BSLALG_ARRAYPRIMITIVES_H
395
396// clang-format on
397#else
398
399#if defined(BSLS_PLATFORM_CMP_IBM) // IBM needs specific workarounds.
400# define BSLALG_ARRAYPRIMITIVES_CANNOT_REMOVE_POINTER_FROM_FUNCTION_POINTER 1
401 // xlC has problem removing pointer from function pointer types.
402
403# define BSLALG_ARRAYPRIMITIVES_NON_ZERO_NULL_VALUE_FOR_MEMBER_POINTERS 1
404 // xlC representation for a null member pointer is not all zero bits.
405#endif
406
407
408
409namespace bslalg {
410
411struct ArrayPrimitives_Imp;
412
413 // ======================
414 // struct ArrayPrimitives
415 // ======================
416
417/// This `struct` provides a namespace for a suite of independent utility
418/// functions that operate on arrays of elements of parameterized type
419/// `TARGET_TYPE`. Depending on the traits of `TARGET_TYPE`, the default
420/// and copy constructors, destructor, assignment operators, etcetera may
421/// not be invoked, optimized away by no-op or bit-wise move or copy.
422///
423/// See @ref bslalg_arrayprimitives
425
426 public:
427 // TYPES
429 typedef std::size_t size_type;
430 typedef std::ptrdiff_t difference_type;
431
432 // CLASS METHODS
433
434 /// Copy the elements of type `allocator_traits<ALLOCATOR>::value_type`
435 /// in the range beginning at the specified `fromBegin` location and
436 /// ending immediately before the specified `fromEnd` location into the
437 /// uninitialized array beginning at the specified `toBegin` location,
438 /// using the specified `allocator` to supply memory (if required). If
439 /// a constructor throws an exception during this operation, the output
440 /// array is left in an uninitialized state.
441 ///
442 /// \pre The behavior is undefined unless `toBegin` refers to space sufficient to hold
443 /// `fromEnd - fromBegin` elements.
444 template <class ALLOCATOR, class FWD_ITER, class SENTINEL>
445 static void
448 FWD_ITER fromBegin,
449 SENTINEL fromEnd,
450 ALLOCATOR allocator);
451 template <class ALLOCATOR, class SOURCE_TYPE>
452 static void
455 SOURCE_TYPE *fromBegin,
456 SOURCE_TYPE *fromEnd,
457 ALLOCATOR allocator);
458
459 /// Copy into an uninitialized array of (the template parameter)
460 /// `TARGET_TYPE` beginning at the specified `toBegin` address, the
461 /// elements in the array of `TARGET_TYPE` starting at the specified
462 /// `fromBegin` address and ending immediately before the specified
463 /// `fromEnd` address. If the (template parameter) `ALLOCATOR` type is
464 /// derived from `bslma::Allocator` and `TARGET_TYPE` supports `bslma`
465 /// allocators, then the specified `allocator` is passed to each
466 /// invocation of the `TARGET_TYPE` copy constructor. If a
467 /// `TARGET_TYPE` constructor throws an exception during the operation,
468 /// then the destructor is called on any newly-constructed elements,
469 /// leaving the output array in an uninitialized state.
470 template <class TARGET_TYPE, class FWD_ITER, class SENTINEL>
471 static void copyConstruct(TARGET_TYPE *toBegin,
472 FWD_ITER fromBegin,
473 SENTINEL fromEnd,
474 bslma::Allocator *allocator);
475 template <class TARGET_TYPE, class SOURCE_TYPE>
476 static void copyConstruct(TARGET_TYPE *toBegin,
477 SOURCE_TYPE *fromBegin,
478 SOURCE_TYPE *fromEnd,
479 bslma::Allocator *allocator);
480
481 /// Move the elements of type `allocator_traits<ALLOCATOR>::value_type`
482 /// in the range beginning at the specified `fromBegin` location and
483 /// ending immediately before the specified `fromEnd` location into the
484 /// uninitialized array beginning at the specified `toBegin` location,
485 /// using the specified `allocator` to supply memory (if required). The
486 /// elements in the input array are left in a valid but unspecified
487 /// state. If a constructor throws an exception during this operation,
488 /// the output array is left in an uninitialized state.
489 ///
490 /// \pre The behavior is undefined unless `toBegin` refers to space sufficient to hold
491 /// `fromEnd - fromBegin` elements.
492 template <class ALLOCATOR>
493 static void
498 ALLOCATOR allocator);
499
500 /// Move the elements of the (template parameter) `TARGET_TYPE` starting
501 /// at the specified `fromBegin` address and ending immediately before
502 /// the specified `fromEnd` address into the uninitialized array of
503 /// `TARGET_TYPE` beginning at the specified `toBegin` address, using
504 /// the specified `allocator` to supply memory (if required). The
505 /// elements in the input array are left in a valid but unspecified
506 /// state. If a constructor throws an exception during this operation,
507 /// the output array is left in an uninitialized state.
508 ///
509 /// \pre The behavior is undefined unless `toBegin` refers to space sufficient to hold
510 /// `fromEnd - fromBegin` elements.
511 template <class TARGET_TYPE>
512 static void moveConstruct(TARGET_TYPE *toBegin,
513 TARGET_TYPE *fromBegin,
514 TARGET_TYPE *fromEnd,
515 bslma::Allocator *allocator);
516
517 /// Value-inititalize the specified `numElements` objects of type
518 /// `allocator_traits<ALLOCATOR>::value_type` into the uninitialized
519 /// array beginning at the specified `begin` location, using the
520 /// specified `allocator` to supply memory (if required). If a
521 /// constructor throws an exception during this operation, then the
522 /// destructor is called on any newly constructed elements, leaving the
523 /// output array in an uninitialized state.
524 ///
525 /// \pre The behavior is undefined unless the `begin` refers to space sufficient to hold `numElements`.
526 template <class ALLOCATOR>
527 static void defaultConstruct(
529 size_type numElements,
530 ALLOCATOR allocator);
531
532 /// Construct each of the elements of an array of the specified
533 /// `numElements` of the parameterized `TARGET_TYPE` starting at the
534 /// specified `begin` address by value-initialization. If the (template
535 /// parameter) `ALLOCATOR` type is derived from `bslma::Allocator` and
536 /// `TARGET_TYPE` supports `bslma` allocators, then the specified
537 /// `allocator` is passed to each `TARGET_TYPE` default constructor call.
538 ///
539 /// \pre The behavior is undefined unless the output array contains at
540 /// least `numElements` uninitialized elements after `begin`. If a
541 /// `TARGET_TYPE` constructor throws an exception during this operation,
542 /// then the destructor is called on any newly-constructed elements,
543 /// leaving the output array in an uninitialized state.
544 template <class TARGET_TYPE>
545 static void defaultConstruct(TARGET_TYPE *begin,
546 size_type numElements,
547 bslma::Allocator *allocator);
548
549 /// Move the elements of type `allocator_traits<ALLOCATOR>::value_type`
550 /// in the range beginning at the specified `fromBegin` location and
551 /// ending immediately before the specified `fromEnd` location into the
552 /// uninitialized array beginning at the specified `toBegin` location,
553 /// using the specified `allocator` to supply memory (if required). On
554 /// return, the elements in the input range are invalid, i.e., their
555 /// destructors must not be called after this operation returns. If a
556 /// constructor throws an exception during this operation, the output
557 /// array is left in an uninitialized state. If a constructor other
558 /// than the move constructor of a non-copy-constructible type throws
559 /// an exception during this operation, the input array is unaffected;
560 /// otherwise, if the move constructor of a non-copy-constructible type
561 /// throws an exception during this operation, the input array is left in a valid but unspecified state.
562 ///
563 /// \pre The behavior is undefined unless
564 /// `toBegin` refers to space sufficient to hold `fromEnd - fromBegin`
565 /// elements.
566 template <class ALLOCATOR>
567 static void destructiveMove(
571 ALLOCATOR allocator);
572
573 /// Move the elements of the parameterized `TARGET_TYPE` in the array
574 /// starting at the specified `fromBegin` address and ending immediately
575 /// before the specified `fromEnd` address into an uninitialized array
576 /// of `TARGET_TYPE` beginning at the specified `toBegin` address. On
577 /// return, the elements in the input range are invalid, i.e., their
578 /// destructors must not be called after this operation returns. If the
579 /// parameterized `ALLOCATOR` type is derived from `bslma::Allocator`
580 /// and `TARGET_TYPE` supports `bslma` allocators, then the specified
581 /// `allocator` is used by the objects in their new location. If an
582 /// exception is thrown by a `TARGET_TYPE` constructor during the
583 /// operation, then the output array is left in an uninitialized state
584 /// and the input elements remain in their original state.
585 template <class TARGET_TYPE>
586 static void destructiveMove(TARGET_TYPE *toBegin,
587 TARGET_TYPE *fromBegin,
588 TARGET_TYPE *fromEnd,
589 bslma::Allocator *allocator);
590
591#if !BSLS_COMPILERFEATURES_SIMULATE_CPP11_FEATURES // $var-args=10
592
593 /// Move the elements of type `allocator_traits<ALLOCATOR>::value_type`
594 /// in the specified range `[fromBegin .. fromEnd)` into the
595 /// uninitialized array beginning at the specified `toBegin` location,
596 /// using the specified `allocator` to supply memory (if required),
597 /// inserting at the specified `position` (after translating from
598 /// `fromBegin` to `toBegin`) a newly created object constructed by
599 /// forwarding `allocator` (if required) and the specified (variable
600 /// number of) `arguments` to the corresponding constructor of the
601 /// target type, ensuring that the specified `fromEndPtr` points to the
602 /// first uninitialized element in `[fromBegin .. fromEnd)` as the
603 /// elements are moved from source to destination. On return, the
604 /// elements in the input range are invalid, i.e., their destructors
605 /// must not be called after this operation returns. If a constructor
606 /// throws an exception during this operation, the output array is left
607 /// in an uninitialized state. If an exception is thrown during the
608 /// in-place construction of the new object, the input array is
609 /// unaffected; otherwise, if a (copy or move) constructor throws an
610 /// exception during this operation, the input elements in the range
611 /// `[fromBegin .. *fromEndPtr)` are left in a valid but unspecified
612 /// state and the remaining portion of the input array is left in an uninitialized state.
613 ///
614 /// \pre The behavior is undefined unless
615 /// `fromBegin <= position <= fromEnd` and `toBegin` refers to space
616 /// sufficient to hold `fromEnd - fromBegin + 1` elements.
617 template <class ALLOCATOR, class... ARGS>
618 static void destructiveMoveAndEmplace(
624 ALLOCATOR allocator,
625 ARGS&&... arguments);
626
627#endif
628
629 /// Move the elements of type `allocator_traits<ALLOCATOR>::value_type`
630 /// in the range beginning at the specified `fromBegin` location and
631 /// ending immediately before the specified `fromEnd` location into the
632 /// uninitialized array beginning at the specified `toBegin` location
633 /// using the specified `allocator` to supply memory (if required),
634 /// inserting at the specified `position` (after translating from
635 /// `fromBegin` to `toBegin`) the specified `numElements` objects
636 /// initialized to default values, ensuring that the specified
637 /// `fromEndPtr` points to the first uninitialized element in
638 /// `[fromBegin .. fromEnd)` as the elements are moved from source to
639 /// destination. On return, the elements in the input range are
640 /// invalid, i.e., their destructors must not be called after this
641 /// operation returns. If a constructor throws an exception during this
642 /// operation, the output array is left in an uninitialized state. If a
643 /// default constructor throws an exception, the input array is
644 /// unaffected; otherwise, if a (copy or move) constructor throws an
645 /// exception during this operation, the input elements in the range
646 /// `[fromBegin .. *fromEndPtr)` are left in a valid but unspecified
647 /// state and the remaining portion of the input array is left in an uninitialized state.
648 ///
649 /// \pre The behavior is undefined unless 'fromBegin <=
650 /// position <= fromEnd' and `toBegin` refers to space sufficient to
651 /// hold `fromEnd - fromBegin + 1` elements.
652 template <class ALLOCATOR>
653 static void destructiveMoveAndInsert(
659 size_type numElements,
660 ALLOCATOR allocator);
661
662 /// Move the elements of the (template parameter) `TARGET_TYPE` in the
663 /// starting at the specified `fromBegin` address and ending immediately
664 /// before the specified `fromEnd` address into the uninitialized array
665 /// beginning at the specified `toBegin` location using the specified
666 /// `allocator` to supply memory (if required), inserting at the
667 /// specified `position` (after translating from `fromBegin` to
668 /// `toBegin`) `numElements` objects initialized to default values,
669 /// ensuring that the specified `fromEndPtr` points to the first
670 /// uninitialized element in `[fromBegin .. fromEnd)` as the elements
671 /// are moved from source to destination. On return, the elements in
672 /// the input range are invalid, i.e., their destructors must not be
673 /// called after this operation returns. If a constructor throws an
674 /// exception during this operation, the output array is left in an
675 /// uninitialized state. If a default constructor throws an exception,
676 /// the input array is unaffected; otherwise, if a (copy or move)
677 /// constructor throws an exception during this operation, the input
678 /// elements in the range `[fromBegin .. *fromEndPtr)` are left in a
679 /// valid but unspecified state and the remaining portion of the input
680 /// array is left in an uninitialized state.
681 ///
682 /// \pre The behavior is undefined unless `fromBegin <= position <= fromEnd` and `toBegin` refers to
683 /// space sufficient to hold `fromEnd - fromBegin + numElements`
684 /// elements.
685 template <class TARGET_TYPE>
686 static void destructiveMoveAndInsert(TARGET_TYPE *toBegin,
687 TARGET_TYPE **fromEndPtr,
688 TARGET_TYPE *fromBegin,
689 TARGET_TYPE *position,
690 TARGET_TYPE *fromEnd,
691 size_type numElements,
692 bslma::Allocator *allocator);
693
694 /// Move the elements of type `allocator_traits<ALLOCATOR>::value_type`
695 /// in the range beginning at the specified `fromBegin` location and
696 /// ending immediately before the specified `fromEnd` location into the
697 /// uninitialized array beginning at the specified `toBegin` location
698 /// using the specified `allocator` to supply memory (if required),
699 /// inserting at the specified `position` (after translating from
700 /// `fromBegin` to `toBegin`) the specified `numElements` copies of the
701 /// specified `value`, ensuring that the specified `fromEndPtr` points
702 /// to the first uninitialized element in `[fromBegin .. fromEnd)` as
703 /// the elements are moved from source to destination. On return, the
704 /// elements in the input range are invalid, i.e., their destructors
705 /// must not be called after this operation returns. If a constructor
706 /// throws an exception during this operation, the output array is left
707 /// in an uninitialized state. If a (copy or move) constructor throws
708 /// an exception during this operation, the input elements in the range
709 /// `[fromBegin .. *fromEndPtr)` are left in a valid but unspecified
710 /// state and the remaining portion of the input array is left in an uninitialized state.
711 ///
712 /// \pre The behavior is undefined unless
713 /// `fromBegin <= position <= fromEnd` and `toBegin` refers to space
714 /// sufficient to hold `fromEnd - fromBegin + numElements` elements.
715 template <class ALLOCATOR>
716 static void destructiveMoveAndInsert(
723 size_type numElements,
724 ALLOCATOR allocator);
725
726 /// Move the elements of the parameterized `TARGET_TYPE` in the array
727 /// starting at the specified `fromBegin` address and ending immediately
728 /// before the specified `fromEnd` address into an uninitialized array
729 /// of `TARGET_TYPE` at the specified `toBegin` address, inserting at
730 /// the specified `position` (after translating from `fromBegin` to
731 /// `toBegin`) the specified `numElements` copies of the specified
732 /// `value`. Keep the pointer at the specified `fromEndPtr` address
733 /// pointing to the first uninitialized element in '[ fromBegin,
734 /// fromEnd)' as the elements are moved from source to destination.
735 ///
736 /// \pre The behavior is undefined unless `fromBegin <= position <= fromEnd` and
737 /// the destination array contains at least
738 /// `(fromEnd - fromBegin) + numElements` uninitialized elements. If a
739 /// copy constructor or assignment operator for `TARGET_TYPE` throws an
740 /// exception, then any elements created in the output array are
741 /// destroyed and the elements in the range `[ fromBegin, *fromEndPtr )`
742 /// will have unspecified but valid values.
743 template <class TARGET_TYPE>
744 static void destructiveMoveAndInsert(TARGET_TYPE *toBegin,
745 TARGET_TYPE **fromEndPtr,
746 TARGET_TYPE *fromBegin,
747 TARGET_TYPE *position,
748 TARGET_TYPE *fromEnd,
749 const TARGET_TYPE& value,
750 size_type numElements,
751 bslma::Allocator *allocator);
752
753 /// Move the elements of type `allocator_traits<ALLOCATOR>::value_type` in
754 /// the range beginning at the specified `fromBegin` location and ending
755 /// immediately before the specified `fromEnd` location into the
756 /// uninitialized array beginning at the specified `toBegin` location using
757 /// the specified `allocator` to supply memory (if required), inserting at
758 /// the specified `position` (after translating from `fromBegin` to
759 /// `toBegin`) the specified `numElements` copies of the non-modifiable
760 /// elements from the range starting at the specified `first` iterator of
761 /// (template parameter) type `FWD_ITER` and ending immediately before the
762 /// specified `last` sentinel or iterator, ensuring that the specified
763 /// `fromEndPtr` points to the first uninitialized element in
764 /// `[fromBegin .. fromEnd)` as the elements are moved from source to
765 /// destination. On return, the elements in the input range are invalid,
766 /// i.e., their destructors must not be called after this operation
767 /// returns. If a constructor throws an exception during this operation,
768 /// the output array is left in an uninitialized state. If a constructor
769 /// other than the copy or move constructor throws an exception during this
770 /// operation, the input array is unaffected; otherwise, if a copy or move
771 /// constructor throws an exception during this operation, the input
772 /// elements in the range `[fromBegin .. *fromEndPtr)` are left in a valid
773 /// but unspecified state and the remaining portion of the input array is left in an uninitialized state.
774 ///
775 /// \pre The behavior is undefined unless
776 /// `fromBegin <= position <= fromEnd` and `toBegin` refers to space
777 /// sufficient to hold `fromEnd - fromBegin + numElements` elements.
778 template <class ALLOCATOR, class FWD_ITER, class SENTINEL>
779 static void destructiveMoveAndInsert(
785 FWD_ITER first,
786 SENTINEL last,
787 size_type numElements,
788 ALLOCATOR allocator);
789
790 /// Move the elements of the parameterized `TARGET_TYPE` in the array
791 /// starting at the specified `fromBegin` address and ending immediately
792 /// before the specified `fromEnd` address into an uninitialized array of
793 /// `TARGET_TYPE` at the specified `toBegin` address, inserting at the
794 /// specified `position` (after translating from `fromBegin` to `toBegin`)
795 /// the specified `numElements` copies of the non-modifiable elements from
796 /// the range starting at the specified `first` iterator of the
797 /// parameterized `FWD_ITER` type and ending immediately before the
798 /// specified `last` sentinel or iterator. Keep the pointer at the
799 /// specified `fromEndPtr` to point to the first uninitialized element in
800 /// `[fromBegin, fromEnd)` as the elements are moved from source to destination.
801 ///
802 /// \pre The behavior is undefined unless
803 /// `fromBegin <= position <= fromEnd`, the destination array contains at
804 /// least `(fromEnd - fromBegin) + numElements` uninitialized elements
805 /// after `toBegin`, and `numElements` is the distance from `first` to
806 /// `last`. If a copy constructor or assignment operator for `TARGET_TYPE`
807 /// throws an exception, then any elements created in the output array are
808 /// destroyed and the elements in the range `[ fromBegin, *fromEndPtr )`
809 /// will have unspecified but valid values.
810 template <class TARGET_TYPE, class FWD_ITER, class SENTINEL>
811 static void destructiveMoveAndInsert(TARGET_TYPE *toBegin,
812 TARGET_TYPE **fromEndPtr,
813 TARGET_TYPE *fromBegin,
814 TARGET_TYPE *position,
815 TARGET_TYPE *fromEnd,
816 FWD_ITER first,
817 SENTINEL last,
818 size_type numElements,
819 bslma::Allocator *allocator);
820
821 /// TBD: improve comment
822 /// Move, into an uninitialized array beginning at the specified
823 /// `toBegin` pointer, elements of type given by the `allocator_traits`
824 /// class template for (template parameter) `ALLOCATOR`, from elements
825 /// starting at the specified `fromBegin` pointer and ending immediately
826 /// before the specified `fromEnd` address, moving into the specified
827 /// `position` (after translating from `fromBegin` to `toBegin`) the
828 /// specified `numElements` elements starting at the specified `first`
829 /// pointer and ending immediately before the specified `last` pointer.
830 /// Keep the pointer at the specified `fromEndPtr` address pointing to
831 /// the first uninitialized element in `[ fromBegin, fromEnd)` as the
832 /// elements are moved from source to destination.
833 ///
834 /// \pre The behavior is undefined unless `fromBegin <= position <= fromEnd` and the
835 /// destination array contains at least
836 /// `(fromEnd - fromBegin) + numElements` uninitialized elements. If a
837 /// constructor or assignment operator for the target type throws an
838 /// exception, then any elements created in the output array are
839 /// destroyed and the elements in the range `[ fromBegin, *fromEndPtr )`
840 /// will have valid but unspecified values.
841 template <class ALLOCATOR>
851 size_type numElements,
852 ALLOCATOR allocator);
853
854 /// Move the elements of (template parameter) `TARGET_TYPE` in the array
855 /// starting at the specified `fromBegin` address and ending immediately
856 /// before the specified `fromEnd` address into an uninitialized array
857 /// of `TARGET_TYPE` at the specified `toBegin` address, moving into the
858 /// specified `position` (after translating from `fromBegin` to
859 /// `toBegin`) the specified `numElements` of the `TARGET_TYPE` from the
860 /// array starting at the specified `first` address and ending
861 /// immediately before the specified `last` address. Keep the pointer
862 /// at the specified `fromEndPtr` address pointing to the first
863 /// uninitialized element in `[fromBegin, fromEnd)`, and the pointer at
864 /// the specified `lastPtr` address pointing to the end of the moved
865 /// range as the elements from the range `[ first, last)` are moved from source to destination.
866 ///
867 /// \pre The behavior is undefined unless
868 /// `fromBegin <= position <= fromEnd`, the destination array contains
869 /// at least `(fromEnd - fromBegin) + numElements` uninitialized
870 /// elements after `toBegin`, and `numElements` is the distance from
871 /// `first` to `last`. If a copy constructor or assignment operator for
872 /// `TARGET_TYPE` throws an exception, then any elements in
873 /// `[ *lastPtr, last )` as well as in `[ toBegin, ... )` are destroyed,
874 /// and the elements in the ranges `[ first, *lastPtr )` and
875 /// `[ fromBegin, *fromEndPtr )` will have unspecified but valid values.
876 template <class TARGET_TYPE>
877 static void destructiveMoveAndMoveInsert(TARGET_TYPE *toBegin,
878 TARGET_TYPE **fromEndPtr,
879 TARGET_TYPE **lastPtr,
880 TARGET_TYPE *fromBegin,
881 TARGET_TYPE *position,
882 TARGET_TYPE *fromEnd,
883 TARGET_TYPE *first,
884 TARGET_TYPE *last,
885 size_type numElements,
886 bslma::Allocator *allocator);
887
888#if !BSLS_COMPILERFEATURES_SIMULATE_CPP11_FEATURES // $var-args=10
889
890 /// Insert a newly created `allocator_traits<ALLOCATOR>::value_type`
891 /// object, constructed by forwarding the specified `allocator` (if
892 /// required) and the specified (variable number of) `arguments` to the
893 /// corresponding constructor of
894 /// `allocator_traits<ALLOCATOR>::value_type`, into the array at the
895 /// specified `toBegin` location, shifting forward the elements from
896 /// `toBegin` to the specified `toEnd` location by one position. If an
897 /// exception is thrown during the in-place construction of the new
898 /// object, the elements in the range `[toBegin .. toEnd)` are
899 /// unaffected; otherwise, if a (copy or move) constructor or a (copy or
900 /// move) assignment operator throws an exception, then any elements
901 /// created after `toEnd` are destroyed and the elements in the range
902 /// `[toBegin .. toEnd )` are left in a valid but unspecified state.
903 ///
904 /// \pre The behavior is undefined unless `toBegin` refers to sufficient
905 /// space to hold at least `toEnd - toBegin + 1` elements.
906 template <class ALLOCATOR, class... ARGS>
907 static void emplace(
910 ALLOCATOR allocator,
911 ARGS&&... arguments);
912
913 /// Insert a newly created object of the (template parameter) type
914 /// `TARGET_TYPE`, constructed by forwarding the specified `allocator`
915 /// (if required) and the specified (variable number of) `arguments` to
916 /// the corresponding constructor of `TARGET_TYPE`, into the array at
917 /// the specified `toBegin` address, shifting the elements from
918 /// `toBegin` to the specified `toEnd` address up one position towards
919 /// larger addresses. If an exception is thrown during the in-place
920 /// construction of the new object, the elements in the range
921 /// `[toBegin .. toEnd)` are unaffected; otherwise, if a (copy or move)
922 /// constructor or a (copy or move) assignment operator throws an
923 /// exception, then any elements created after `toEnd` are destroyed and
924 /// the elements in the range `[toBegin .. toEnd )` are left in a valid but unspecified state.
925 ///
926 /// \pre The behavior is undefined unless `toBegin`
927 /// refers to sufficient space to hold at least `toEnd - toBegin + 1`
928 /// elements.
929 template <class TARGET_TYPE, class... ARGS>
930 static void emplace(TARGET_TYPE *toBegin,
931 TARGET_TYPE *toEnd,
932 bslma::Allocator *allocator,
933 ARGS&&... args);
934
935#endif
936
937 /// TBD: improve comment
938 /// Destroy the elements of type given by the `allocator_traits` class
939 /// template for (template parameter) `ALLOCATOR` starting at the
940 /// specified `first` `first` pointer and ending immediately before the
941 /// specified `middle` pointer, and move the elements in the array
942 /// starting at `middle` and ending at the specified `last` pointer down
943 /// to the `first` pointer. If an assignment throws an exception during
944 /// this process, all of the elements in the range `[ first, last )`
945 /// will have unspecified but valid values, and no elements are destroyed.
946 ///
947 /// \pre The behavior is undefined unless
948 /// `first <= middle <= last`.
949 template <class ALLOCATOR>
950 static void
954 ALLOCATOR allocator);
955
956 /// Destroy the elements of the parameterized `TARGET_TYPE` in the array
957 /// starting at the specified `first` address and ending immediately
958 /// before the specified `middle` address, and move the elements in the
959 /// array starting at `middle` and ending at the specified `last`
960 /// address down to the `first` address. If an assignment throws an
961 /// exception during this process, all of the elements in the range
962 /// `[ first, last )` will have unspecified but valid values, and no elements are destroyed.
963 ///
964 /// \pre The behavior is undefined unless
965 /// `first <= middle <= last`.
966 template <class TARGET_TYPE>
967 static void erase(TARGET_TYPE *first,
968 TARGET_TYPE *middle,
969 TARGET_TYPE *last,
970 bslma::Allocator *allocator = 0);
971
972 /// Insert the specified `value` into the array of
973 /// `allocator_traits<ALLOCATOR>::value_type` objects at the specified
974 /// `toBegin` location, shifting forward the elements from `toBegin` to
975 /// the specified `toEnd` location by one position. `value` is left in
976 /// a valid but unspecified state. If a (copy or move) constructor or a
977 /// (copy or move) assignment operator throws an exception, then any
978 /// elements created after `toEnd` are destroyed and the elements in the
979 /// range `[toBegin .. toEnd )` are left in a valid but unspecified state.
980 ///
981 /// \pre The behavior is undefined unless `toBegin` refers to
982 /// sufficient space to hold at least `toEnd - toBegin + 1` elements.
983 template <class ALLOCATOR>
984 static void
989 ALLOCATOR allocator);
990
991 /// Insert the specified `value` into the array of the (template
992 /// parameter) type `TARGET_TYPE` at the specified `toBegin` address,
993 /// shifting the elements from `toBegin` to the specified `toEnd`
994 /// address by one position towards larger addresses. `value` is left
995 /// in a valid but unspecified state. If a (copy or move) constructor
996 /// or a (copy or move) assignment operator throws an exception, then
997 /// any elements created after `toEnd` are destroyed and the elements in
998 /// the range `[toBegin .. toEnd )` are left in a valid but unspecified state.
999 ///
1000 /// \pre The behavior is undefined unless `toBegin` refers to
1001 /// sufficient space to hold at least `toEnd - toBegin + 1` elements.
1002 template <class TARGET_TYPE>
1003 static void insert(TARGET_TYPE *toBegin,
1004 TARGET_TYPE *toEnd,
1006 bslma::Allocator *allocator);
1007
1008 /// Insert the specified `numElements` copies of the specified `value`
1009 /// into the array of type `allocator_traits<ALLOCATOR>::value_type`
1010 /// starting at the specified `toBegin` location, shifting forward the
1011 /// elements from `toBegin` to the specified `toEnd` location by
1012 /// `numElements` positions. If a (copy or move) constructor or a (copy
1013 /// or move) assignment operator throws an exception, any elements
1014 /// created after `toEnd` are destroyed and the elements in the range
1015 /// `[toBegin .. toEnd)` are left in a valid but unspecified state.
1016 ///
1017 /// \pre The behavior is undefined unless `toBegin` refers to space sufficient to
1018 /// hold at least `toEnd - toBegin + numElements` elements.
1019 template <class ALLOCATOR>
1020 static void
1021 insert(
1025 size_type numElements,
1026 ALLOCATOR allocator);
1027
1028 /// Insert the specified `numElements` copies of the specified `value`
1029 /// into the array of (template parameter) `TARGET_TYPE` starting at the
1030 /// specified `toBegin` address and ending immediately before the
1031 /// specified `toEnd` address, shifting the elements in the array by
1032 /// `numElements` positions towards larger addresses.
1033 ///
1034 /// \pre The behavior is undefined unless the destination array contains at least
1035 /// `numElements` uninitialized elements after `toEnd`. If a copy
1036 /// constructor or assignment operator for `TARGET_TYPE` throws an
1037 /// exception, then any elements created after `toEnd` are destroyed and
1038 /// the elements in the range `[ toBegin, toEnd )` will have
1039 /// unspecified, but valid, values.
1040 template <class TARGET_TYPE>
1041 static void insert(TARGET_TYPE *toBegin,
1042 TARGET_TYPE *toEnd,
1043 const TARGET_TYPE& value,
1044 size_type numElements,
1045 bslma::Allocator *allocator);
1046
1047 /// TBD: improve comment
1048 /// Insert the specified `numElements` from the range starting at the
1049 /// specified `fromBegin` of (template parameter) `FWD_ITER` type (or
1050 /// template parameter `SOURCE_TYPE *`) and ending immediately before the
1051 /// specified `fromEnd` sentinels or iterators of (template parameter)
1052 /// `SENTINEL` type (or template parameter `SOURCE_TYPE *`), into the array
1053 /// of elements of type given by the `allocator_traits` class template for
1054 /// (template parameter) `ALLOCATOR`, starting at the specified `toBegin`
1055 /// address, shifting forward the elements in the array by `numElements` positions.
1056 ///
1057 /// \pre The behavior is undefined unless the destination array
1058 /// contains `numElements` uninitialized elements after `toEnd`,
1059 /// `numElements` is the distance between `fromBegin` and `fromEnd`, and
1060 /// the input array and the destination array do not overlap. If a copy
1061 /// constructor or assignment operator throws an exception, then any
1062 /// elements created after `toEnd` are destroyed and the elements in the
1063 /// range `[ toBegin, toEnd )` will have valid but unspecified values.
1064 template <class ALLOCATOR, class FWD_ITER, class SENTINEL>
1065 static void
1068 FWD_ITER fromBegin,
1069 SENTINEL fromEnd,
1070 size_type numElements,
1071 ALLOCATOR allocator);
1072 template <class ALLOCATOR, class SOURCE_TYPE>
1073 static void
1076 SOURCE_TYPE *fromBegin,
1077 SOURCE_TYPE *fromEnd,
1078 size_type numElements,
1079 ALLOCATOR allocator);
1080
1081 /// Insert, into the array at the specified `toBegin` location, the
1082 /// specified `numElements` from the range starting at the specified
1083 /// `fromBegin` iterators of the (template parameter) `FWD_ITER` type (or
1084 /// the (template parameter) `SOURCE_TYPE *`) and ending immediately before
1085 /// the specified `fromEnd` sentinels or iterators of the (template
1086 /// parameter) `SENTINEL` type (or the (template parameter)
1087 /// `SOURCE_TYPE *`), into the array of elements of the parameterized
1088 /// `TARGET_TYPE` starting at the specified `toBegin` address and ending
1089 /// immediately before the specified `toEnd` address, shifting the elements
1090 /// in the array by `numElements` positions towards larger addresses.
1091 ///
1092 /// \pre The behavior is undefined unless the destination array contains
1093 /// `numElements` uninitialized elements after `toEnd`, `numElements` is
1094 /// the distance between `fromBegin` and `fromEnd`, and the input array and
1095 /// the destination array do not overlap. If a copy constructor or
1096 /// assignment operator for `TARGET_TYPE` throws an exception, then any
1097 /// elements created after `toEnd` are destroyed and the elements in the
1098 /// range `[ toBegin, toEnd )` will have unspecified, but valid, values.
1099 template <class TARGET_TYPE, class FWD_ITER, class SENTINEL>
1100 static void insert(TARGET_TYPE *toBegin,
1101 TARGET_TYPE *toEnd,
1102 FWD_ITER fromBegin,
1103 SENTINEL fromEnd,
1104 size_type numElements,
1105 bslma::Allocator *allocator);
1106 template <class TARGET_TYPE, class SOURCE_TYPE>
1107 static void insert(TARGET_TYPE *toBegin,
1108 TARGET_TYPE *toEnd,
1109 SOURCE_TYPE *fromBegin,
1110 SOURCE_TYPE *fromEnd,
1111 size_type numElements,
1112 bslma::Allocator *allocator);
1113
1114 /// TBD: improve comment
1115 /// Move the elements of type given by the `allocator_traits` class
1116 /// template for (template parameter) `ALLOCATOR` in the array starting
1117 /// at the specified `toBegin` location and ending immediately before
1118 /// the specified `toEnd` location by the specified `numElements`
1119 /// positions towards larger addresses, and fill the `numElements` at
1120 /// the `toBegin` location by moving the elements from the array
1121 /// starting at the specified `fromBegin` and ending immediately before
1122 /// the specified `fromEnd` location. Keep the iterator at the
1123 /// specified `fromEndPtr` address pointing to the end of the range as
1124 /// the elements from `[ fromBegin, fromEnd )` are moved from source to destination.
1125 ///
1126 /// \pre The behavior is undefined unless the destination array
1127 /// contains `numElements` uninitialized elements after `toEnd`,
1128 /// `numElements` is the distance from `fromBegin` to `fromEnd`, and the
1129 /// input and destination arrays do not overlap. If a copy constructor
1130 /// or assignment operator for `TARGET_TYPE` throws an exception, then
1131 /// any elements created after `toEnd` are destroyed, the elements in
1132 /// the ranges `[ toBegin, toEnd)` and `[ fromBegin, *fromEndPtr )` will
1133 /// have unspecified, but valid, values, and the elements in
1134 /// `[ *fromEndPtr, fromEnd )` will be destroyed.
1135 template <class ALLOCATOR>
1136 static void moveInsert(
1139 typename bsl::allocator_traits<ALLOCATOR>::pointer *fromEndPtr,
1142 size_type numElements,
1143 ALLOCATOR allocator);
1144
1145 /// Move the elements of the (template parameter) `TARGET_TYPE` in the
1146 /// array starting at the specified `toBegin` address and ending
1147 /// immediately before the specified `toEnd` address by the specified
1148 /// `numElements` positions towards larger addresses, and fill the
1149 /// `numElements` at the `toBegin` address by moving the elements from
1150 /// the array starting at the specified `fromBegin` and ending
1151 /// immediately before the specified `fromEnd` address. Keep the
1152 /// iterator at the specified `fromEndPtr` address pointing to the end
1153 /// of the range as the elements from `[ fromBegin, fromEnd )` are moved from source to destination.
1154 ///
1155 /// \pre The behavior is undefined unless the
1156 /// destination array contains `numElements` uninitialized elements
1157 /// after `toEnd`, `numElements` is the distance from `fromBegin` to
1158 /// `fromEnd`, and the input and destination arrays do not overlap. If
1159 /// a copy constructor or assignment operator for `TARGET_TYPE` throws
1160 /// an exception, then any elements created after `toEnd` are destroyed,
1161 /// the elements in the ranges `[ toBegin, toEnd)` and
1162 /// `[ fromBegin, *fromEndPtr )` will have unspecified, but valid,
1163 /// values, and the elements in `[ *fromEndPtr, fromEnd )` will be
1164 /// destroyed.
1165 template <class TARGET_TYPE>
1166 static void moveInsert(TARGET_TYPE *toBegin,
1167 TARGET_TYPE *toEnd,
1168 TARGET_TYPE **fromEndPtr,
1169 TARGET_TYPE *fromBegin,
1170 TARGET_TYPE *fromEnd,
1171 size_type numElements,
1172 bslma::Allocator *allocator);
1173
1174 /// Move the elements of the parameterized `TARGET_TYPE` in the array
1175 /// starting at the specified `first` address and ending immediately
1176 /// before the specified `middle` address to the array of the same
1177 /// length ending at the specified `last` address (and thus starting at
1178 /// the `last - (middle - first)` address), and move the elements
1179 /// previously in the array starting at `middle` and ending at `last`
1180 /// down to the `first` address. If the assignment operator throws an
1181 /// exception during this process, all of the elements in
1182 /// `[ first, last )` will have unspecified, but valid, values.
1183 ///
1184 /// \pre The behavior is undefined unless `first <= middle <= last`.
1185 template <class TARGET_TYPE>
1186 static void rotate(TARGET_TYPE *first,
1187 TARGET_TYPE *middle,
1188 TARGET_TYPE *last);
1189
1190 /// TBD: improve comment
1191 /// Construct copies of the specified `value` of type given by the
1192 /// `allocator_traits` class template for (template parameter)
1193 /// `ALLOCATOR` into the uninitialized array containing the specified
1194 /// `numElements` starting at the specified `begin` location.
1195 ///
1196 /// \pre The behavior is undefined unless the output array contains at least
1197 /// `numElements` uninitialized elements after `begin`. If a
1198 /// constructor throws an exception during the operation, then the
1199 /// destructor is called on any newly-constructed elements, leaving the
1200 /// output array in an uninitialized state.
1201 template <class ALLOCATOR>
1202 static void uninitializedFillN(
1204 size_type numElements,
1206 ALLOCATOR allocator);
1207
1208 /// Construct copies of the specified `value` of the parameterized type
1209 /// `TARGET_TYPE` into the uninitialized array containing the specified
1210 /// `numElements` starting at the specified `begin` address. If the
1211 /// (template parameter) `ALLOCATOR` type is derived from
1212 /// `bslma::Allocator` and `TARGET_TYPE` supports `bslma` allocators,
1213 /// then the specified `allocator` is passed to each invocation of the `TARGET_TYPE` copy constructor.
1214 ///
1215 /// \pre The behavior is undefined unless
1216 /// the output array contains at least `numElements` uninitialized
1217 /// elements after `begin`. If a `TARGET_TYPE` constructor throws an
1218 /// exception during the operation, then the destructor is called on any
1219 /// newly-constructed elements, leaving the output array in an uninitialized state.
1220 ///
1221 /// \note Note that the argument order was chosen to
1222 /// maintain compatibility with the existing `bslalg`.
1223 template <class TARGET_TYPE>
1224 static void uninitializedFillN(TARGET_TYPE *begin,
1225 size_type numElements,
1226 const TARGET_TYPE& value,
1227 bslma::Allocator *allocator);
1228};
1229
1230 // ==========================
1231 // struct ArrayPrimitives_Imp
1232 // ==========================
1233
1234/// This `struct` provides a namespace for a suite of independent utility
1235/// functions that operate on arrays of elements of a parameterized
1236/// `TARGET_TYPE`. These utility functions are only for the purpose of
1237/// implementing those in the `ArrayPrimitives` utility. For brevity, we do
1238/// not repeat the main contracts here, but instead refer to the
1239/// corresponding contract in the `ArrayPrimitives` utility.
1240///
1241/// See @ref bslalg_arrayprimitives
1243
1244 private:
1245 // PRIVATE METHODS
1246
1247 /// Copy-assign the specified `value` to the range starting at the
1248 /// specified `srcStart` and ending immediately before the specified `srcEnd`.
1249 ///
1250 /// \note Note that the (template parameter) `TARGET_TYPE` must be
1251 /// copy-assignable. Also note that `value` should not be an element in
1252 /// the range `[srcStart, srcEnd)`.
1253 template <class TARGET_TYPE>
1254 static void assign(TARGET_TYPE *srcStart,
1255 TARGET_TYPE *srcEnd,
1256 TARGET_TYPE& value);
1257
1258 /// Copy-assign the elements in reverse order from the range starting at
1259 /// the specified `srcStart` and ending immediately before the specified
1260 /// `srcEnd` to the range starting at the specified `dest` and ending
1261 /// immediately before `dest + (srcEnd - srcStart)`.
1262 ///
1263 /// \pre The behavior is undefined unless each element is both range `[srcStart, srcEnd)` and range `[dest, dest + (srcEnd - srcStart))` is valid.
1264 ///
1265 /// \note Note that the
1266 /// (template parameter) `TARGET_TYPE` must be copy-assignable. Also
1267 /// note that this method is intended to support range assignment when
1268 /// the two ranges may be overlapped, and `srcStart <= dest`.
1269 template <class TARGET_TYPE>
1270 static void reverseAssign(TARGET_TYPE *dest,
1271 TARGET_TYPE *srcStart,
1272 TARGET_TYPE *srcEnd);
1273
1274 public:
1275 // TYPES
1278
1279 enum {
1280 // These constants are used in the overloads below, when the last
1281 // argument is of type 'bslmf::integral_constant<int,N>', indicating
1282 // that 'TARGET_TYPE' has the traits for which the enumerator equal to
1283 // 'N' is named.
1284
1291 e_NIL_TRAITS = 0
1293
1294 enum {
1295 // Number of bytes for which a stack-allocated buffer can be
1296 // comfortably obtained to optimize bitwise moves.
1297
1300
1301 // CLASS METHODS
1302
1303 /// Fill the specified `numBytes` in the array starting at the specified
1304 /// `begin` address, as if by bit-wise copying the specified
1305 /// `numBytesInitialized` at every offset that is a multiple of
1306 /// `numBytesInitialized` within the output array.
1307 ///
1308 /// \pre The behavior is undefined unless `numBytesInitialized <= numBytes`.
1309 ///
1310 /// \note Note that `numBytes` usually is, but does not have to be, a multiple of
1311 /// `numBytesInitialized`.
1312 static void bitwiseFillN(char *begin,
1313 size_type numBytesInitialized,
1314 size_type numBytes);
1315
1316 /// Copy the specified `value` of the parameterized `TARGET_TYPE` into
1317 /// every of the specified `numElements` in the array starting at the
1318 /// specified `begin` address. Pass the specified `allocator` to the copy constructor if appropriate.
1319 ///
1320 /// \note Note that if `TARGET_TYPE` is
1321 /// bit-wise copyable or is not based on `bslma::Allocator`, `allocator`
1322 /// is ignored. The last argument is for removing overload ambiguities
1323 /// and is not used.
1324 static void uninitializedFillN(
1325 bool *begin,
1326 bool value,
1327 size_type numElements,
1328 void * = 0,
1331 static void uninitializedFillN(
1332 char *begin,
1333 char value,
1334 size_type numElements,
1335 void * = 0,
1338 static void uninitializedFillN(
1339 unsigned char *begin,
1340 unsigned char value,
1341 size_type numElements,
1342 void * = 0,
1345 static void uninitializedFillN(
1346 signed char *begin,
1347 signed char value,
1348 size_type numElements,
1349 void * = 0,
1352 static void uninitializedFillN(
1353 wchar_t *begin,
1354 wchar_t value,
1355 size_type numElements,
1356 void * = 0,
1360 short *begin,
1361 short value,
1362 size_type numElements,
1363 void * = 0,
1366 static void uninitializedFillN(
1367 unsigned short *begin,
1368 unsigned short value,
1369 size_type numElements,
1370 void * = 0,
1374 int *begin,
1375 int value,
1376 size_type numElements,
1377 void * = 0,
1380 static void uninitializedFillN(
1381 unsigned int *begin,
1382 unsigned int value,
1383 size_type numElements,
1384 void * = 0,
1387 static void uninitializedFillN(
1388 long *begin,
1389 long value,
1390 size_type numElements,
1391 void * = 0,
1394 static void uninitializedFillN(
1395 unsigned long *begin,
1396 unsigned long value,
1397 size_type numElements,
1398 void * = 0,
1402 bsls::Types::Int64 *begin,
1403 bsls::Types::Int64 value,
1404 size_type numElements,
1405 void * = 0,
1408 static void uninitializedFillN(
1409 bsls::Types::Uint64 *begin,
1410 bsls::Types::Uint64 value,
1411 size_type numElements,
1412 void * = 0,
1416 float *begin,
1417 float value,
1418 size_type numElements,
1419 void * = 0,
1423 double *begin,
1424 double value,
1425 size_type numElements,
1426 void * = 0,
1430 long double *begin,
1431 long double value,
1432 size_type numElements,
1433 void * = 0,
1437 void **begin,
1438 void *value,
1439 size_type numElements,
1440 void * = 0,
1444 const void **begin,
1445 const void *value,
1446 size_type numElements,
1447 void * = 0,
1451 volatile void **begin,
1452 volatile void *value,
1453 size_type numElements,
1454 void * = 0,
1458 const volatile void **begin,
1459 const volatile void *value,
1460 size_type numElements,
1461 void * = 0,
1464 template <class TARGET_TYPE>
1465 static void uninitializedFillN(
1466 TARGET_TYPE **begin,
1467 TARGET_TYPE *value,
1468 size_type numElements,
1469 void * = 0,
1472 template <class TARGET_TYPE>
1473 static void uninitializedFillN(
1474 const TARGET_TYPE **begin,
1475 const TARGET_TYPE *value,
1476 size_type numElements,
1477 void * = 0,
1480 template <class TARGET_TYPE>
1481 static void uninitializedFillN(
1482 volatile TARGET_TYPE **begin,
1483 volatile TARGET_TYPE *value,
1484 size_type numElements,
1485 void * = 0,
1488 template <class TARGET_TYPE>
1489 static void uninitializedFillN(
1490 const volatile TARGET_TYPE **begin,
1491 const volatile TARGET_TYPE *value,
1492 size_type numElements,
1493 void * = 0,
1496 template <class TARGET_TYPE, class ALLOCATOR>
1497 static void uninitializedFillN(
1498 TARGET_TYPE *begin,
1499 const TARGET_TYPE& value,
1500 size_type numElements,
1501 ALLOCATOR *allocator,
1503 template <class TARGET_TYPE, class ALLOCATOR>
1504 static void uninitializedFillN(
1505 TARGET_TYPE *begin,
1506 const TARGET_TYPE& value,
1507 size_type numElements,
1508 ALLOCATOR *allocator,
1510
1511 /// These functions follow the `copyConstruct` contract. If the (template
1512 /// parameter) `ALLOCATOR` type is based on `bslma::Allocator` and the
1513 /// `TARGET_TYPE` constructors take an allocator argument, then pass the
1514 /// specified `allocator` to the copy constructor.
1515 ///
1516 /// \pre The behavior is undefined unless the output array has length at least the distance from the specified `fromBegin` to the specified `fromEnd`.
1517 ///
1518 /// \note Note that if
1519 /// `FWD_ITER` is the `TARGET_TYPE *` pointer type and `TARGET_TYPE` is
1520 /// bit-wise copyable, then this operation is simply `memcpy`. The last
1521 /// argument is for removing overload ambiguities and is not used.
1522 template <class TARGET_TYPE,
1523 class FWD_ITER,
1524 class SENTINEL,
1525 class ALLOCATOR>
1526 static void copyConstruct(
1527 TARGET_TYPE *toBegin,
1528 FWD_ITER fromBegin,
1529 SENTINEL fromEnd,
1530 ALLOCATOR allocator,
1532 template <class TARGET_TYPE, class ALLOCATOR>
1533 static void copyConstruct(
1534 TARGET_TYPE *toBegin,
1535 const TARGET_TYPE *fromBegin,
1536 const TARGET_TYPE *fromEnd,
1537 ALLOCATOR allocator,
1539 template <class TARGET_TYPE,
1540 class FWD_ITER,
1541 class SENTINEL,
1542 class ALLOCATOR>
1543 static void copyConstruct(
1544 TARGET_TYPE *toBegin,
1545 FWD_ITER fromBegin,
1546 SENTINEL fromEnd,
1547 ALLOCATOR allocator,
1549 template <class FWD_ITER, class SENTINEL, class ALLOCATOR>
1550 static void copyConstruct(
1551 void **toBegin,
1552 FWD_ITER fromBegin,
1553 SENTINEL fromEnd,
1554 ALLOCATOR allocator,
1556 template <class TARGET_TYPE,
1557 class FWD_ITER,
1558 class SENTINEL,
1559 class ALLOCATOR>
1560 static void copyConstruct(
1561 TARGET_TYPE *toBegin,
1562 FWD_ITER fromBegin,
1563 SENTINEL fromEnd,
1564 ALLOCATOR allocator,
1566
1567 /// TBD: improve comment
1568 /// Move-insert into an uninitialized array beginning at the specified
1569 /// `toBegin` pointer, elements of type given by the `allocator_traits`
1570 /// class template for (template parameter) `ALLOCATOR` from elements
1571 /// starting at the specified `fromBegin` pointer and ending immediately
1572 /// before the specified `fromEnd` pointer. The elements in the range
1573 /// `[fromBegin...fromEnd)` are left in a valid but unspecified state.
1574 /// If a constructor throws an exception during the operation, then the
1575 /// destructor is called on any newly-constructed elements, leaving the
1576 /// output array in an uninitialized state.
1577 ///
1578 /// \pre The behavior is undefined unless `toBegin` refers to space sufficient to hold
1579 /// `fromEnd - fromBegin` elements.
1580 template <class TARGET_TYPE, class ALLOCATOR>
1581 static void moveConstruct(
1582 TARGET_TYPE *toBegin,
1583 TARGET_TYPE *fromBegin,
1584 TARGET_TYPE *fromEnd,
1585 ALLOCATOR allocator,
1587 template <class TARGET_TYPE, class ALLOCATOR>
1588 static void moveConstruct(
1589 TARGET_TYPE *toBegin,
1590 TARGET_TYPE *fromBegin,
1591 TARGET_TYPE *fromEnd,
1592 ALLOCATOR allocator,
1594
1595 /// TBD: improve comment
1596 /// Either move- or copy-insert into an uninitialized array beginning at
1597 /// the specified `toBegin` pointer, elements of type given by the
1598 /// `allocator_traits` class template for (template parameter)
1599 /// `ALLOCATOR` from elements starting at the specified `fromBegin`
1600 /// pointer and ending immediately before the specified `fromEnd`
1601 /// pointer. The elements in the range `[fromBegin...fromEnd)` are left
1602 /// in a valid but unspecified state. Use the move constructor if it is
1603 /// guaranteed to not throw or if the target type does not define a copy
1604 /// constructor; otherwise use the copy constructor. If a constructor
1605 /// throws an exception during the operation, then the destructor is
1606 /// called on any newly-constructed elements, leaving the output array in an uninitialized state.
1607 ///
1608 /// \pre The behavior is undefined unless
1609 /// `toBegin` refers to space sufficient to hold `fromEnd - fromBegin`
1610 /// elements.
1611 template <class TARGET_TYPE, class ALLOCATOR>
1612 static void moveIfNoexcept(
1613 TARGET_TYPE *toBegin,
1614 TARGET_TYPE *fromBegin,
1615 TARGET_TYPE *fromEnd,
1616 ALLOCATOR allocator,
1618
1619 /// Use the default constructor of the (template parameter)
1620 /// `TARGET_TYPE` (or `memset` to 0 if `TARGET_TYPE` has a trivial
1621 /// default constructor) on each element of the array starting at the
1622 /// specified `begin` address and ending immediately before the `end`
1623 /// address. Pass the specified `allocator` to the default constructor
1624 /// if appropriate. The last argument is for traits overloading
1625 /// resolution only and its value is ignored.
1626 template <class TARGET_TYPE, class ALLOCATOR>
1627 static void defaultConstruct(
1628 TARGET_TYPE *begin,
1629 size_type numElements,
1630 ALLOCATOR allocator,
1632 template <class TARGET_TYPE, class ALLOCATOR>
1633 static void defaultConstruct(
1634 TARGET_TYPE *begin,
1635 size_type numElements,
1636 ALLOCATOR allocator,
1638 template <class TARGET_TYPE, class ALLOCATOR>
1639 static void defaultConstruct(
1640 TARGET_TYPE *begin,
1641 size_type numElements,
1642 ALLOCATOR allocator,
1644
1645 /// These functions follow the `destructiveMove` contract.
1646 ///
1647 /// \note Note that both arrays cannot overlap (one contains only initialized elements
1648 /// and the other only uninitialized elements), and that if
1649 /// `TARGET_TYPE` is bit-wise moveable, then this operation is simply
1650 /// `memcpy`. The last argument is for removing overload ambiguities
1651 /// and is not used.
1652 template <class TARGET_TYPE, class ALLOCATOR>
1653 static void destructiveMove(
1654 TARGET_TYPE *toBegin,
1655 TARGET_TYPE *fromBegin,
1656 TARGET_TYPE *fromEnd,
1657 ALLOCATOR allocator,
1659 template <class TARGET_TYPE, class ALLOCATOR>
1660 static void destructiveMove(
1661 TARGET_TYPE *toBegin,
1662 TARGET_TYPE *fromBegin,
1663 TARGET_TYPE *fromEnd,
1664 ALLOCATOR allocator,
1666
1667#if !BSLS_COMPILERFEATURES_SIMULATE_CPP11_FEATURES
1668 /// TBD: document this
1669 template <class TARGET_TYPE, class ALLOCATOR, class... ARGS>
1670 static void emplace(
1671 TARGET_TYPE *toBegin,
1672 TARGET_TYPE *toEnd,
1673 ALLOCATOR allocator,
1675 ARGS&&... args);
1676 template <class TARGET_TYPE, class ALLOCATOR, class... ARGS>
1677 static void emplace(
1678 TARGET_TYPE *toBegin,
1679 TARGET_TYPE *toEnd,
1680 ALLOCATOR allocator,
1682 ARGS&&... args);
1683 template <class TARGET_TYPE, class ALLOCATOR, class... ARGS>
1684 static void emplace(
1685 TARGET_TYPE *toBegin,
1686 TARGET_TYPE *toEnd,
1687 ALLOCATOR allocator,
1689 ARGS&&... args);
1690#endif
1691
1692 /// These functions follow the `erase` contract.
1693 /// \note Note that if (template
1694 /// parameter) `TARGET_TYPE` is bit-wise moveable, then this operation
1695 /// can be implemented by first bit-wise moving the elements in
1696 /// `[middle, last)` towards first, and destroying
1697 /// `[ last - (middle - first), last)`; note that this cannot throw
1698 /// exceptions.
1699 template <class TARGET_TYPE, class ALLOCATOR>
1700 static void erase(
1701 TARGET_TYPE *first,
1702 TARGET_TYPE *middle,
1703 TARGET_TYPE *last,
1704 ALLOCATOR allocator,
1706 template <class TARGET_TYPE, class ALLOCATOR>
1707 static void erase(
1708 TARGET_TYPE *first,
1709 TARGET_TYPE *middle,
1710 TARGET_TYPE *last,
1711 ALLOCATOR allocator,
1713
1714 /// These functions follow the `insert` contract.
1715 /// \note Note that if
1716 /// `TARGET_TYPE` is bit-wise copyable, then this operation is simply
1717 /// `memmove` followed by `bitwiseFillN`. If `TARGET_TYPE` is bit-wise
1718 /// moveable, then this operation can still be optimized using `memmove`
1719 /// followed by repeated assignments, but a guard needs to be set up.
1720 /// The last argument is for removing overload ambiguities and is not
1721 /// used.
1722 template <class TARGET_TYPE, class ALLOCATOR>
1723 static void insert(
1724 TARGET_TYPE *toBegin,
1725 TARGET_TYPE *toEnd,
1726 const TARGET_TYPE& value,
1727 size_type numElements,
1728 ALLOCATOR allocator,
1730 template <class TARGET_TYPE, class ALLOCATOR>
1731 static void insert(
1732 TARGET_TYPE *toBegin,
1733 TARGET_TYPE *toEnd,
1734 const TARGET_TYPE& value,
1735 size_type numElements,
1736 ALLOCATOR allocator,
1738 template <class TARGET_TYPE, class ALLOCATOR>
1739 static void insert(
1740 TARGET_TYPE *toBegin,
1741 TARGET_TYPE *toEnd,
1742 const TARGET_TYPE& value,
1743 size_type numElements,
1744 ALLOCATOR allocator,
1746
1747 /// These functions follow the `insert` contract.
1748 /// \note Note that if
1749 /// `TARGET_TYPE` is bit-wise copyable and `FWD_ITER` is convertible to
1750 /// `const TARGET_TYPE *`, then this operation is simply `memmove`
1751 /// followed by `memcpy`. If `TARGET_TYPE` is bit-wise moveable and
1752 /// `FWD_ITER` is convertible to `const TARGET_TYPE *`, then this
1753 /// operation can still be optimized using `memmove` followed by
1754 /// repeated copies. The last argument is for removing overload
1755 /// ambiguities and is not used.
1756 template <class TARGET_TYPE,
1757 class FWD_ITER,
1758 class SENTINEL,
1759 class ALLOCATOR>
1760 static void insert(
1761 TARGET_TYPE *toBegin,
1762 TARGET_TYPE *toEnd,
1763 FWD_ITER fromBegin,
1764 SENTINEL fromEnd,
1765 size_type numElements,
1766 ALLOCATOR allocator,
1768 template <class TARGET_TYPE, class ALLOCATOR>
1769 static void insert(
1770 TARGET_TYPE *toBegin,
1771 TARGET_TYPE *toEnd,
1772 const TARGET_TYPE *fromBegin,
1773 const TARGET_TYPE *fromEnd,
1774 size_type numElements,
1775 ALLOCATOR allocator,
1777 template <class TARGET_TYPE,
1778 class FWD_ITER,
1779 class SENTINEL,
1780 class ALLOCATOR>
1781 static void insert(
1782 TARGET_TYPE *toBegin,
1783 TARGET_TYPE *toEnd,
1784 FWD_ITER fromBegin,
1785 SENTINEL fromEnd,
1786 size_type numElements,
1787 ALLOCATOR allocator,
1789 template <class FWD_ITER, class SENTINEL, class ALLOCATOR>
1790 static void insert(
1791 void **toBegin,
1792 void **toEnd,
1793 FWD_ITER fromBegin,
1794 SENTINEL fromEnd,
1795 size_type numElements,
1796 ALLOCATOR allocator,
1798 template <class TARGET_TYPE,
1799 class FWD_ITER,
1800 class SENTINEL,
1801 class ALLOCATOR>
1802 static void insert(
1803 TARGET_TYPE *toBegin,
1804 TARGET_TYPE *toEnd,
1805 FWD_ITER fromBegin,
1806 SENTINEL fromEnd,
1807 size_type numElements,
1808 ALLOCATOR allocator,
1810
1811 /// These functions follow the `moveInsert` contract.
1812 /// \note Note that if
1813 /// `TARGET_TYPE` is at least bit-wise moveable, then this operation is
1814 /// simply `memmove` followed by `memcpy`.
1815 template <class TARGET_TYPE, class ALLOCATOR>
1816 static void moveInsert(
1817 TARGET_TYPE *toBegin,
1818 TARGET_TYPE *toEnd,
1819 TARGET_TYPE **lastPtr,
1820 TARGET_TYPE *first,
1821 TARGET_TYPE *last,
1822 size_type numElements,
1823 ALLOCATOR allocator,
1825 template <class TARGET_TYPE, class ALLOCATOR>
1826 static void moveInsert(
1827 TARGET_TYPE *toBegin,
1828 TARGET_TYPE *toEnd,
1829 TARGET_TYPE **lastPtr,
1830 TARGET_TYPE *first,
1831 TARGET_TYPE *last,
1832 size_type numElements,
1833 ALLOCATOR allocator,
1835
1836 /// These functions follow the `rotate` contract, but the first overload
1837 /// is optimized when the parameterized `TARGET_TYPE` is bit-wise
1838 /// moveable. The last argument is for removing overload ambiguities and is not used.
1839 ///
1840 /// \note Note that if `TARGET_TYPE` is bit-wise moveable,
1841 /// the `rotate(char*, char*, char*)` can be used, enabling to take the
1842 /// whole implementation out-of-line.
1843 template <class TARGET_TYPE>
1844 static void rotate(
1845 TARGET_TYPE *begin,
1846 TARGET_TYPE *middle,
1847 TARGET_TYPE *end,
1849 template <class TARGET_TYPE>
1850 static void rotate(
1851 TARGET_TYPE *begin,
1852 TARGET_TYPE *middle,
1853 TARGET_TYPE *end,
1855
1856 /// Shift the specified `[begin, end)` sequence one position right, then
1857 /// insert the specified `value` at the position pointed by `begin`.
1858 /// The specified `allocator` is used for the element construction.
1859 ///
1860 /// \pre The behavior is undefined unless the specified `[begin, end)` sequence
1861 /// contains at least one element.
1862 template <class ALLOCATOR>
1863 static void shiftAndInsert(
1868 ALLOCATOR allocator,
1870 template <class ALLOCATOR>
1871 static void shiftAndInsert(
1876 ALLOCATOR allocator,
1878 template <class ALLOCATOR>
1879 static void shiftAndInsert(
1884 ALLOCATOR allocator,
1886
1887 // 'bitwise' METHODS
1888
1889 /// This function follows the `rotate` contract, but by using bit-wise
1890 /// moves on the underlying `char` array.
1891 static void bitwiseRotate(char *begin, char *middle, char *end);
1892
1893 /// Move the characters in the array starting at the specified `first`
1894 /// address and ending immediately before the specified `middle` address
1895 /// to the array of the same length ending at the specified `last`
1896 /// address (and thus starting at the `last - (middle - first)`
1897 /// address), and move the elements previously in the array starting at
1898 /// `middle` and ending at `last` down to the `first` address.
1899 ///
1900 /// \pre The behavior is undefined unless
1901 /// `middle - begin <= k_INPLACE_BUFFER_SIZE`.
1902 static void bitwiseRotateBackward(char *begin, char *middle, char *end);
1903
1904 /// Move the characters in the array starting at the specified `first`
1905 /// address and ending immediately before the specified `middle` address
1906 /// to the array of the same length ending at the specified `last`
1907 /// address (and thus starting at the `last - (middle - first)`
1908 /// address), and move the elements previously in the array starting at
1909 /// `middle` and ending at `last` down to the `first` address.
1910 ///
1911 /// \pre The behavior is undefined unless
1912 /// `end - middle <= k_INPLACE_BUFFER_SIZE`.
1913 static void bitwiseRotateForward(char *begin, char *middle, char *end);
1914
1915 /// Swap the characters in the array starting at the specified `first`
1916 /// address and ending immediately before the specified `middle` address
1917 /// with the array of the same length starting at the `middle` address
1918 /// and ending at the specified `last` address.
1919 ///
1920 /// \pre The behavior is undefined unless `middle - begin == end - middle`.
1921 static void bitwiseSwapRanges(char *begin, char *middle, char *end);
1922
1923 /// Return `true` if the specified `begin` and the specified `end`
1924 /// provably do not form a valid semi-open range, `[begin, end)`, and `false` otherwise.
1925 ///
1926 /// \note Note that `begin == null == end` produces a
1927 /// valid range, and any other use of the null pointer value will return
1928 /// `true`. Also note that this function is intended to support
1929 /// testing, primarily through assertions, so will return `false` unless
1930 /// it can *prove* that the passed range is invalid. Currently, this
1931 /// function can prove invalid ranges only for pointers, although should
1932 /// also encompass generic random access iterators in a future update,
1933 /// where iterator tag types are levelized below `bslalg`.
1934 template <class FORWARD_ITERATOR, class SENTINEL>
1935 static bool isInvalidRange(FORWARD_ITERATOR begin, SENTINEL end);
1936 template <class TARGET_TYPE>
1937 static bool isInvalidRange(TARGET_TYPE *begin, TARGET_TYPE *end);
1938};
1939
1940// ============================================================================
1941// INLINE FUNCTION DEFINITIONS
1942// ============================================================================
1943// IMPLEMENTATION NOTES: Specializations of 'uninitializedFillN' for most
1944// fundamental types are not templates nor inline, and thus can be found in the
1945// '.cpp' file.
1946
1947 // =====================================
1948 // struct ArrayPrimitives_CanBitwiseCopy
1949 // =====================================
1950
1951template <class FROM_TYPE, class TO_TYPE>
1954 bsl::is_same<
1955 typename bsl::remove_const<FROM_TYPE>::type,
1956 typename bsl::remove_const<TO_TYPE >::type>
1957 ::value
1958 && bslmf::IsBitwiseCopyable<
1959 typename bsl::remove_const<TO_TYPE >::type>
1960 ::value
1961 > {
1962};
1963
1964 // ----------------------
1965 // struct ArrayPrimitives
1966 // ----------------------
1967
1968template <class ALLOCATOR>
1969inline
1972 size_type numElements,
1974 ALLOCATOR allocator)
1975{
1976 BSLS_ASSERT_SAFE(begin || 0 == numElements);
1978
1979 typedef typename bsl::allocator_traits<ALLOCATOR>::value_type TargetType;
1980
1981 enum {
1982 // We provide specialized overloads of 'uninitializedFillN' for
1983 // fundamental and pointer types. However, function pointers can have
1984 // extern "C" linkage and SunPro doesn't match them properly with the
1985 // pointer template function overload in 'Imp', so we resort to the
1986 // general case for those.
1987
1988 k_IS_FUNCTION_POINTER = bslmf::IsFunctionPointer<TargetType>::value,
1989 k_IS_FUNDAMENTAL = bsl::is_fundamental<TargetType>::value,
1991
1992 k_IS_FUNDAMENTAL_OR_POINTER = k_IS_FUNDAMENTAL ||
1993 (k_IS_POINTER && !k_IS_FUNCTION_POINTER),
1994
1995 k_IS_BITWISECOPYABLE = bslmf::IsBitwiseCopyable<TargetType>::value,
1996
1997 k_VALUE =
1998 k_IS_FUNDAMENTAL_OR_POINTER ? Imp::e_IS_FUNDAMENTAL_OR_POINTER
1999 : k_IS_BITWISECOPYABLE ? Imp::e_BITWISE_COPYABLE_TRAITS
2001 };
2003 begin,
2004 value,
2005 numElements,
2006 &allocator,
2008}
2009
2010template <class TARGET_TYPE>
2011inline
2013 size_type numElements,
2014 const TARGET_TYPE& value,
2015 bslma::Allocator *basicAllocator)
2016{
2017 uninitializedFillN<bsl::allocator<TARGET_TYPE> >(begin,
2018 numElements,
2019 value,
2020 basicAllocator);
2021}
2022
2023template <class ALLOCATOR, class FWD_ITER, class SENTINEL>
2026 FWD_ITER fromBegin,
2027 SENTINEL fromEnd,
2028 ALLOCATOR allocator)
2029{
2030 BSLS_ASSERT_SAFE(toBegin || fromBegin == fromEnd);
2031
2033 typedef typename bsl::allocator_traits<ALLOCATOR>::value_type TargetType;
2034
2035 /// Overload resolution will handle the case where `FWD_ITER` is a raw
2036 /// pointer, so we need handle only user-defined iterators. As `bslalg`
2037 /// is levelized below `bslstl` we cannot use `iterator_traits`, but
2038 /// rely on the same property as `iterator_traits` that this typedef
2039 /// must be defined for any standard-conforming iterator, unless the
2040 /// iterator explicitly specialized the `std::iterator_traits` template.
2041 /// In practice, iterators always prefer to provide the member typedef
2042 /// than specialize the traits as it is a much simpler implementation,
2043 /// so this assumption is good enough.
2044 ///
2045 /// Also note that as we know that `FWD_ITER` is not a pointer, then we
2046 /// cannot take advantage of bitwise copying as we do not have pointers
2047 /// to pass to the `memcpy` describing the whole range. It is not worth
2048 /// the effort to try to bitwise copy one element at a time.
2049 typedef typename FWD_ITER::value_type FwdTarget;
2050
2051 /// We want to detect the special case of copying function pointers to
2052 /// `void *` or `const void *` pointers.
2053 typedef typename bsl::remove_pointer<TargetType>::type RemovePtrTarget;
2054
2055 enum {
2056 k_ITER_TO_FUNC_PTRS = bslmf::IsFunctionPointer<FwdTarget>::value,
2057 k_TARGET_IS_VOID_PTR = bsl::is_pointer<TargetType>::value &&
2059
2060 k_VALUE = k_ITER_TO_FUNC_PTRS && k_TARGET_IS_VOID_PTR
2063 };
2064
2066 fromBegin,
2067 fromEnd,
2068 allocator,
2070}
2071
2072template <class TARGET_TYPE, class FWD_ITER, class SENTINEL>
2073inline
2074void ArrayPrimitives::copyConstruct(TARGET_TYPE *toBegin,
2075 FWD_ITER fromBegin,
2076 SENTINEL fromEnd,
2077 bslma::Allocator *basicAllocator)
2078{
2079 copyConstruct<bsl::allocator<TARGET_TYPE> >(toBegin,
2080 fromBegin,
2081 fromEnd,
2082 basicAllocator);
2083}
2084
2085template <class ALLOCATOR, class SOURCE_TYPE>
2086inline
2089 SOURCE_TYPE *fromBegin,
2090 SOURCE_TYPE *fromEnd,
2091 ALLOCATOR allocator)
2092{
2093 BSLS_ASSERT_SAFE(toBegin || fromBegin == fromEnd);
2094
2095 typedef typename bsl::allocator_traits<ALLOCATOR>::value_type TargetType;
2096
2097 enum {
2098 k_ARE_PTRS_TO_PTRS = bsl::is_pointer<TargetType>::value &&
2100 k_IS_BITWISECOPYABLE =
2102 k_VALUE = k_ARE_PTRS_TO_PTRS ? Imp::e_IS_POINTER_TO_POINTER
2103 : k_IS_BITWISECOPYABLE ? Imp::e_BITWISE_COPYABLE_TRAITS
2105 };
2106
2108 fromBegin,
2109 fromEnd,
2110 allocator,
2112}
2113
2114template <class TARGET_TYPE, class SOURCE_TYPE>
2115inline
2116void ArrayPrimitives::copyConstruct(TARGET_TYPE *toBegin,
2117 SOURCE_TYPE *fromBegin,
2118 SOURCE_TYPE *fromEnd,
2119 bslma::Allocator *basicAllocator)
2120{
2121 copyConstruct<bsl::allocator<TARGET_TYPE> >(toBegin,
2122 fromBegin,
2123 fromEnd,
2124 basicAllocator);
2125}
2126
2127template <class ALLOCATOR>
2128inline
2131 size_type numElements,
2132 ALLOCATOR allocator)
2133{
2135 BSLS_ASSERT_SAFE(begin || 0 == numElements);
2136
2137 typedef typename bsl::allocator_traits<ALLOCATOR>::value_type TargetType;
2138
2139 enum {
2143#if !defined(BSLALG_ARRAYPRIMITIVES_NON_ZERO_NULL_VALUE_FOR_MEMBER_POINTERS)
2145#endif
2151 };
2153 begin,
2154 numElements,
2155 allocator,
2157}
2158
2159template <class TARGET_TYPE>
2160inline
2162 size_type numElements,
2163 bslma::Allocator *basicAllocator)
2164{
2165 defaultConstruct<bsl::allocator<TARGET_TYPE> >(begin,
2166 numElements,
2167 basicAllocator);
2168}
2169
2170template <class ALLOCATOR>
2171inline
2176 ALLOCATOR allocator)
2177{
2178 BSLS_ASSERT_SAFE(toBegin || fromBegin == fromEnd);
2180
2181 typedef typename bsl::allocator_traits<ALLOCATOR>::value_type TargetType;
2182
2183 enum {
2187 };
2189 toBegin,
2190 fromBegin,
2191 fromEnd,
2192 allocator,
2194}
2195
2196template <class TARGET_TYPE>
2197inline
2198void ArrayPrimitives::destructiveMove(TARGET_TYPE *toBegin,
2199 TARGET_TYPE *fromBegin,
2200 TARGET_TYPE *fromEnd,
2201 bslma::Allocator *basicAllocator)
2202{
2203 destructiveMove<bsl::allocator<TARGET_TYPE> >(toBegin,
2204 fromBegin,
2205 fromEnd,
2206 basicAllocator);
2207}
2208
2209#if !BSLS_COMPILERFEATURES_SIMULATE_CPP11_FEATURES // $var-args=10
2210template <class ALLOCATOR, class... ARGS>
2213 typename bsl::allocator_traits<ALLOCATOR>::pointer *fromEndPtr,
2217 ALLOCATOR allocator,
2218 ARGS&&... arguments)
2219{
2220 // Key to the transformation diagrams:
2221 //..
2222 // A...H original contents of '[fromBegin, fromEnd)' ("source")
2223 // v...v default-constructed values ("input")
2224 // ; ... contents of '[toBegin, toEnd)' ("destination")
2225 // ..:.. position of 'fromEndPtr' in the input
2226 // _____ uninitialized array elements
2227 // [...] part of array protected by an exception guard object
2228 //..
2229
2230 typedef typename bsl::allocator_traits<ALLOCATOR>::value_type TargetType;
2231
2232 *fromEndPtr = fromEnd;
2233
2234 // Note: Construct new element.
2235 //..
2236 // Transformation: ABCDEFGH: ; ___________[]
2237 // => ABCDEFGH: ; ____[v]____
2238 //..
2239
2240 TargetType *toPositionBegin = toBegin + (position - fromBegin);
2241
2243 allocator,
2244 toPositionBegin,
2245 BSLS_COMPILERFEATURES_FORWARD(ARGS,arguments)...);
2246
2247 TargetType *toPositionEnd = toPositionBegin + 1;
2248
2249 AutoArrayDestructor<TargetType, ALLOCATOR> guard(toPositionBegin,
2250 toPositionEnd,
2251 allocator);
2252
2253 //..
2254 // Transformation: ABCDEFGH: ; ____[v]____
2255 // => ABCD:____ ; ____[vEFGH]
2256 //..
2257
2258 destructiveMove(toPositionEnd,
2259 position,
2260 fromEnd,
2261 allocator);
2262
2263 *fromEndPtr = position; // shorten input range after partial destruction
2264 guard.moveEnd(fromEnd - position); // toEnd
2265
2266 //..
2267 // Transformation: ABCD:____ ; ____[vEFGH]
2268 // => :________ ; ABCDvEFGH[]
2269 //..
2270
2271 destructiveMove(toBegin,
2272 fromBegin,
2273 position,
2274 allocator);
2275
2276 *fromEndPtr = fromBegin; // empty input range after final destruction
2277 guard.release();
2278}
2279#endif
2280
2281template <class ALLOCATOR>
2284 typename bsl::allocator_traits<ALLOCATOR>::pointer *fromEndPtr,
2288 size_type numElements,
2289 ALLOCATOR allocator)
2290{
2291 // Key to the transformation diagrams:
2292 //..
2293 // A...H original contents of '[fromBegin, fromEnd)' ("source")
2294 // v...v default-constructed values ("input")
2295 // ; ... contents of '[toBegin, toEnd)' ("destination")
2296 // ..:.. position of 'fromEndPtr' in the input
2297 // _____ uninitialized array elements
2298 // [...] part of array protected by an exception guard object
2299 //..
2300
2301 typedef typename bsl::allocator_traits<ALLOCATOR>::value_type TargetType;
2302
2303 *fromEndPtr = fromEnd;
2304
2305 // Note: Construct default values.
2306 //..
2307 // Transformation: ABCDEFGH: ; _____________[]
2308 // => ABCDEFGH: ; ____[vvvvv]____
2309 //..
2310
2311 TargetType *toPositionBegin = toBegin + (position - fromBegin);
2312 defaultConstruct(toPositionBegin, numElements, allocator);
2313
2314 TargetType *toPositionEnd = toPositionBegin + numElements;
2315
2316 AutoArrayDestructor<TargetType, ALLOCATOR> guard(toPositionBegin,
2317 toPositionEnd,
2318 allocator);
2319
2320 //..
2321 // Transformation: ABCDEFGH: ; ____[vvvvv]____
2322 // => ABCD:____ ; ____[vvvvvEFGH]
2323 //..
2324
2325 destructiveMove(toPositionEnd,
2326 position,
2327 fromEnd,
2328 allocator);
2329
2330 *fromEndPtr = position; // shorten input range after partial destruction
2331 guard.moveEnd(fromEnd - position); // toEnd
2332
2333 //..
2334 // Transformation: ABCD:____ ; ____[vvvvvEFGH]
2335 // => :________ ; ABCDvvvvvEFGH[]
2336 //..
2337
2338 destructiveMove(toBegin,
2339 fromBegin,
2340 position,
2341 allocator);
2342
2343 *fromEndPtr = fromBegin; // empty input range after final destruction
2344 guard.release();
2345}
2346
2347template <class TARGET_TYPE>
2348inline
2350 TARGET_TYPE *toBegin,
2351 TARGET_TYPE **fromEndPtr,
2352 TARGET_TYPE *fromBegin,
2353 TARGET_TYPE *position,
2354 TARGET_TYPE *fromEnd,
2355 size_type numElements,
2356 bslma::Allocator *basicAllocator)
2357{
2358 destructiveMoveAndInsert<bsl::allocator<TARGET_TYPE> >(toBegin,
2359 fromEndPtr,
2360 fromBegin,
2361 position,
2362 fromEnd,
2363 numElements,
2364 basicAllocator);
2365}
2366
2367template <class ALLOCATOR>
2370 typename bsl::allocator_traits<ALLOCATOR>::pointer *fromEndPtr,
2375 size_type numElements,
2376 ALLOCATOR allocator)
2377{
2378 // Key to the transformation diagrams:
2379 //..
2380 // A...H original contents of '[fromBegin, fromEnd)' ("source")
2381 // v...v copies of 'value' ("input")
2382 // ; ... contents of '[toBegin, toEnd)' ("destination")
2383 // ..:.. position of 'fromEndPtr' in the input
2384 // _____ uninitialized array elements
2385 // [...] part of array protected by an exception guard object
2386 //..
2387
2388 typedef typename bsl::allocator_traits<ALLOCATOR>::value_type TargetType;
2389
2390 *fromEndPtr = fromEnd;
2391
2392 // Note: Construct copies of 'value' first in case 'value' is a reference
2393 // in the input range, which would be invalidated by any of the following
2394 // moves.
2395 //
2396 //..
2397 // Transformation: ABCDEFGH: ; _____________[]
2398 // => ABCDEFGH: ; ____[vvvvv]____
2399 //..
2400
2401 TargetType *toPositionBegin = toBegin + (position - fromBegin);
2402 uninitializedFillN(toPositionBegin, numElements, value, allocator);
2403
2404 TargetType *toPositionEnd = toPositionBegin + numElements;
2405
2406 AutoArrayDestructor<TargetType, ALLOCATOR> guard(toPositionBegin,
2407 toPositionEnd,
2408 allocator);
2409
2410 //..
2411 // Transformation: ABCDEFGH: ; ____[vvvvv]____
2412 // => ABCD:____ ; ____[vvvvvEFGH]
2413 //..
2414
2415 destructiveMove(toPositionEnd,
2416 position,
2417 fromEnd,
2418 allocator);
2419
2420 *fromEndPtr = position; // shorten input range after partial destruction
2421 guard.moveEnd(fromEnd - position); // toEnd
2422
2423 //..
2424 // Transformation: ABCD:____ ; ____[vvvvvEFGH]
2425 // => :________ ; ABCDvvvvvEFGH[]
2426 //..
2427
2428 destructiveMove(toBegin,
2429 fromBegin,
2430 position,
2431 allocator);
2432
2433 *fromEndPtr = fromBegin; // empty input range after final destruction
2434 guard.release();
2435}
2436
2437template <class TARGET_TYPE>
2439 TARGET_TYPE *toBegin,
2440 TARGET_TYPE **fromEndPtr,
2441 TARGET_TYPE *fromBegin,
2442 TARGET_TYPE *position,
2443 TARGET_TYPE *fromEnd,
2444 const TARGET_TYPE& value,
2445 size_type numElements,
2446 bslma::Allocator *basicAllocator)
2447{
2448 destructiveMoveAndInsert<bsl::allocator<TARGET_TYPE> >(toBegin,
2449 fromEndPtr,
2450 fromBegin,
2451 position,
2452 fromEnd,
2453 value,
2454 numElements,
2455 basicAllocator);
2456}
2457
2458template <class ALLOCATOR, class FWD_ITER, class SENTINEL>
2461 typename bsl::allocator_traits<ALLOCATOR>::pointer *fromEndPtr,
2465 FWD_ITER first,
2466 SENTINEL last,
2467 size_type numElements,
2468 ALLOCATOR allocator)
2469{
2470 // Key to the transformation diagrams:
2471 //..
2472 // A...H original contents of '[fromBegin, fromEnd)' ("source")
2473 // t...z original contents of '[first, last)' ("input")
2474 // ; ... contents of '[toBegin, toEnd)' ("destination")
2475 // ..:.. position of 'fromEndPtr' in the input
2476 // _____ uninitialized array elements
2477 // [...] part of array protected by an exception guard object
2478 //..
2479
2480 typedef typename bsl::allocator_traits<ALLOCATOR>::value_type TargetType;
2481
2482 *fromEndPtr = fromEnd;
2483
2484 // Note: Construct copies of 'value' first in case 'value' is a reference
2485 // in the input range, which would be invalidated by any of the following
2486 // moves:
2487 //..
2488 // Transformation: ABCDEFGH: ; _________[]____
2489 // => ABCDEFGH: ; ____[tuvxy]____
2490 //..
2491
2492 TargetType *toPositionBegin = toBegin + (position - fromBegin);
2493 copyConstruct(toPositionBegin, first, last, allocator);
2494
2495 TargetType *toPositionEnd = toPositionBegin + numElements;
2496
2497 AutoArrayDestructor<TargetType, ALLOCATOR> guard(toPositionBegin,
2498 toPositionEnd,
2499 allocator);
2500
2501 //..
2502 // Transformation: ABCDEFGH: ; ____[tuvxy]____
2503 // => ABCD:____ ; ____[tuvxyEFGH]
2504 //..
2505
2506 destructiveMove(toPositionEnd,
2507 position,
2508 fromEnd,
2509 allocator);
2510
2511 *fromEndPtr = position; // shorten input range after partial destruction
2512 guard.moveEnd(fromEnd - position); // toEnd
2513
2514 //..
2515 // Transformation: ABCD:____ ; ____[tuvxyEFGH]
2516 // => :________ ; ABCDtuvxyEFGH[]
2517 //..
2518
2519 destructiveMove(toBegin,
2520 fromBegin,
2521 position,
2522 allocator);
2523
2524 *fromEndPtr = fromBegin; // empty input range after final destruction
2525 guard.release();
2526}
2527
2528template <class TARGET_TYPE, class FWD_ITER, class SENTINEL>
2529inline
2531 TARGET_TYPE *toBegin,
2532 TARGET_TYPE **fromEndPtr,
2533 TARGET_TYPE *fromBegin,
2534 TARGET_TYPE *position,
2535 TARGET_TYPE *fromEnd,
2536 FWD_ITER first,
2537 SENTINEL last,
2538 size_type numElements,
2539 bslma::Allocator *basicAllocator)
2540{
2541 destructiveMoveAndInsert<bsl::allocator<TARGET_TYPE> >(toBegin,
2542 fromEndPtr,
2543 fromBegin,
2544 position,
2545 fromEnd,
2546 first,
2547 last,
2548 numElements,
2549 basicAllocator);
2550}
2551
2552template <class ALLOCATOR>
2555 typename bsl::allocator_traits<ALLOCATOR>::pointer *fromEndPtr,
2562 size_type numElements,
2563 ALLOCATOR allocator)
2564{
2565 // Key to the transformation diagrams:
2566 //..
2567 // A...H original contents of '[fromBegin, fromEnd)' ("source")
2568 // t...z original contents of '[first, last)' ("input")
2569 // ; ... contents of '[toBegin, toEnd)' ("destination")
2570 // ..:.. position of 'fromEndPtr' in the input
2571 // _____ uninitialized array elements
2572 // [...] part of array protected by an exception guard object
2573 //..
2574
2575 typedef typename bsl::allocator_traits<ALLOCATOR>::value_type TargetType;
2576
2577 *lastPtr = last;
2578 *fromEndPtr = fromEnd;
2579
2580 //..
2581 // Transformation: ABCDEFGH: ; _____________[]
2582 // => ABCD:____ ; _________[EFGH]
2583 //..
2584
2585 TargetType *toPositionBegin = toBegin + (position - fromBegin);
2586 TargetType *toPositionEnd = toPositionBegin + numElements;
2587
2588 destructiveMove(toPositionEnd,
2589 position,
2590 fromEnd,
2591 allocator);
2592
2593 *fromEndPtr = position; // shorten input range after partial destruction
2594
2596 guard(toPositionEnd,
2597 toPositionEnd + (fromEnd - position),
2598 allocator);
2599
2600 //..
2601 // Transformation: ABCD:____ ; _________[EFGH]
2602 // => ABCD:____ ; _____[tuvwEFGH]
2603 //..
2604
2605 destructiveMove(toPositionBegin,
2606 first,
2607 last,
2608 allocator);
2609
2610 *lastPtr = first;
2611 guard.moveBegin(-static_cast<difference_type>(numElements));
2612
2613 //..
2614 // Transformation: ABCD:____ ; ____[tuvwEFGH]
2615 // => :________ ; ABCDtuvwEFGH[]
2616 //..
2617
2618 destructiveMove(toBegin,
2619 fromBegin,
2620 position,
2621 allocator);
2622
2623 *fromEndPtr = fromBegin; // empty input range after final destruction
2624 guard.release();
2625}
2626
2627template <class TARGET_TYPE>
2628inline
2630 TARGET_TYPE *toBegin,
2631 TARGET_TYPE **fromEndPtr,
2632 TARGET_TYPE **lastPtr,
2633 TARGET_TYPE *fromBegin,
2634 TARGET_TYPE *position,
2635 TARGET_TYPE *fromEnd,
2636 TARGET_TYPE *first,
2637 TARGET_TYPE *last,
2638 size_type numElements,
2639 bslma::Allocator *basicAllocator)
2640{
2641 destructiveMoveAndMoveInsert<bsl::allocator<TARGET_TYPE> >(toBegin,
2642 fromEndPtr,
2643 lastPtr,
2644 fromBegin,
2645 position,
2646 fromEnd,
2647 first,
2648 last,
2649 numElements,
2650 basicAllocator);
2651}
2652
2653#if !BSLS_COMPILERFEATURES_SIMULATE_CPP11_FEATURES
2654template <class ALLOCATOR, class... ARGS>
2655inline
2659 ALLOCATOR allocator,
2660 ARGS&&... args)
2661{
2663 toEnd));
2665
2666 typedef typename bsl::allocator_traits<ALLOCATOR>::value_type TargetType;
2667
2668 enum {
2674 };
2675
2677 toBegin,
2678 toEnd,
2679 allocator,
2681 BSLS_COMPILERFEATURES_FORWARD(ARGS, args)...);
2682}
2683
2684template <class TARGET_TYPE, class... ARGS>
2685inline
2686void ArrayPrimitives::emplace(TARGET_TYPE *toBegin,
2687 TARGET_TYPE *toEnd,
2688 bslma::Allocator *basicAllocator,
2689 ARGS&&... args)
2690{
2691 emplace<bsl::allocator<TARGET_TYPE> >(
2692 toBegin,
2693 toEnd,
2694 basicAllocator,
2695 BSLS_COMPILERFEATURES_FORWARD(ARGS, args)...);
2696}
2697
2698#endif
2699
2700template <class ALLOCATOR>
2701inline
2706 ALLOCATOR allocator)
2707{
2710
2711 typedef typename bsl::allocator_traits<ALLOCATOR>::value_type TargetType;
2712
2713 if (first == middle) { // erasing empty range O(1) versus O(N): Do not
2714 // remove!
2715 return; // RETURN
2716 }
2717
2718 enum {
2722 };
2724 middle,
2725 last,
2726 allocator,
2728}
2729
2730template <class TARGET_TYPE>
2731inline
2732void ArrayPrimitives::erase(TARGET_TYPE *first,
2733 TARGET_TYPE *middle,
2734 TARGET_TYPE *last,
2735 bslma::Allocator *basicAllocator)
2736{
2737 erase<bsl::allocator<TARGET_TYPE> >(first,
2738 middle,
2739 last,
2740 basicAllocator);
2741}
2742
2743template <class ALLOCATOR>
2744inline
2750 ALLOCATOR allocator)
2751{
2754
2755 typedef typename bsl::allocator_traits<ALLOCATOR>::value_type TargetType;
2756
2757 if (toBegin != toEnd) {
2758 // Insert in the middle. Note that there is no strong exception
2759 // guarantee if copy constructor, move constructor, or assignment
2760 // operator throw.
2761
2762 enum {
2768 };
2769
2771 toBegin,
2772 toEnd,
2774 allocator,
2776 }
2777 else { // toBegin == toEnd
2779 allocator, toBegin, bslmf::MovableRefUtil::move(value));
2780 }
2781}
2782
2783template <class TARGET_TYPE>
2784inline
2785void ArrayPrimitives::insert(TARGET_TYPE *toBegin,
2786 TARGET_TYPE *toEnd,
2788 bslma::Allocator *basicAllocator)
2789{
2790 insert<bsl::allocator<TARGET_TYPE> >(toBegin,
2791 toEnd,
2793 basicAllocator);
2794}
2795
2796template <class ALLOCATOR>
2801 size_type numElements,
2802 ALLOCATOR allocator)
2803{
2806
2807 typedef typename bsl::allocator_traits<ALLOCATOR>::value_type TargetType;
2808
2809 if (0 == numElements) {
2810 return; // RETURN
2811 }
2812
2813 enum {
2819 };
2821 toEnd,
2822 value,
2823 numElements,
2824 allocator,
2826}
2827
2828template <class TARGET_TYPE>
2829inline
2830void ArrayPrimitives::insert(TARGET_TYPE *toBegin,
2831 TARGET_TYPE *toEnd,
2832 const TARGET_TYPE& value,
2833 size_type numElements,
2834 bslma::Allocator *basicAllocator)
2835{
2836 insert<bsl::allocator<TARGET_TYPE> >(toBegin,
2837 toEnd,
2838 value,
2839 numElements,
2840 basicAllocator);
2841}
2842
2843template <class ALLOCATOR, class FWD_ITER, class SENTINEL>
2847 FWD_ITER fromBegin,
2848 SENTINEL fromEnd,
2849 size_type numElements,
2850 ALLOCATOR allocator)
2851{
2852 if (0 == numElements) {
2853 return; // RETURN
2854 }
2855
2856 typedef typename bsl::allocator_traits<ALLOCATOR>::value_type TargetType;
2857
2859
2860 /// Overload resolution will handle the case where `FWD_ITER` is a raw
2861 /// pointer, so we need handle only user-defined iterators. As `bslalg`
2862 /// is levelized below `bslstl` we cannot use `iterator_traits`, but
2863 /// rely on the same property as `iterator_traits` that this typedef
2864 /// must be defined for any standard-conforming iterator, unless the
2865 /// iterator explicitly specialized the `std::iterator_traits` template.
2866 /// In practice, iterators always prefer to provide the member typedef
2867 /// than specialize the traits as it is a much simpler implementation,
2868 /// so this assumption is good enough.
2869 ///
2870 /// Also note that as we know that `FWD_ITER` is not a pointer, then we
2871 /// cannot take advantage of bitwise copying as we do not have pointers
2872 /// to pass to the `memcpy` describing the whole range. It is not worth
2873 /// the effort to try to bitwise copy one element at a time.
2874 typedef typename FWD_ITER::value_type FwdTarget;
2875
2876 /// We want to detect the special case of copying function pointers to
2877 /// `void *` or `const void *` pointers.
2878 typedef typename bsl::remove_pointer<TargetType>::type RemovePtrTarget;
2879
2880 enum {
2881 k_ITER_TO_FUNC_PTRS = bslmf::IsFunctionPointer<FwdTarget>::value,
2882 k_TARGET_IS_VOID_PTR = bsl::is_pointer<TargetType>::value &&
2884
2885 k_VALUE = k_ITER_TO_FUNC_PTRS && k_TARGET_IS_VOID_PTR
2888 };
2890 toEnd,
2891 fromBegin,
2892 fromEnd,
2893 numElements,
2894 allocator,
2896}
2897
2898template <class TARGET_TYPE, class FWD_ITER, class SENTINEL>
2899inline
2900void ArrayPrimitives::insert(TARGET_TYPE *toBegin,
2901 TARGET_TYPE *toEnd,
2902 FWD_ITER fromBegin,
2903 SENTINEL fromEnd,
2904 size_type numElements,
2905 bslma::Allocator *basicAllocator)
2906{
2907 insert<bsl::allocator<TARGET_TYPE> >(toBegin,
2908 toEnd,
2909 fromBegin,
2910 fromEnd,
2911 numElements,
2912 basicAllocator);
2913}
2914
2915template <class ALLOCATOR, class SOURCE_TYPE>
2919 SOURCE_TYPE *fromBegin,
2920 SOURCE_TYPE *fromEnd,
2921 size_type numElements,
2922 ALLOCATOR allocator)
2923{
2924 if (0 == numElements) {
2925 return; // RETURN
2926 }
2927
2928 typedef typename bsl::allocator_traits<ALLOCATOR>::value_type TargetType;
2929
2930 enum {
2931 k_ARE_PTRS_TO_PTRS = bsl::is_pointer<TargetType>::value &&
2933 k_IS_BITWISEMOVEABLE = bslmf::IsBitwiseMoveable<TargetType>::value,
2934 k_IS_BITWISECOPYABLE =
2936 k_VALUE = k_ARE_PTRS_TO_PTRS ? Imp::e_IS_POINTER_TO_POINTER
2937 : k_IS_BITWISECOPYABLE ? Imp::e_BITWISE_COPYABLE_TRAITS
2938 : k_IS_BITWISEMOVEABLE ? Imp::e_BITWISE_MOVEABLE_TRAITS
2940 };
2942 toEnd,
2943 fromBegin,
2944 fromEnd,
2945 numElements,
2946 allocator,
2948}
2949
2950template <class TARGET_TYPE, class SOURCE_TYPE>
2951inline
2952void ArrayPrimitives::insert(TARGET_TYPE *toBegin,
2953 TARGET_TYPE *toEnd,
2954 SOURCE_TYPE *fromBegin,
2955 SOURCE_TYPE *fromEnd,
2956 size_type numElements,
2957 bslma::Allocator *basicAllocator)
2958{
2959 insert<bsl::allocator<TARGET_TYPE> >(toBegin,
2960 toEnd,
2961 fromBegin,
2962 fromEnd,
2963 numElements,
2964 basicAllocator);
2965}
2966
2967template <class ALLOCATOR>
2968inline
2973 ALLOCATOR allocator)
2974{
2975 BSLS_ASSERT_SAFE(toBegin || fromBegin == fromEnd);
2976
2977 typedef typename bsl::allocator_traits<ALLOCATOR>::value_type TargetType;
2978
2979 enum {
2983 };
2984
2986 fromBegin,
2987 fromEnd,
2988 allocator,
2990}
2991
2992template <class TARGET_TYPE>
2993inline
2994void ArrayPrimitives::moveConstruct(TARGET_TYPE *toBegin,
2995 TARGET_TYPE *fromBegin,
2996 TARGET_TYPE *fromEnd,
2997 bslma::Allocator *basicAllocator)
2998{
2999 moveConstruct<bsl::allocator<TARGET_TYPE> >(toBegin,
3000 fromBegin,
3001 fromEnd,
3002 basicAllocator);
3003}
3004
3005template <class ALLOCATOR>
3006inline
3010 typename bsl::allocator_traits<ALLOCATOR>::pointer *fromEndPtr,
3013 size_type numElements,
3014 ALLOCATOR allocator)
3015{
3016 typedef typename bsl::allocator_traits<ALLOCATOR>::value_type TargetType;
3017
3018 enum {
3022 };
3024 toEnd,
3025 fromEndPtr,
3026 fromBegin,
3027 fromEnd,
3028 numElements,
3029 allocator,
3031}
3032
3033template <class TARGET_TYPE>
3034inline
3035void ArrayPrimitives::moveInsert(TARGET_TYPE *toBegin,
3036 TARGET_TYPE *toEnd,
3037 TARGET_TYPE **fromEndPtr,
3038 TARGET_TYPE *fromBegin,
3039 TARGET_TYPE *fromEnd,
3040 size_type numElements,
3041 bslma::Allocator *basicAllocator)
3042{
3043 moveInsert<bsl::allocator<TARGET_TYPE> >(toBegin,
3044 toEnd,
3045 fromEndPtr,
3046 fromBegin,
3047 fromEnd,
3048 numElements,
3049 basicAllocator);
3050}
3051
3052template <class TARGET_TYPE>
3053inline
3054void ArrayPrimitives::rotate(TARGET_TYPE *first,
3055 TARGET_TYPE *middle,
3056 TARGET_TYPE *last)
3057{
3059 middle));
3061 last));
3062
3063 enum {
3067 };
3069 middle,
3070 last,
3072}
3073
3074 // --------------------------
3075 // struct ArrayPrimitives_Imp
3076 // --------------------------
3077
3078// CLASS METHODS
3079template <class TARGET_TYPE>
3080inline
3081void ArrayPrimitives_Imp::assign(TARGET_TYPE *srcStart,
3082 TARGET_TYPE *srcEnd,
3083 TARGET_TYPE& value)
3084{
3085 for ( ; srcStart != srcEnd; ++srcStart) {
3086 *srcStart = value;
3087 }
3088}
3089
3090template <class FORWARD_ITERATOR, class SENTINEL>
3091inline
3092bool ArrayPrimitives_Imp::isInvalidRange(FORWARD_ITERATOR, SENTINEL)
3093{
3094 // Ideally would dispatch on random_access_iterator_tag to support
3095 // generalized random access iterators, but we are constrained by 'bsl'
3096 // levelization to not depend on 'bsl_iterator.h'. As the intent is to
3097 // detect invalid ranges in assertions, the conservative choice is to
3098 // return 'false' always. Note that this differs from the pointers case
3099 // below, which also disallows empty ranges.
3100
3101 return false;
3102}
3103
3104template <class TARGET_TYPE>
3105inline
3107 TARGET_TYPE *end)
3108{
3109 return !begin != !end || begin > end;
3110}
3111
3112template <class TARGET_TYPE>
3113inline
3114void ArrayPrimitives_Imp::reverseAssign(TARGET_TYPE *dest,
3115 TARGET_TYPE *srcStart,
3116 TARGET_TYPE *srcEnd)
3117{
3118 TARGET_TYPE *destEnd = srcEnd - srcStart + dest;
3119 while (srcStart != srcEnd) {
3120 *--destEnd = *--srcEnd;
3121 }
3122}
3123
3124
3125 // *** 'uninitializedFillN' overloads: ***
3126
3127inline
3129 bool *begin,
3130 bool value,
3131 size_type numElements,
3132 void *,
3134{
3135 BSLS_ASSERT_SAFE(begin || 0 == numElements);
3137 BSLMF_ASSERT(sizeof(bool) == 1);
3138
3139 if (BSLS_PERFORMANCEHINT_PREDICT_LIKELY(numElements != 0)) {
3140 std::memset(reinterpret_cast<char *>(begin), // odd, why not 'void *'?
3141 static_cast<char>(value),
3142 numElements);
3143 }
3144}
3145
3146inline
3148 char *begin,
3149 char value,
3150 size_type numElements,
3151 void *,
3153{
3154 BSLS_ASSERT_SAFE(begin || 0 == numElements);
3156
3157 if (BSLS_PERFORMANCEHINT_PREDICT_LIKELY(numElements != 0)) {
3158 std::memset(begin, value, numElements);
3159 }
3160}
3161
3162inline
3164 unsigned char *begin,
3165 unsigned char value,
3166 size_type numElements,
3167 void *,
3169{
3170 BSLS_ASSERT_SAFE(begin || 0 == numElements);
3172
3173 if (BSLS_PERFORMANCEHINT_PREDICT_LIKELY(numElements != 0)) {
3174 std::memset(begin, value, numElements);
3175 }
3176}
3177
3178inline
3180 signed char *begin,
3181 signed char value,
3182 size_type numElements,
3183 void *,
3185{
3186 BSLS_ASSERT_SAFE(begin || 0 == numElements);
3188
3189 if (BSLS_PERFORMANCEHINT_PREDICT_LIKELY(numElements != 0)) {
3190 std::memset(begin, value, numElements);
3191 }
3192}
3193
3194inline
3196 wchar_t *begin,
3197 wchar_t value,
3198 size_type numElements,
3199 void *,
3201{
3202 BSLS_ASSERT_SAFE(begin || 0 == numElements);
3204
3205 if (BSLS_PERFORMANCEHINT_PREDICT_LIKELY(numElements != 0)) {
3206 std::wmemset(begin, value, numElements);
3207 }
3208}
3209
3210inline
3212 unsigned short *begin,
3213 unsigned short value,
3214 size_type numElements,
3215 void *,
3217{
3218 BSLS_ASSERT_SAFE(begin || 0 == numElements);
3220
3222 reinterpret_cast<short *>(begin),
3223 static_cast<short>(value),
3224 numElements,
3225 (void *)0,
3227}
3228
3229inline
3231 unsigned int *begin,
3232 unsigned int value,
3233 size_type numElements,
3234 void *,
3236{
3237 BSLS_ASSERT_SAFE(begin || 0 == numElements);
3239
3241 reinterpret_cast<int *>(begin),
3242 static_cast<int>(value),
3243 numElements,
3244 (void *)0,
3246}
3247
3248inline
3250 long *begin,
3251 long value,
3252 size_type numElements,
3253 void *,
3255{
3256 BSLS_ASSERT_SAFE(begin || 0 == numElements);
3258
3259#if defined(BSLS_PLATFORM_CPU_64_BIT) && !defined(BSLS_PLATFORM_OS_WINDOWS)
3260 uninitializedFillN(reinterpret_cast<bsls::Types::Int64 *>(begin),
3261 static_cast<bsls::Types::Int64>(value),
3262 numElements);
3263#else
3265 reinterpret_cast<int *>(begin),
3266 static_cast<int>(value),
3267 numElements,
3268 (void *)0,
3270#endif
3271}
3272
3273inline
3275 unsigned long *begin,
3276 unsigned long value,
3277 size_type numElements,
3278 void *,
3280{
3281 BSLS_ASSERT_SAFE(begin || 0 == numElements);
3283
3284#if defined(BSLS_PLATFORM_CPU_64_BIT) && !defined(BSLS_PLATFORM_OS_WINDOWS)
3286 reinterpret_cast<bsls::Types::Int64 *>(begin),
3287 static_cast<bsls::Types::Int64>(value),
3288 numElements,
3289 (void *)0,
3291#else
3293 reinterpret_cast<int *>(begin),
3294 static_cast<int>(value),
3295 numElements,
3296 (void *)0,
3298#endif
3299}
3300
3301inline
3303 bsls::Types::Uint64 *begin,
3304 bsls::Types::Uint64 value,
3305 size_type numElements,
3306 void *,
3308{
3309 BSLS_ASSERT_SAFE(begin || 0 == numElements);
3311
3313 reinterpret_cast<bsls::Types::Int64 *>(begin),
3314 value,
3315 numElements,
3316 (void *)0,
3318}
3319
3320template <class TARGET_TYPE>
3321inline
3323 TARGET_TYPE **begin,
3324 TARGET_TYPE *value,
3325 size_type numElements,
3326 void *,
3328{
3329 BSLS_ASSERT_SAFE(begin || 0 == numElements);
3331
3332 // Note: 'const'-correctness is respected because the next overload picks
3333 // up the 'const TARGET_TYPE' and will be a better match. Note that we
3334 // cannot cast to 'const void **' (one would have to add 'const' at every
3335 // level, not just the innermost; i.e., 'const void *const *' would be
3336 // correct, 'const void **' is not [C++ Standard, 4.4 Qualification
3337 // conversions]).
3338
3340 reinterpret_cast<void **>(begin),
3341 static_cast<void *>(value),
3342 numElements,
3343 (void *)0,
3345}
3346
3347template <class TARGET_TYPE>
3348inline
3350 const TARGET_TYPE **begin,
3351 const TARGET_TYPE *value,
3352 size_type numElements,
3353 void *,
3355{
3356 BSLS_ASSERT_SAFE(begin || 0 == numElements);
3358
3359 // While it seems that this overload is subsumed by the previous template,
3360 // SunPro does not detect it.
3361
3363 reinterpret_cast<const void **>(begin),
3364 static_cast<const void *>(value),
3365 numElements,
3366 (void *)0,
3368}
3369
3370template <class TARGET_TYPE>
3371inline
3373 volatile TARGET_TYPE **begin,
3374 volatile TARGET_TYPE *value,
3375 size_type numElements,
3376 void *,
3378{
3379 BSLS_ASSERT_SAFE(begin || 0 == numElements);
3381
3382 // While it seems that this overload is subsumed by the previous template,
3383 // SunPro does not detect it.
3384
3386 reinterpret_cast<volatile void **>(begin),
3387 static_cast<volatile void *>(value),
3388 numElements,
3389 (void *)0,
3391}
3392
3393template <class TARGET_TYPE>
3394inline
3396 const volatile TARGET_TYPE **begin,
3397 const volatile TARGET_TYPE *value,
3398 size_type numElements,
3399 void *,
3401{
3402 BSLS_ASSERT_SAFE(begin || 0 == numElements);
3404
3405 // While it seems that this overload is subsumed by the previous template,
3406 // SunPro does not detect it.
3407
3409 reinterpret_cast<const volatile void **>(begin),
3410 static_cast<const volatile void *>(value),
3411 numElements,
3412 (void *)0,
3414}
3415
3416template <class TARGET_TYPE, class ALLOCATOR>
3418 TARGET_TYPE *begin,
3419 const TARGET_TYPE& value,
3420 size_type numElements,
3421 ALLOCATOR *,
3423{
3424 BSLS_ASSERT_SAFE(begin || 0 == numElements);
3426
3427 if (0 == numElements) {
3428 return; // RETURN
3429 }
3430
3431 const char *valueBuffer =
3432 reinterpret_cast<const char *>(BSLS_UTIL_ADDRESSOF(value));
3433
3434 std::memcpy((void *)begin, valueBuffer, sizeof(TARGET_TYPE));
3435 bitwiseFillN(reinterpret_cast<char *>(begin),
3436 sizeof(TARGET_TYPE),
3437 sizeof(TARGET_TYPE) * numElements);
3438}
3439
3440template <class TARGET_TYPE, class ALLOCATOR>
3442 TARGET_TYPE *begin,
3443 const TARGET_TYPE& value,
3444 size_type numElements,
3445 ALLOCATOR *allocator,
3447{
3448 BSLS_ASSERT_SAFE(begin || 0 == numElements);
3450 BSLS_ASSERT_SAFE(allocator);
3451
3452 if (0 == numElements) {
3453 return; // RETURN
3454 }
3456 begin,
3457 *allocator);
3458
3459 TARGET_TYPE *end = begin + numElements;
3460 do {
3461 bsl::allocator_traits<ALLOCATOR>::construct(*allocator, begin, value);
3462 begin = guard.moveEnd(1);
3463 } while (begin != end);
3464 guard.release();
3465}
3466
3467 // *** 'copyConstruct' overloads: ***
3468
3469template <class TARGET_TYPE, class FWD_ITER, class SENTINEL, class ALLOCATOR>
3470inline
3472 TARGET_TYPE *toBegin,
3473 FWD_ITER fromBegin,
3474 SENTINEL fromEnd,
3475 ALLOCATOR allocator,
3477{
3478 // We may be casting a function pointer to a 'void *' here, so this won't
3479 // work if we port to an architecture where the two are of different sizes.
3480
3481 BSLMF_ASSERT(sizeof(void *) == sizeof(void (*)()));
3482
3483 typedef typename bsl::remove_cv<
3484 typename bsl::remove_pointer<TARGET_TYPE>::type>::type NcPtrType;
3485
3486 typedef typename bsl::remove_cv<
3487 typename bsl::remove_pointer<
3488 typename bsl::remove_pointer<FWD_ITER>::type>::type>::type NcIter;
3489
3490#if defined(BSLALG_ARRAYPRIMITIVES_CANNOT_REMOVE_POINTER_FROM_FUNCTION_POINTER)
3491 // fall back on traditional C-style casts.
3492 copyConstruct((void * *)toBegin,
3493 (void * const *)fromBegin,
3494 (void * const *)fromEnd,
3495 allocator,
3497#else
3499 reinterpret_cast<void * *>(const_cast<NcPtrType **>(toBegin)),
3500 reinterpret_cast<void * const *>(const_cast<NcIter * const *>(fromBegin)),
3501 reinterpret_cast<void * const *>(const_cast<NcIter * const *>(fromEnd)),
3502 allocator,
3504#endif
3505}
3506
3507template <class FWD_ITER, class SENTINEL, class ALLOCATOR>
3509 void **toBegin,
3510 FWD_ITER fromBegin,
3511 SENTINEL fromEnd,
3512 ALLOCATOR,
3514{
3515 BSLMF_ASSERT(sizeof(void *) == sizeof(void (*)()));
3516 // We will be casting a function pointer to a 'void *', so this won't
3517 // work if we port to an architecture where the two are of different
3518 // sizes.
3519
3520 BSLS_ASSERT_SAFE(toBegin || fromBegin == fromEnd);
3522
3523 while (fromBegin != fromEnd) {
3524 // 'fromBegin' iterates over pointers to functions, which must be
3525 // @ref reinterpret_cast to 'void *'.
3526
3527 *toBegin = reinterpret_cast<void *>(*fromBegin);
3528 ++fromBegin;
3529 ++toBegin;
3530 }
3531}
3532
3533template <class TARGET_TYPE, class ALLOCATOR>
3534inline
3536 TARGET_TYPE *toBegin,
3537 const TARGET_TYPE *fromBegin,
3538 const TARGET_TYPE *fromEnd,
3539 ALLOCATOR,
3541{
3542 BSLS_ASSERT_SAFE(toBegin);
3544 fromEnd));
3545
3546 const size_type numBytes = reinterpret_cast<const char*>(fromEnd)
3547 - reinterpret_cast<const char*>(fromBegin);
3548 if (BSLS_PERFORMANCEHINT_PREDICT_LIKELY(numBytes != 0)) {
3549 std::memcpy((void *)toBegin, fromBegin, numBytes);
3550 }
3551}
3552
3553template <class TARGET_TYPE, class FWD_ITER, class SENTINEL, class ALLOCATOR>
3555 TARGET_TYPE *toBegin,
3556 FWD_ITER fromBegin,
3557 SENTINEL fromEnd,
3558 ALLOCATOR allocator,
3560{
3561 BSLS_ASSERT_SAFE(toBegin || fromBegin == fromEnd);
3563 fromEnd));
3564
3565 AutoArrayDestructor<TARGET_TYPE, ALLOCATOR> guard(toBegin, toBegin,
3566 allocator);
3567
3568 while (fromBegin != fromEnd) {
3569 // Note: We are not sure the value type of 'FWD_ITER' is convertible to
3570 // 'TARGET_TYPE'. Use 'construct' instead.
3571
3573 toBegin,
3574 *fromBegin);
3575 ++fromBegin;
3576 toBegin = guard.moveEnd(1);
3577 }
3578 guard.release();
3579}
3580
3581 // *** 'moveConstruct' overloads: ***
3582template <class TARGET_TYPE, class ALLOCATOR>
3583inline
3585 TARGET_TYPE *toBegin,
3586 TARGET_TYPE *fromBegin,
3587 TARGET_TYPE *fromEnd,
3588 ALLOCATOR,
3590{
3591 BSLS_ASSERT_SAFE(toBegin);
3593 fromEnd));
3594
3595 const size_type numBytes = reinterpret_cast<const char*>(fromEnd)
3596 - reinterpret_cast<const char*>(fromBegin);
3597 if (BSLS_PERFORMANCEHINT_PREDICT_LIKELY(numBytes != 0)) {
3598 std::memcpy((void *)toBegin, fromBegin, numBytes);
3599 }
3600}
3601
3602template <class TARGET_TYPE, class ALLOCATOR>
3604 TARGET_TYPE *toBegin,
3605 TARGET_TYPE *fromBegin,
3606 TARGET_TYPE *fromEnd,
3607 ALLOCATOR allocator,
3609{
3610 BSLS_ASSERT_SAFE(toBegin || fromBegin == fromEnd);
3612 fromEnd));
3613
3614 AutoArrayDestructor<TARGET_TYPE, ALLOCATOR> guard(toBegin, toBegin,
3615 allocator);
3616
3617 while (fromBegin != fromEnd) {
3619 allocator,
3620 toBegin,
3621 bslmf::MovableRefUtil::move(*fromBegin));
3622 ++fromBegin;
3623 toBegin = guard.moveEnd(1);
3624 }
3625 guard.release();
3626}
3627
3628template <class TARGET_TYPE, class ALLOCATOR>
3630 TARGET_TYPE *toBegin,
3631 TARGET_TYPE *fromBegin,
3632 TARGET_TYPE *fromEnd,
3633 ALLOCATOR allocator,
3635{
3636 BSLS_ASSERT_SAFE(toBegin || fromBegin == fromEnd);
3638 fromEnd));
3639
3640 AutoArrayDestructor<TARGET_TYPE, ALLOCATOR> guard(toBegin, toBegin,
3641 allocator);
3642
3643 while (fromBegin != fromEnd) {
3645 allocator,
3646 toBegin,
3648 ++fromBegin;
3649 toBegin = guard.moveEnd(1);
3650 }
3651 guard.release();
3652}
3653
3654
3655 // *** 'defaultConstruct' overloads: ***
3656
3657template <class TARGET_TYPE, class ALLOCATOR>
3658inline
3660 TARGET_TYPE *begin,
3661 size_type numElements,
3662 ALLOCATOR,
3664{
3665 BSLS_ASSERT_SAFE(begin || 0 == numElements);
3667
3668 if (BSLS_PERFORMANCEHINT_PREDICT_LIKELY(numElements != 0)) {
3669 std::memset(static_cast<void *>(begin),
3670 0,
3671 sizeof(TARGET_TYPE) * numElements);
3672 }
3673}
3674
3675template <class TARGET_TYPE, class ALLOCATOR>
3676inline
3678 TARGET_TYPE *begin,
3679 size_type numElements,
3680 ALLOCATOR allocator,
3682{
3683 BSLS_ASSERT_SAFE(begin || 0 == numElements);
3685
3686 if (0 < numElements) {
3688 bitwiseFillN(reinterpret_cast<char *>(begin),
3689 sizeof(TARGET_TYPE),
3690 numElements * sizeof(TARGET_TYPE));
3691 }
3692}
3693
3694template <class TARGET_TYPE, class ALLOCATOR>
3696 TARGET_TYPE *begin,
3697 size_type numElements,
3698 ALLOCATOR allocator,
3700{
3701 BSLS_ASSERT_SAFE(begin || 0 == numElements);
3703
3704 AutoArrayDestructor<TARGET_TYPE, ALLOCATOR> guard(begin, begin, allocator);
3705
3706 const TARGET_TYPE *end = begin + numElements;
3707 while (begin != end) {
3709 begin = guard.moveEnd(1);
3710 }
3711 guard.release();
3712}
3713
3714 // *** 'destructiveMove' overloads: ***
3715
3716template <class TARGET_TYPE, class ALLOCATOR>
3717inline
3719 TARGET_TYPE *toBegin,
3720 TARGET_TYPE *fromBegin,
3721 TARGET_TYPE *fromEnd,
3722 ALLOCATOR,
3724{
3725 BSLS_ASSERT_SAFE(toBegin || fromBegin == fromEnd);
3727 fromEnd));
3728
3729 const size_type numBytes = reinterpret_cast<const char*>(fromEnd)
3730 - reinterpret_cast<const char*>(fromBegin);
3731 if (BSLS_PERFORMANCEHINT_PREDICT_LIKELY(numBytes != 0)) {
3732 std::memcpy((void *)toBegin, fromBegin, numBytes);
3733 }
3734}
3735
3736template <class TARGET_TYPE, class ALLOCATOR>
3737inline
3739 TARGET_TYPE *toBegin,
3740 TARGET_TYPE *fromBegin,
3741 TARGET_TYPE *fromEnd,
3742 ALLOCATOR allocator,
3744{
3745 BSLS_ASSERT_SAFE(toBegin || fromBegin == fromEnd);
3747 fromEnd));
3748
3749 // 'TARGET_TYPE' certainly cannot be bit-wise copyable, so we can save the
3750 // compiler some work.
3751
3752 moveIfNoexcept(toBegin, fromBegin, fromEnd, allocator,
3754 ArrayDestructionPrimitives::destroy(fromBegin, fromEnd, allocator);
3755}
3756
3757 // *** 'emplace' with 'args' overloads: ***
3758
3759#if !BSLS_COMPILERFEATURES_SIMULATE_CPP11_FEATURES
3760template <class TARGET_TYPE, class ALLOCATOR, class... ARGS>
3761inline
3763 TARGET_TYPE *toBegin,
3764 TARGET_TYPE *toEnd,
3765 ALLOCATOR allocator,
3767 ARGS&&... args)
3768{
3769 // TBD: The implementation is exactly the same as 'BITWISE_MOVEABLE_TRAITS'
3770 // unless 'AutoArrayMoveDestructor' has a 'release' method so the guard can
3771 // be called off after one in-place construction. Then an optimization
3772 // using 'bitwiseFillN' is possible.
3773
3775 toBegin,
3776 toEnd,
3777 allocator,
3779 BSLS_COMPILERFEATURES_FORWARD(ARGS, args)...);
3780}
3781
3782template <class TARGET_TYPE, class ALLOCATOR, class... ARGS>
3784 TARGET_TYPE *toBegin,
3785 TARGET_TYPE *toEnd,
3786 ALLOCATOR allocator,
3788 ARGS&&... args)
3789{
3791 toEnd));
3793
3794 // TBD: fix to reflect that its only a single item....
3795 size_type numElements = 1;
3796
3797 // Key to the transformation diagrams:
3798 //..
3799 // A...G original contents of '[toBegin, toEnd)' ("tail")
3800 // v...v contents of '[fromBegin, fromEnd)' ("input")
3801 // _____ uninitialized array element
3802 // [...] part of an array guarded by an exception guard object
3803 // |.(.,.) part of array guarded by move guard
3804 // (middle indicated by ',' and dest by '|')
3805 //..
3806
3807 size_type tailLen = toEnd - toBegin;
3808 size_type numGuarded = tailLen < numElements ? tailLen : numElements;
3809
3810 //..
3811 // Transformation: ABCDE_______ => _______ABCDE (might overlap)
3812 //..
3813
3814 TARGET_TYPE *destBegin = toBegin + numElements;
3815 if (BSLS_PERFORMANCEHINT_PREDICT_LIKELY(tailLen != 0)) {
3816 std::memmove((void *)destBegin,
3817 toBegin,
3818 tailLen * sizeof(TARGET_TYPE));
3819 }
3820
3821 //..
3822 // Transformation: |_______(,ABCDE) => vvvvv|__(ABCDE,)
3823 //..
3824
3825 TARGET_TYPE *destEnd = toEnd + numElements;
3826
3828 destEnd - numGuarded,
3829 destEnd - numGuarded,
3830 destEnd,
3831 allocator);
3832
3833 while (guard.middle() != guard.end()) {
3835 guard.destination(),
3836 BSLS_COMPILERFEATURES_FORWARD(ARGS, args)...);
3837 guard.advance();
3838 }
3839
3840 // The bitwise 'guard' is now inactive, since 'middle() == end()' and
3841 // 'guard.destination()' is the smaller of 'destBegin' or 'toEnd'.
3842
3843 if (tailLen < numElements) {
3844 // There still is a gap of 'numElements - tailLen' to fill in between
3845 // 'toEnd' and 'destBegin'. The elements that have been 'memmove'-ed
3846 // need to be guarded, we fill the gap backward from there to keep
3847 // guarded portion in one piece.
3848
3850 destEnd,
3851 allocator);
3852
3853 //..
3854 // Transformation: vvvvv__[ABCDE] => vvvvv[vvABCDE]
3855 //..
3856
3857 while (toEnd != destBegin) {
3859 --destBegin,
3860 BSLS_COMPILERFEATURES_FORWARD(ARGS,args)...);
3861
3862 endGuard.moveBegin(-1);
3863 }
3864 endGuard.release();
3865 }
3866}
3867
3868template <class TARGET_TYPE, class ALLOCATOR, class... ARGS>
3870 TARGET_TYPE *toBegin,
3871 TARGET_TYPE *toEnd,
3872 ALLOCATOR allocator,
3874 ARGS&&... args)
3875{
3877 toEnd));
3879
3880 // Key to the transformation diagrams:
3881 //..
3882 // A...G original contents of '[toBegin, toEnd)' ("tail")
3883 // v...v copies of 'value' ("input")
3884 // _____ uninitialized array elements
3885 // [...] part of array protected by an exception guard object
3886 //..
3887
3888 if (toEnd > toBegin) {
3889 // Insert in the middle. First, construct a temporary object from the
3890 // parameter pack of the strong exception guarantee if the construction
3891 // throws. A welcome consequence is that the parameter pack may refer
3892 // (directly or indirectly) into a container element.
3893
3896 allocator,
3897 BSLS_UTIL_ADDRESSOF(space.object()),
3898 BSLS_COMPILERFEATURES_FORWARD(ARGS, args)...);
3900 BSLS_UTIL_ADDRESSOF(space.object()));
3901
3902 //..
3903 // Transformation: ABCDEFG_[] => ABCDEFG[G].
3904 //..
3905
3907 allocator,
3908 toEnd,
3910
3912 toEnd + 1,
3913 allocator);
3914
3915 //..
3916 // Transformation: ABCDEFG[G] => AABCDEF[G].
3917 //..
3918
3919 TARGET_TYPE *destEnd = toEnd;
3920 TARGET_TYPE *srcEnd = toEnd - 1;
3921 while (toBegin != srcEnd) {
3922 *--destEnd = bslmf::MovableRefUtil::move_if_noexcept(*--srcEnd);
3923 }
3924
3925 //..
3926 // Transformation: AABCDEFG[G] => vABCDEF[G].
3927 //..
3928
3930
3931 guard.release();
3932 }
3933 else {
3934 //..
3935 // Transformation: _ => v.
3936 //..
3937
3939 allocator, toEnd, BSLS_COMPILERFEATURES_FORWARD(ARGS, args)...);
3940 }
3941}
3942#endif
3943
3944 // *** 'erase' overloads: ***
3945
3946template <class TARGET_TYPE, class ALLOCATOR>
3948 TARGET_TYPE *first,
3949 TARGET_TYPE *middle,
3950 TARGET_TYPE *last,
3951 ALLOCATOR allocator,
3953{
3956
3957 // Key to the transformation diagrams:
3958 //..
3959 // t...z Original contents of '[first, middle)'
3960 // A...G Original contents of '[middle, last)'
3961 // _ Destroyed array element
3962 //..
3963
3964 //..
3965 // Transformation: tuvABCDEFG => ___ABCDEFG (no throw)
3966 //..
3967 ArrayDestructionPrimitives::destroy(first, middle, allocator);
3968
3969 //..
3970 // Transformation: ___ABCDEFG => ABCDEFG___ (might overlap, but no throw)
3971 //..
3972 size_type numBytes = reinterpret_cast<const char *>(last)
3973 - reinterpret_cast<const char *>(middle);
3974 if (BSLS_PERFORMANCEHINT_PREDICT_LIKELY(numBytes != 0)) {
3975 std::memmove((void *)first, middle, numBytes);
3976 }
3977}
3978
3979template <class TARGET_TYPE, class ALLOCATOR>
3981 TARGET_TYPE *first,
3982 TARGET_TYPE *middle,
3983 TARGET_TYPE *last,
3984 ALLOCATOR allocator,
3986{
3989
3990 // Key to the transformation diagrams:
3991 //..
3992 // t...z Original contents of '[first, middle)'
3993 // A...G Original contents of '[middle, last)'
3994 // _ Destructed array element
3995 //..
3996
3997 //..
3998 // Transformation: tuvABCDEFG => ABCDEFGEFG.
3999 //..
4000
4001 while (middle != last) {
4002 *first++ = bslmf::MovableRefUtil::move_if_noexcept(*middle++);
4003 }
4004
4005 //..
4006 // Transformation: ABCDEFGEFG => ABCDEFG___.
4007 //..
4008
4009 ArrayDestructionPrimitives::destroy(first, middle, allocator);
4010}
4011
4012 // *** 'insert' with 'value' overloads: ***
4013
4014template <class TARGET_TYPE, class ALLOCATOR>
4015inline
4017 TARGET_TYPE *toBegin,
4018 TARGET_TYPE *toEnd,
4019 const TARGET_TYPE& value,
4020 size_type numElements,
4021 ALLOCATOR allocator,
4023{
4026
4027 // Key to the transformation diagrams:
4028 //..
4029 // A...G original contents of '[toBegin, toEnd)' ("tail")
4030 // v...v contents of '[fromBegin, fromEnd)' ("input")
4031 // _____ uninitialized array element
4032 //..
4033
4034 // ALIASING: If 'value' is a reference into the array 'toBegin..toEnd',
4035 // then moving the array first might introduce a change in 'value'. Since
4036 // type is bitwise copyable, then no memory changes outside the array, so
4037 // the test below is sufficient to discover all the possible aliasing.
4038 // Note that we never make a copy.
4039
4040 const TARGET_TYPE *tempValuePtr = BSLS_UTIL_ADDRESSOF(value);
4041 if (toBegin <= tempValuePtr && tempValuePtr < toEnd ) {
4042 // Adjust pointer for shifting after the move.
4043
4044 tempValuePtr += numElements;
4045 }
4046
4047 //..
4048 // Transformation: ABCDE___ => ___ABCDE (might overlap).
4049 //..
4050
4051 const size_type numBytes = reinterpret_cast<const char*>(toEnd)
4052 - reinterpret_cast<const char*>(toBegin);
4053 if (BSLS_PERFORMANCEHINT_PREDICT_LIKELY(numBytes != 0)) {
4054 std::memmove((void *)(toBegin + numElements), toBegin, numBytes);
4055 }
4056
4057 //..
4058 // Transformation: ___ABCDE => v__ABCDE (no overlap).
4059 //..
4060
4061 // Use 'copyConstruct' instead of 'memcpy' because the former optimizes for
4062 // fundamental types using 'operator=' instead, which avoid the 'memcpy'
4063 // function call.
4064
4066 toBegin,
4067 *tempValuePtr);
4068 //..
4069 // Transformation: v__ABCDE => vvvABCDE.
4070 //..
4071
4072 bitwiseFillN(reinterpret_cast<char *>(toBegin),
4073 sizeof value,
4074 numElements * sizeof value);
4075}
4076
4077template <class TARGET_TYPE, class ALLOCATOR>
4079 TARGET_TYPE *toBegin,
4080 TARGET_TYPE *toEnd,
4081 const TARGET_TYPE& value,
4082 size_type numElements,
4083 ALLOCATOR allocator,
4085{
4088
4089 // Key to the transformation diagrams:
4090 //..
4091 // A...G original contents of '[toBegin, toEnd)' ("tail")
4092 // v...v contents of '[fromBegin, fromEnd)' ("input")
4093 // _____ uninitialized array element
4094 // [...] part of an array guarded by an exception guard object
4095 // |.(.,.) part of array guarded by move guard
4096 // (middle indicated by ',' and dest by '|')
4097 //..
4098
4099 const TARGET_TYPE *tempValuePtr = BSLS_UTIL_ADDRESSOF(value);
4100 if (toBegin <= tempValuePtr && tempValuePtr < toEnd + numElements) {
4101 // Adjust pointer for shifting after the move.
4102
4103 tempValuePtr += numElements;
4104 }
4105
4106 size_type tailLen = toEnd - toBegin;
4107 size_type numGuarded = tailLen < numElements ? tailLen : numElements;
4108
4109 //..
4110 // Transformation: ABCDE_______ => _______ABCDE (might overlap)
4111 //..
4112
4113 TARGET_TYPE *destBegin = toBegin + numElements;
4114 if (BSLS_PERFORMANCEHINT_PREDICT_LIKELY(tailLen != 0)) {
4115 std::memmove((void *)destBegin,
4116 toBegin,
4117 tailLen * sizeof(TARGET_TYPE));
4118 }
4119
4120 //..
4121 // Transformation: |_______(,ABCDE) => vvvvv|__(ABCDE,)
4122 //..
4123
4124 TARGET_TYPE *destEnd = toEnd + numElements;
4125
4127 destEnd - numGuarded,
4128 destEnd - numGuarded,
4129 destEnd,
4130 allocator);
4131
4132 while (guard.middle() != guard.end()) {
4134 guard.destination(),
4135 *tempValuePtr);
4136 guard.advance();
4137 }
4138
4139 // The bitwise 'guard' is now inactive, since 'middle() == end()' and
4140 // 'guard.destination()' is the smaller of 'destBegin' or 'toEnd'.
4141
4142 if (tailLen < numElements) {
4143 // There still is a gap of 'numElements - tailLen' to fill in between
4144 // 'toEnd' and 'destBegin'. The elements that have been 'memmove'-ed
4145 // need to be guarded, we fill the gap backward from there to keep
4146 // guarded portion in one piece.
4147
4149 destEnd,
4150 allocator);
4151
4152 //..
4153 // Transformation: vvvvv__[ABCDE] => vvvvv[vvABCDE]
4154 //..
4155
4156 while (toEnd != destBegin) {
4158 --destBegin,
4159 *tempValuePtr);
4160
4161 endGuard.moveBegin(-1);
4162 }
4163 endGuard.release();
4164 }
4165}
4166
4167template <class TARGET_TYPE, class ALLOCATOR>
4169 TARGET_TYPE *toBegin,
4170 TARGET_TYPE *toEnd,
4171 const TARGET_TYPE& value,
4172 size_type numElements,
4173 ALLOCATOR allocator,
4175{
4178
4179 // Aliasing: Make a temp copy of 'value' (always). The reason is that
4180 // 'value' could be a reference inside the input range, or even outside
4181 // but with lifetime controlled by one of these values, and so the next
4182 // transformation could invalidate 'value'. Note: One cannot rely on
4183 // 'TARGET_TYPE' to have a single-argument copy constructor (i.e.,
4184 // default allocator argument to 0) if it takes an allocator; hence the
4185 // constructor proxy.
4186
4190 value);
4192 BSLS_UTIL_ADDRESSOF(space.object()));
4193
4194 // Key to the transformation diagrams:
4195 //..
4196 // A...G original contents of '[toBegin, toEnd)' ("tail")
4197 // v...v copies of 'value' ("input")
4198 // _____ uninitialized array elements
4199 // [...] part of array protected by an exception guard object
4200 //..
4201
4202 const size_type tailLen = toEnd - toBegin;
4203 if (tailLen >= numElements) {
4204 // Tail is not shorter than input.
4205
4206 //..
4207 // Transformation: ABCDEFG___[] => ABCDEFG[EFG].
4208 //..
4209
4210 moveIfNoexcept(toEnd, // destination
4211 toEnd - numElements, // source
4212 toEnd, // end source
4213 allocator,
4215
4217 toEnd + numElements,
4218 allocator);
4219
4220 // TBD: this does the same thing as the old code - don't like that we
4221 // circumvent the whole allocator thing, but for now, let's keep it
4222 // consistent.
4223 // ConstructorProxy<TARGET_TYPE>
4224 // tempValue(value, bslma::Default::allocator());
4225
4226 //..
4227 // Transformation: ABCDEFG[EFG] => ABCABCD[EFG].
4228 //..
4229
4230 TARGET_TYPE *src = toEnd - numElements;
4231 TARGET_TYPE *dest = toEnd;
4232 while (toBegin != src) {
4234 }
4235
4236 //..
4237 // Transformation: ABCABCD[EFG] => vvvABCD[EFG].
4238 //..
4239
4240 for ( ; toBegin != dest; ++toBegin) {
4241 *toBegin = space.object();
4242 }
4243 // TBD: this can't be good
4244 guard.release();
4245 }
4246 else {
4247 // Tail is shorter than input. We can avoid the temp copy of value
4248 // since there will be space to make a first copy after the tail, and
4249 // use that to make the subsequent copies.
4250 //
4251 // TBD: Update comment now that the assumption is no longer true, and
4252 // we make a copy at the top of the call, regardless. We could
4253 // restore this optimization if we use metaprogramming to check if
4254 // 'moveIfNoexcept' will move or copy, but not convinced it is worth
4255 // the complexity.
4256
4257 difference_type remElements = numElements - tailLen;
4258
4259 //..
4260 // Transformation: ABC_______[] => ABC____[ABC].
4261 //..
4262
4263 moveIfNoexcept(toBegin + numElements, // destination
4264 toBegin, // source
4265 toEnd, // end source
4266 allocator,
4268
4269 AutoArrayDestructor<TARGET_TYPE, ALLOCATOR> guard(toEnd + remElements,
4270 toEnd + numElements,
4271 allocator);
4272
4273 //..
4274 // Transformation: ABC____[ABC] => ABC[vvvvABC].
4275 //..
4276
4277 uninitializedFillN(toEnd,
4278 space.object(),
4279 remElements,
4280 &allocator,
4282 guard.moveBegin(-remElements);
4283
4284 //..
4285 // Transformation: ABC[vvvvABC] => vvv[vvvvABC].
4286 //..
4287
4288 for ( ; toBegin != toEnd; ++toBegin) {
4289 *toBegin = space.object();
4290 }
4291
4292 guard.release();
4293 }
4294}
4295
4296 // *** 'insert' with 'FWD_ITER' overloads: ***
4297
4298
4299template <class TARGET_TYPE, class FWD_ITER, class SENTINEL, class ALLOCATOR>
4300inline
4302 TARGET_TYPE *toBegin,
4303 TARGET_TYPE *toEnd,
4304 FWD_ITER fromBegin,
4305 SENTINEL fromEnd,
4306 size_type numElements,
4307 ALLOCATOR allocator,
4309{
4310 // We may be casting a function pointer to a 'void *' here, so this won't
4311 // work if we port to an architecture where the two are of different sizes.
4312
4313 BSLMF_ASSERT(sizeof(void *) == sizeof(void (*)()));
4314
4315#if defined(BSLALG_ARRAYPRIMITIVES_CANNOT_REMOVE_POINTER_FROM_FUNCTION_POINTER)
4316 // fall back on traditional C-style casts.
4317 insert((void * *)toBegin,
4318 (void * *)toEnd,
4319 (void * const *)fromBegin,
4320 (void * const *)fromEnd,
4321 numElements,
4322 allocator,
4324#else
4325 typedef typename bsl::remove_cv<
4326 typename bsl::remove_pointer<TARGET_TYPE>::type>::type NcPtrType;
4327
4328 typedef typename bsl::remove_cv<
4329 typename bsl::remove_pointer<
4330 typename bsl::remove_pointer<FWD_ITER>::type>::type>::type NcIter;
4331
4332 insert(
4333 reinterpret_cast<void * *>(const_cast<NcPtrType **>(toBegin)),
4334 reinterpret_cast<void * *>(const_cast<NcPtrType **>(toEnd)),
4335 reinterpret_cast<void * const *>(const_cast<NcIter * const *>(fromBegin)),
4336 reinterpret_cast<void * const *>(const_cast<NcIter * const *>(fromEnd)),
4337 numElements,
4338 allocator,
4340#endif
4341}
4342
4343template <class TARGET_TYPE, class ALLOCATOR>
4344inline
4346 TARGET_TYPE *toBegin,
4347 TARGET_TYPE *toEnd,
4348 const TARGET_TYPE *fromBegin,
4349 const TARGET_TYPE *fromEnd,
4350 size_type numElements,
4351 ALLOCATOR,
4353{
4355
4356 // 'FWD_ITER' has been converted to a 'const TARGET_TYPE *' and
4357 // 'TARGET_TYPE' is bit-wise copyable.
4360 BSLS_ASSERT_SAFE(fromBegin || 0 == numElements);
4361
4362 BSLS_ASSERT_SAFE(fromBegin + numElements == fromEnd);
4363 BSLS_ASSERT_SAFE(fromEnd <= toBegin || toEnd + numElements <= fromBegin);
4364
4365 (void) fromEnd; // quell warning when 'BSLS_ASSERT_SAFE' is compiled out
4366
4367 // Key to the transformation diagrams:
4368 //..
4369 // A...G original contents of '[toBegin, toEnd)' ("tail")
4370 // t...z contents of '[fromBegin, fromEnd)' ("input")
4371 // _____ uninitialized array element
4372 //..
4373
4374 //..
4375 // Transformation: ABCDE_______ => _______ABCDE (might overlap).
4376 //..
4377
4378 const size_type numBytes = reinterpret_cast<const char*>(toEnd)
4379 - reinterpret_cast<const char*>(toBegin);
4380 if (BSLS_PERFORMANCEHINT_PREDICT_LIKELY(numBytes != 0)) {
4381 std::memmove((void *)(toBegin + numElements), toBegin, numBytes);
4382 }
4383
4384 //..
4385 // Transformation: _______ABCDE => tuvwxyzABCDE (no overlap).
4386 //..
4387
4388 if (BSLS_PERFORMANCEHINT_PREDICT_LIKELY(numElements != 0)) {
4389 std::memcpy((void *)toBegin,
4390 fromBegin,
4391 numElements * sizeof(TARGET_TYPE));
4392 }
4393}
4394
4395template <class TARGET_TYPE, class FWD_ITER, class SENTINEL, class ALLOCATOR>
4397 TARGET_TYPE *toBegin,
4398 TARGET_TYPE *toEnd,
4399 FWD_ITER fromBegin,
4400 SENTINEL,
4401 size_type numElements,
4402 ALLOCATOR allocator,
4404{
4405 // 'TARGET_TYPE' is bit-wise moveable.
4408
4409 if (0 == numElements) {
4410 return; // RETURN
4411 }
4412
4413 // The following assertions make sense only if 'FWD_ITER' is a pointer to a
4414 // possibly cv-qualified 'TARGET_TYPE', and are tested in that overload
4415 // (see above).
4416 //..
4417 // BSLS_ASSERT(fromBegin + numElements == fromEnd);
4418 // BSLS_ASSERT(fromEnd <= toBegin || toEnd + numElements <= fromBegin);
4419 //..
4420
4421 // Key to the transformation diagrams:
4422 //..
4423 // A...G original contents of '[toBegin, toEnd)' ("tail")
4424 // t...z contents of '[fromBegin, fromEnd)' ("input")
4425 // _____ uninitialized array element
4426 // [...] part of array guarded by exception guard
4427 // |.(.,.) part of array guarded by move guard
4428 // (middle indicated by ',' and dest by '|')
4429 //..
4430
4431 const size_type tailLen = toEnd - toBegin;
4432 const size_type numGuarded = tailLen < numElements ? tailLen : numElements;
4433
4434 //..
4435 // Transformation: ABCDE____ => ____ABCDE (might overlap).
4436 //..
4437
4438 TARGET_TYPE *destBegin = toBegin + numElements;
4439 if (BSLS_PERFORMANCEHINT_PREDICT_LIKELY(tailLen != 0)) {
4440 std::memmove((void *)destBegin,
4441 toBegin,
4442 tailLen * sizeof(TARGET_TYPE));
4443 }
4444
4445 //..
4446 // Transformation: |_______(,ABCDE) => tuvwx|__(ABCDE,).
4447 //..
4448
4449 TARGET_TYPE *destEnd = toEnd + numElements;
4450
4452 destEnd - numGuarded,
4453 destEnd - numGuarded,
4454 destEnd,
4455 allocator);
4456
4457 for (; guard.middle() != guard.end(); ++fromBegin) {
4459 guard.destination(),
4460 *fromBegin);
4461 guard.advance();
4462 }
4463
4464 // The bitwise 'guard' is now inactive, since 'middle() == end()', and
4465 // 'guard.destination()' is the smaller of 'destBegin' or 'toEnd'.
4466
4467 if (tailLen < numElements) {
4468 // There still is a gap of 'numElements - tailLen' to fill in between
4469 // 'toEnd' and 'destBegin'. The elements that have been 'memmove'-ed
4470 // need to be guarded, and we need to continue to fill the hole at the
4471 // same guarding the copied elements as well.
4472
4474 toEnd,
4475 allocator);
4477 destEnd,
4478 allocator);
4479
4480 //..
4481 // Transformation: tuvwx[]__[ABCDE] => tuvwx[yz][ABCDE].
4482 //..
4483
4484 for (; toEnd != destBegin; ++fromBegin) {
4486 toEnd,
4487 *fromBegin);
4488 toEnd = endGuard1.moveEnd(1);
4489 }
4490 endGuard1.release();
4491 endGuard2.release();
4492 }
4493}
4494
4495template <class TARGET_TYPE, class FWD_ITER, class SENTINEL, class ALLOCATOR>
4497 TARGET_TYPE *toBegin,
4498 TARGET_TYPE *toEnd,
4499 FWD_ITER fromBegin,
4500 SENTINEL fromEnd,
4501 size_type numElements,
4502 ALLOCATOR allocator,
4504{
4507
4508 if (0 == numElements) {
4509 return; // RETURN
4510 }
4511
4512 // Key to the transformation diagrams:
4513 //..
4514 // A...G original contents of '[toBegin, toEnd)' ("tail")
4515 // t...z contents of '[fromBegin, fromEnd)' ("input")
4516 // _____ uninitialized array elements
4517 // [...] part of array protected by a guard object
4518 //..
4519
4520 const size_type tailLen = toEnd - toBegin;
4521 if (tailLen > numElements) {
4522 // Tail is longer than input.
4523
4524 //..
4525 // Transformation: ABCDEFG___[] => ABCDEFG[EFG].
4526 //..
4527
4528 moveIfNoexcept(toEnd, // destination
4529 toEnd - numElements, // source
4530 toEnd, // end source
4531 allocator,
4533
4535 toEnd + numElements,
4536 allocator);
4537
4538 //..
4539 // Transformation: ABCDEFG[EFG] => ABCABCD[EFG].
4540 //..
4541
4542 TARGET_TYPE *src = toEnd - numElements;
4543 TARGET_TYPE *dest = toEnd;
4544 while (toBegin != src) {
4546 }
4547
4548 //..
4549 // Transformation: ABCABCD[EFG] => tuvABCD[EFG].
4550 //..
4551
4552 for (; toBegin != dest; ++toBegin, ++fromBegin) {
4553 *toBegin = *fromBegin;
4554 }
4555
4556 guard.release();
4557 }
4558 else {
4559 // Tail is not longer than input (numElements).
4560
4561 difference_type remElements = numElements - tailLen;
4562
4563 //..
4564 // Transformation: ABC_______[] => ABC____[ABC]
4565 //..
4566
4567 moveIfNoexcept(toBegin + numElements, // destination
4568 toBegin, // source
4569 toEnd, // end source
4570 allocator,
4572
4573 AutoArrayDestructor<TARGET_TYPE, ALLOCATOR> guard(toEnd + remElements,
4574 toEnd + numElements,
4575 allocator);
4576
4577 //..
4578 // Transformation: ABC____[ABC] => tuv____[ABC].
4579 //..
4580
4581 for (; toBegin != toEnd; ++fromBegin, ++toBegin) {
4582 *toBegin = *fromBegin;
4583 }
4584
4585 //..
4586 // Transformation: tuv____[ABC] => tuvwxyzABC[].
4587 //..
4588 copyConstruct(toBegin,
4589 fromBegin,
4590 fromEnd,
4591 allocator,
4593
4594 guard.release();
4595 }
4596}
4597
4598template <class FWD_ITER, class SENTINEL, class ALLOCATOR>
4600 void **toBegin,
4601 void **toEnd,
4602 FWD_ITER fromBegin,
4603 SENTINEL,
4604 size_type numElements,
4605 ALLOCATOR,
4607{
4608 // This very specific overload is required for the case that 'FWD_ITER' is
4609 // an iterator that is not a pointer, iterating over a sequence of function
4610 // pointers. The implementation relies on the conditionally-supported
4611 // behavior that any function pointer can be @ref reinterpret_cast to
4612 // 'void *'.
4613
4614 // 'TARGET_TYPE' is bit-wise moveable.
4617
4618 if (0 == numElements) {
4619 return; // RETURN
4620 }
4621
4622 // The following assertions make sense only if 'FWD_ITER' is a pointer to a
4623 // possibly cv-qualified 'TARGET_TYPE', and are tested in that overload
4624 // (see above).
4625 //..
4626 // BSLS_ASSERT(fromBegin + numElements == fromEnd);
4627 // BSLS_ASSERT(fromEnd <= toBegin || toEnd + numElements <= fromBegin);
4628 //..
4629
4630 // Key to the transformation diagrams:
4631 //..
4632 // A...G original contents of '[toBegin, toEnd)' ("tail")
4633 // t...z contents of '[fromBegin, fromEnd)' ("input")
4634 // _____ uninitialized array element
4635 // [...] part of array guarded by exception guard
4636 // |.(.,.) part of array guarded by move guard
4637 // (middle indicated by ',' and dest by '|')
4638 //..
4639
4640 const size_type tailLen = toEnd - toBegin;
4641
4642 //..
4643 // Transformation: ABCDE____ => ____ABCDE (might overlap).
4644 //..
4645
4646 void **destBegin = toBegin + numElements;
4647
4648 if (BSLS_PERFORMANCEHINT_PREDICT_LIKELY(tailLen != 0)) {
4649 std::memmove(destBegin, toBegin, tailLen * sizeof(void **));
4650 }
4651
4652 for (size_type i = 0; i < numElements; ++i) {
4653 *toBegin = reinterpret_cast<void *>(*fromBegin);
4654
4655 ++fromBegin;
4656 ++toBegin;
4657 }
4658}
4659
4660 // *** 'moveInsert' overloads: ***
4661
4662template <class TARGET_TYPE, class ALLOCATOR>
4663inline
4665 TARGET_TYPE *toBegin,
4666 TARGET_TYPE *toEnd,
4667 TARGET_TYPE **lastPtr,
4668 TARGET_TYPE *first,
4669 TARGET_TYPE *last,
4670 size_type numElements,
4671 ALLOCATOR allocator,
4673{
4676 BSLS_ASSERT_SAFE(first || 0 == numElements);
4678 BSLS_ASSERT_SAFE(lastPtr);
4679
4680 // Functionally indistinguishable from this:
4681
4682 *lastPtr = last;
4683 insert(toBegin, toEnd, first, last, numElements, allocator,
4685 *lastPtr = first;
4686}
4687
4688template <class TARGET_TYPE, class ALLOCATOR>
4689inline
4691 TARGET_TYPE *toBegin,
4692 TARGET_TYPE *toEnd,
4693 TARGET_TYPE **lastPtr,
4694 TARGET_TYPE *first,
4695 TARGET_TYPE *last,
4696 size_type numElements,
4697 ALLOCATOR allocator,
4699{
4702 BSLS_ASSERT_SAFE(first || 0 == numElements);
4704 BSLS_ASSERT_SAFE(lastPtr);
4705
4706 // There isn't any advantage at destroying [first,last) one by one as we're
4707 // moving it, except perhaps for slightly better memory usage.
4708
4709 *lastPtr = last;
4710 insert(toBegin, toEnd, first, last, numElements, allocator,
4712 ArrayDestructionPrimitives::destroy(first, last, allocator);
4713 *lastPtr = first;
4714}
4715
4716 // *** 'rotate' overloads: ***
4717
4718template <class TARGET_TYPE>
4719inline
4721 TARGET_TYPE *begin,
4722 TARGET_TYPE *middle,
4723 TARGET_TYPE *end,
4725{
4728
4729 bitwiseRotate(reinterpret_cast<char *>(begin),
4730 reinterpret_cast<char *>(middle),
4731 reinterpret_cast<char *>(end));
4732}
4733
4734template <class TARGET_TYPE>
4736 TARGET_TYPE *begin,
4737 TARGET_TYPE *middle,
4738 TARGET_TYPE *end,
4740{
4743
4744 if (begin == middle || middle == end) {
4745 // This test changes into O(1) what would otherwise be O(N): Do not
4746 // remove!
4747
4748 return; // RETURN
4749 }
4750
4751 // This case is simple enough, it should be taken care of on its own.
4752
4753 const std::size_t numElements = middle - begin;
4754 const std::size_t remElements = end - middle;
4755
4756 if (numElements == remElements) {
4757 for (; middle != end; ++begin, ++middle) {
4758 TARGET_TYPE tmp(*middle);
4759 *middle = *begin;
4760 *begin = tmp;
4761 }
4762 return; // RETURN
4763 }
4764
4765 // This algorithm proceeds by decomposing the rotation into cycles, which
4766 // can then be rotated using a single element buffer. First we compute the
4767 // 'gcd(end - begin, numElements)' which is the number of cycles in the
4768 // rotation.
4769
4770 std::size_t numCycles = end - begin;
4771 std::size_t remainder = numElements;
4772 while (remainder != 0) {
4773 std::size_t t = numCycles % remainder;
4774 numCycles = remainder;
4775 remainder = t;
4776 }
4777
4778 // Key to the transformation diagrams:
4779 //..
4780 // A...D Contents of the current cycle
4781 // W...Z Contents of another cycle
4782 // _ Elements not in the current cycle
4783 //..
4784
4785 for (std::size_t i = 0; i < numCycles; ++i) {
4786 // Let the current cycle be initially 'A__B__C__D__', (note that its
4787 // stride is 'length / numCycles') and let (*) denote the current
4788 // position of 'ptr'.
4789
4790 TARGET_TYPE *ptr = begin; // seed for current cycle: A(*)__B__C__D__
4791 TARGET_TYPE tmp = *ptr; // value held at the seed: tmp == A
4792
4793 if (numElements < remElements) {
4794 // Rotate the cycle forward by numElements positions (or backward
4795 // by -(length-numElements)=-remElements positions if crossing the
4796 // boundary forward). The transformation is:
4797 //..
4798 // A(*)__B__C__D__ => B__B(*)__C__D__
4799 // => B__C__C(*)__D__
4800 // => B__C__D__D(*)__
4801 //..
4802 // The length of the cycle is always 'length / numCycles', but it
4803 // crosses the range boundaries 'numElements / numCycles' times,
4804 // each triggering an extra assignment in the 'if' clause below, so
4805 // the loop must only be executed:
4806 //..
4807 // (length - numElements) / numCycles = remElements / numCycles
4808 //..
4809 // times.
4810
4811 std::size_t cycleSize = remElements / numCycles;
4812
4813 for (std::size_t j = 0; j < cycleSize; ++j) {
4814 if (ptr > begin + remElements) {
4815 // Wrap around the range boundaries. (Note that
4816 // '-remElements == numElements - (end - begin)'.)
4817
4818 *ptr = *(ptr - remElements);
4819 ptr -= remElements;
4820 }
4821
4822 *ptr = *(ptr + numElements);
4823 ptr += numElements;
4824 }
4825 }
4826 else {
4827 // Rotate the cycle backward by '-remElements' positions (or
4828 // forward by 'numElements' positions if crossing the boundary
4829 // backward). The transformation is:
4830 //..
4831 // A(*)__B__C__D__ => D__B__C__D(*)__
4832 // => D__B__C(*)__C__
4833 // => D__B(*)__B__C__
4834 //..
4835 // The length of the cycle is always 'length/numCycles', but going
4836 // backward (which adds an initial extra crossing) crosses the
4837 // range boundaries 'remElements/numCycles+1' times each of which
4838 // trigger an extra assignment in the 'if' clause below, so the
4839 // loop must only be executed:
4840 //..
4841 // (length - remElements) / numCycles - 1 =
4842 // numElements / numCycles - 1
4843 //..
4844 // times.
4845
4846 std::size_t cycleSize = numElements / numCycles - 1;
4847
4848 for (std::size_t j = 0; j < cycleSize; ++j) {
4849 if (ptr < end - numElements) {
4850 *ptr = *(ptr + numElements);
4851 ptr += numElements;
4852 }
4853
4854 *ptr = *(ptr - remElements);
4855 ptr -= remElements;
4856 }
4857 }
4858
4859 *ptr = tmp; // Close the cycle, e.g.:
4860 //..
4861 // (first case): B__C__D__D(*)__ => B__C__D__A__
4862 // (second case): D__D(*)__B__C__ => D__A__B__C__
4863 //..
4864 ++begin; // and move on to the next cycle:
4865 //..
4866 // => _W__X__Y__Z_
4867 //..
4868 }
4869}
4870
4871 // *** 'shiftAndInsert' overloads: ***
4872
4873template <class ALLOCATOR>
4874inline
4880 ALLOCATOR allocator,
4882{
4883 BSLS_ASSERT_SAFE(begin != end); // the range is non-empty
4884
4885 typedef typename bsl::allocator_traits<ALLOCATOR>::value_type ValueType;
4886
4887 // ALIASING: If 'value' is a reference into the array '[begin, end)',
4888 // then moving the array first might introduce a change in 'value'.
4889 // Fortunately we can easily predict its new position after the shift.
4890
4891 ValueType *valuePtr =
4893 if (begin <= valuePtr && valuePtr < end) {
4894 valuePtr += 1; // new address after the shift
4895 }
4896
4897#if defined(BSLS_PLATFORM_PRAGMA_GCC_DIAGNOSTIC_GCC)
4898// clang does not support this pragma
4899#pragma GCC diagnostic push
4900#pragma GCC diagnostic ignored "-Wclass-memaccess"
4901#endif
4902
4903 // shift
4904 std::memmove(static_cast<void *>(begin + 1),
4905 begin,
4906 (end - begin) * sizeof(ValueType));
4907
4908 // insert
4910 allocator,
4911 begin,
4913
4914#if defined(BSLS_PLATFORM_PRAGMA_GCC_DIAGNOSTIC_GCC)
4915#pragma GCC diagnostic pop
4916#endif
4917}
4918
4919template <class ALLOCATOR>
4920inline
4926 ALLOCATOR allocator,
4928{
4929 BSLS_ASSERT_SAFE(begin != end); // the range is non-empty
4930
4931 typedef typename bsl::allocator_traits<ALLOCATOR>::value_type ValueType;
4932
4933 // ALIASING: If 'value' is a reference into the array '[begin, end)',
4934 // then moving the array first might introduce a change in 'value'.
4935 // Fortunately we can easily predict its new position after the shift.
4936
4937 ValueType *valuePtr =
4939 if (begin <= valuePtr && valuePtr < end) {
4940 valuePtr += 1; // new address after the shift
4941 }
4942
4943 // shift
4944 size_t bytesNum = (end - begin) * sizeof(ValueType);
4945
4946
4947#if defined(BSLS_PLATFORM_PRAGMA_GCC_DIAGNOSTIC_GCC)
4948// clang does not support this pragma
4949#pragma GCC diagnostic push
4950#pragma GCC diagnostic ignored "-Wclass-memaccess"
4951#endif
4952
4953 std::memmove(static_cast<void *>(begin + 1), begin, bytesNum);
4954
4955
4956 /// Moves the elements back if `construct` throws.
4957 ///
4958 /// See @ref bslalg_arrayprimitives
4959 class ElementsProctor {
4960
4961 // DATA
4962 ValueType *d_begin;
4963 size_t d_bytesNum;
4964 public:
4965 // CREATORS
4966 ElementsProctor(ValueType *p, size_t n) : d_begin(p), d_bytesNum(n) {}
4967 ~ElementsProctor()
4968 {
4969 if(d_bytesNum) std::memmove(static_cast<void *>(d_begin),
4970 d_begin + 1,
4971 d_bytesNum);
4972 }
4973 // MANIPULATORS
4974 void release() { d_bytesNum = 0; }
4975 } proctor(begin, bytesNum);
4976
4977
4978 // insert
4980 allocator,
4981 begin,
4983 proctor.release();
4984#if defined(BSLS_PLATFORM_PRAGMA_GCC_DIAGNOSTIC_GCC)
4985#pragma GCC diagnostic pop
4986#endif
4987}
4988
4989template <class ALLOCATOR>
4990inline
4996 ALLOCATOR allocator,
4998{
4999 BSLS_ASSERT_SAFE(begin != end); // the range is non-empty
5000
5001 typedef typename bsl::allocator_traits<ALLOCATOR>::value_type ValueType;
5002
5003 // ALIASING: If 'value' is a reference into the array '[begin, end)',
5004 // then moving the array first might introduce a change in 'value'.
5005 // Fortunately we can easily predict its new position after the shift.
5006
5007 ValueType *valuePtr =
5009 if (begin <= valuePtr && valuePtr < end) {
5010 valuePtr += 1; // new address after the shift
5011 }
5012
5013 // Key to the transformation diagrams:
5014 //..
5015 // A...G original contents of '[toBegin, toEnd)' ("tail")
5016 // a...g moved-from or copied values
5017 // v moved 'value' ("input")
5018 // _____ uninitialized array elements
5019 // [...] part of array protected by an exception guard object
5020 //..
5021
5022 //..
5023 // Transformation: ABCDEFG_[] => ABCDEFg[G].
5024 //..
5025
5027 allocator,
5028 end,
5030
5032 end, end + 1, allocator);
5033
5034 //..
5035 // Transformation: ABCDEFg[G] => aABCDEF[G].
5036 //..
5037
5038 ValueType *dst = end;
5039 ValueType *src = end - 1;
5040 while (src != begin) {
5042 }
5043
5044 //..
5045 // Transformation: aABCDEFG[G] => vABCDEF[G].
5046 //..
5047
5048 *begin = bslmf::MovableRefUtil::move_if_noexcept(*valuePtr);
5049
5050 guard.release();
5051}
5052
5053} // close package namespace
5054
5055#ifndef BDE_OPENSOURCE_PUBLICATION // BACKWARD_COMPATIBILITY
5056// ============================================================================
5057// BACKWARD COMPATIBILITY
5058// ============================================================================
5059
5060/// This alias is defined for backward compatibility.
5062#endif // BDE_OPENSOURCE_PUBLICATION -- BACKWARD_COMPATIBILITY
5063
5064
5065
5066#if defined(BSLALG_ARRAYPRIMITIVES_CANNOT_REMOVE_POINTER_FROM_FUNCTION_POINTER)
5067# undef BSLALG_ARRAYPRIMITIVES_CANNOT_REMOVE_POINTER_FROM_FUNCTION_POINTER
5068#endif
5069
5070#endif // End C++11 code
5071
5072#endif
5073
5074// ----------------------------------------------------------------------------
5075// Copyright 2013 Bloomberg Finance L.P.
5076//
5077// Licensed under the Apache License, Version 2.0 (the "License");
5078// you may not use this file except in compliance with the License.
5079// You may obtain a copy of the License at
5080//
5081// http://www.apache.org/licenses/LICENSE-2.0
5082//
5083// Unless required by applicable law or agreed to in writing, software
5084// distributed under the License is distributed on an "AS IS" BASIS,
5085// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
5086// See the License for the specific language governing permissions and
5087// limitations under the License.
5088// ----------------------------- END-OF-FILE ----------------------------------
5089
5090/** @} */
5091/** @} */
5092/** @} */
Definition bslalg_autoarraydestructor.h:232
OBJECT_TYPE * moveEnd(difference_type offset=1)
Definition bslalg_autoarraydestructor.h:331
OBJECT_TYPE * moveBegin(difference_type offset=-1)
Definition bslalg_autoarraydestructor.h:318
void release()
Definition bslalg_autoarraydestructor.h:342
Definition bslalg_autoarraymovedestructor.h:419
OBJECT_TYPE * middle() const
Return the address at the middle of the guarded range.
Definition bslalg_autoarraymovedestructor.h:582
OBJECT_TYPE * destination() const
Definition bslalg_autoarraymovedestructor.h:568
void advance()
Definition bslalg_autoarraymovedestructor.h:547
OBJECT_TYPE * end() const
Return the address at the end of the guarded range.
Definition bslalg_autoarraymovedestructor.h:575
Definition bslma_allocator.h:545
Definition bslma_destructorproctor.h:259
Definition bslmf_movableref.h:752
bslalg::ArrayPrimitives bslalg_ArrayPrimitives
This alias is defined for backward compatibility.
Definition bslalg_arrayprimitives.h:5061
#define BSLMF_ASSERT(expr)
Definition bslmf_assert.h:231
#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_PERFORMANCEHINT_PREDICT_LIKELY(expr)
Definition bsls_performancehint.h:451
#define BSLS_UTIL_ADDRESSOF(OBJ)
Definition bsls_util.h:296
Definition bdlc_flathashmap.h:2218
static void construct(ALLOCATOR_TYPE &basicAllocator, ELEMENT_TYPE *elementAddr, Args &&... arguments)
Definition bslma_allocatortraits.h:1527
BloombergLP::bslma::AllocatorTraits_PointerType< ALLOCATOR_TYPE >::type pointer
Definition bslma_allocatortraits.h:1180
ALLOCATOR_TYPE::value_type value_type
Definition bslma_allocatortraits.h:1176
Definition bslmf_integralconstant.h:261
Definition bslmf_isenum.h:272
Definition bslmf_isfundamental.h:330
Definition bslmf_ismemberpointer.h:143
Definition bslmf_ispointer.h:138
Definition bslmf_issame.h:146
Definition bslmf_istriviallydefaultconstructible.h:296
Definition bslmf_isvoid.h:138
Definition bslmf_removecv.h:120
Definition bslmf_removepointer.h:262
BloombergLP::bslmf::RemovePointer_Imp< t_TYPE >::Type type
Definition bslmf_removepointer.h:274
static void destroy(TARGET_TYPE *begin, TARGET_TYPE *end, ALLOCATOR allocator, bsl::true_type)
Definition bslalg_arraydestructionprimitives.h:238
Definition bslalg_arrayprimitives.h:1961
Definition bslalg_arrayprimitives.h:1242
static void emplace(TARGET_TYPE *toBegin, TARGET_TYPE *toEnd, ALLOCATOR allocator, bsl::integral_constant< int, e_BITWISE_COPYABLE_TRAITS >, ARGS &&... args)
TBD: document this.
Definition bslalg_arrayprimitives.h:3762
static void uninitializedFillN(bsls::Types::Int64 *begin, bsls::Types::Int64 value, size_type numElements, void *=0, bsl::integral_constant< int, e_IS_FUNDAMENTAL_OR_POINTER >=bsl::integral_constant< int, e_IS_FUNDAMENTAL_OR_POINTER >())
static void moveConstruct(TARGET_TYPE *toBegin, TARGET_TYPE *fromBegin, TARGET_TYPE *fromEnd, ALLOCATOR allocator, bsl::integral_constant< int, e_BITWISE_COPYABLE_TRAITS >)
Definition bslalg_arrayprimitives.h:3584
static void copyConstruct(TARGET_TYPE *toBegin, FWD_ITER fromBegin, SENTINEL fromEnd, ALLOCATOR allocator, bsl::integral_constant< int, e_IS_ITERATOR_TO_FUNCTION_POINTER >)
static void bitwiseRotateBackward(char *begin, char *middle, char *end)
static void uninitializedFillN(float *begin, float value, size_type numElements, void *=0, bsl::integral_constant< int, e_IS_FUNDAMENTAL_OR_POINTER >=bsl::integral_constant< int, e_IS_FUNDAMENTAL_OR_POINTER >())
static void bitwiseRotate(char *begin, char *middle, char *end)
static void uninitializedFillN(volatile void **begin, volatile void *value, size_type numElements, void *=0, bsl::integral_constant< int, e_IS_FUNDAMENTAL_OR_POINTER >=bsl::integral_constant< int, e_IS_FUNDAMENTAL_OR_POINTER >())
static void shiftAndInsert(typename bsl::allocator_traits< ALLOCATOR >::pointer begin, typename bsl::allocator_traits< ALLOCATOR >::pointer end, bslmf::MovableRef< typename bsl::allocator_traits< ALLOCATOR >::value_type > value, ALLOCATOR allocator, bsl::integral_constant< int, e_BITWISE_COPYABLE_TRAITS >)
Definition bslalg_arrayprimitives.h:4875
@ k_INPLACE_BUFFER_SIZE
Definition bslalg_arrayprimitives.h:1298
static void bitwiseFillN(char *begin, size_type numBytesInitialized, size_type numBytes)
static void bitwiseSwapRanges(char *begin, char *middle, char *end)
static void uninitializedFillN(bool *begin, bool value, size_type numElements, void *=0, bsl::integral_constant< int, e_IS_FUNDAMENTAL_OR_POINTER >=bsl::integral_constant< int, e_IS_FUNDAMENTAL_OR_POINTER >())
Definition bslalg_arrayprimitives.h:3128
static void moveInsert(TARGET_TYPE *toBegin, TARGET_TYPE *toEnd, TARGET_TYPE **lastPtr, TARGET_TYPE *first, TARGET_TYPE *last, size_type numElements, ALLOCATOR allocator, bsl::integral_constant< int, e_BITWISE_MOVEABLE_TRAITS >)
Definition bslalg_arrayprimitives.h:4664
static void uninitializedFillN(double *begin, double value, size_type numElements, void *=0, bsl::integral_constant< int, e_IS_FUNDAMENTAL_OR_POINTER >=bsl::integral_constant< int, e_IS_FUNDAMENTAL_OR_POINTER >())
static void moveIfNoexcept(TARGET_TYPE *toBegin, TARGET_TYPE *fromBegin, TARGET_TYPE *fromEnd, ALLOCATOR allocator, bsl::integral_constant< int, e_NIL_TRAITS >)
Definition bslalg_arrayprimitives.h:3629
ArrayPrimitives::difference_type difference_type
Definition bslalg_arrayprimitives.h:1277
static void bitwiseRotateForward(char *begin, char *middle, char *end)
static void uninitializedFillN(short *begin, short value, size_type numElements, void *=0, bsl::integral_constant< int, e_IS_FUNDAMENTAL_OR_POINTER >=bsl::integral_constant< int, e_IS_FUNDAMENTAL_OR_POINTER >())
@ e_BITWISE_MOVEABLE_TRAITS
Definition bslalg_arrayprimitives.h:1290
@ e_HAS_TRIVIAL_DEFAULT_CTOR_TRAITS
Definition bslalg_arrayprimitives.h:1288
@ e_NIL_TRAITS
Definition bslalg_arrayprimitives.h:1291
@ e_BITWISE_COPYABLE_TRAITS
Definition bslalg_arrayprimitives.h:1289
@ e_IS_FUNDAMENTAL_OR_POINTER
Definition bslalg_arrayprimitives.h:1287
@ e_IS_ITERATOR_TO_FUNCTION_POINTER
Definition bslalg_arrayprimitives.h:1285
@ e_IS_POINTER_TO_POINTER
Definition bslalg_arrayprimitives.h:1286
ArrayPrimitives::size_type size_type
Definition bslalg_arrayprimitives.h:1276
static bool isInvalidRange(FORWARD_ITERATOR begin, SENTINEL end)
Definition bslalg_arrayprimitives.h:3092
static void destructiveMove(TARGET_TYPE *toBegin, TARGET_TYPE *fromBegin, TARGET_TYPE *fromEnd, ALLOCATOR allocator, bsl::integral_constant< int, e_BITWISE_MOVEABLE_TRAITS >)
Definition bslalg_arrayprimitives.h:3718
static void uninitializedFillN(void **begin, void *value, size_type numElements, void *=0, bsl::integral_constant< int, e_IS_FUNDAMENTAL_OR_POINTER >=bsl::integral_constant< int, e_IS_FUNDAMENTAL_OR_POINTER >())
static void uninitializedFillN(int *begin, int value, size_type numElements, void *=0, bsl::integral_constant< int, e_IS_FUNDAMENTAL_OR_POINTER >=bsl::integral_constant< int, e_IS_FUNDAMENTAL_OR_POINTER >())
static void uninitializedFillN(const volatile void **begin, const volatile void *value, size_type numElements, void *=0, bsl::integral_constant< int, e_IS_FUNDAMENTAL_OR_POINTER >=bsl::integral_constant< int, e_IS_FUNDAMENTAL_OR_POINTER >())
static void erase(TARGET_TYPE *first, TARGET_TYPE *middle, TARGET_TYPE *last, ALLOCATOR allocator, bsl::integral_constant< int, e_BITWISE_MOVEABLE_TRAITS >)
Definition bslalg_arrayprimitives.h:3947
static void rotate(TARGET_TYPE *begin, TARGET_TYPE *middle, TARGET_TYPE *end, bsl::integral_constant< int, e_BITWISE_MOVEABLE_TRAITS >)
Definition bslalg_arrayprimitives.h:4720
static void uninitializedFillN(long double *begin, long double value, size_type numElements, void *=0, bsl::integral_constant< int, e_IS_FUNDAMENTAL_OR_POINTER >=bsl::integral_constant< int, e_IS_FUNDAMENTAL_OR_POINTER >())
static void insert(TARGET_TYPE *toBegin, TARGET_TYPE *toEnd, const TARGET_TYPE &value, size_type numElements, ALLOCATOR allocator, bsl::integral_constant< int, e_BITWISE_COPYABLE_TRAITS >)
Definition bslalg_arrayprimitives.h:4016
static void copyConstruct(TARGET_TYPE *toBegin, FWD_ITER fromBegin, SENTINEL fromEnd, ALLOCATOR allocator, bsl::integral_constant< int, e_IS_POINTER_TO_POINTER >)
Definition bslalg_arrayprimitives.h:3471
static void defaultConstruct(TARGET_TYPE *begin, size_type numElements, ALLOCATOR allocator, bsl::integral_constant< int, e_HAS_TRIVIAL_DEFAULT_CTOR_TRAITS >)
Definition bslalg_arrayprimitives.h:3659
static void uninitializedFillN(const void **begin, const void *value, size_type numElements, void *=0, bsl::integral_constant< int, e_IS_FUNDAMENTAL_OR_POINTER >=bsl::integral_constant< int, e_IS_FUNDAMENTAL_OR_POINTER >())
Definition bslalg_arrayprimitives.h:424
static void destructiveMoveAndMoveInsert(typename bsl::allocator_traits< ALLOCATOR >::pointer toBegin, typename bsl::allocator_traits< ALLOCATOR >::pointer *fromEndPtr, typename bsl::allocator_traits< ALLOCATOR >::pointer *lastPtr, typename bsl::allocator_traits< ALLOCATOR >::pointer fromBegin, typename bsl::allocator_traits< ALLOCATOR >::pointer position, typename bsl::allocator_traits< ALLOCATOR >::pointer fromEnd, typename bsl::allocator_traits< ALLOCATOR >::pointer first, typename bsl::allocator_traits< ALLOCATOR >::pointer last, size_type numElements, ALLOCATOR allocator)
Definition bslalg_arrayprimitives.h:2553
static void destructiveMoveAndEmplace(typename bsl::allocator_traits< ALLOCATOR >::pointer toBegin, typename bsl::allocator_traits< ALLOCATOR >::pointer *fromEndPtr, typename bsl::allocator_traits< ALLOCATOR >::pointer fromBegin, typename bsl::allocator_traits< ALLOCATOR >::pointer position, typename bsl::allocator_traits< ALLOCATOR >::pointer fromEnd, ALLOCATOR allocator, ARGS &&... arguments)
Definition bslalg_arrayprimitives.h:2211
ArrayPrimitives_Imp Imp
Definition bslalg_arrayprimitives.h:428
static void insert(typename bsl::allocator_traits< ALLOCATOR >::pointer toBegin, typename bsl::allocator_traits< ALLOCATOR >::pointer toEnd, bslmf::MovableRef< typename bsl::allocator_traits< ALLOCATOR >::value_type > value, ALLOCATOR allocator)
Definition bslalg_arrayprimitives.h:2745
static void destructiveMove(typename bsl::allocator_traits< ALLOCATOR >::pointer toBegin, typename bsl::allocator_traits< ALLOCATOR >::pointer fromBegin, typename bsl::allocator_traits< ALLOCATOR >::pointer fromEnd, ALLOCATOR allocator)
Definition bslalg_arrayprimitives.h:2172
static void defaultConstruct(typename bsl::allocator_traits< ALLOCATOR >::pointer begin, size_type numElements, ALLOCATOR allocator)
Definition bslalg_arrayprimitives.h:2129
static void moveInsert(typename bsl::allocator_traits< ALLOCATOR >::pointer toBegin, typename bsl::allocator_traits< ALLOCATOR >::pointer toEnd, typename bsl::allocator_traits< ALLOCATOR >::pointer *fromEndPtr, typename bsl::allocator_traits< ALLOCATOR >::pointer fromBegin, typename bsl::allocator_traits< ALLOCATOR >::pointer fromEnd, size_type numElements, ALLOCATOR allocator)
Definition bslalg_arrayprimitives.h:3007
static void copyConstruct(typename bsl::allocator_traits< ALLOCATOR >::pointer toBegin, FWD_ITER fromBegin, SENTINEL fromEnd, ALLOCATOR allocator)
Definition bslalg_arrayprimitives.h:2024
static void emplace(typename bsl::allocator_traits< ALLOCATOR >::pointer toBegin, typename bsl::allocator_traits< ALLOCATOR >::pointer toEnd, ALLOCATOR allocator, ARGS &&... arguments)
Definition bslalg_arrayprimitives.h:2656
static void moveConstruct(typename bsl::allocator_traits< ALLOCATOR >::pointer toBegin, typename bsl::allocator_traits< ALLOCATOR >::pointer fromBegin, typename bsl::allocator_traits< ALLOCATOR >::pointer fromEnd, ALLOCATOR allocator)
Definition bslalg_arrayprimitives.h:2969
static void destructiveMoveAndInsert(typename bsl::allocator_traits< ALLOCATOR >::pointer toBegin, typename bsl::allocator_traits< ALLOCATOR >::pointer *fromEndPtr, typename bsl::allocator_traits< ALLOCATOR >::pointer fromBegin, typename bsl::allocator_traits< ALLOCATOR >::pointer position, typename bsl::allocator_traits< ALLOCATOR >::pointer fromEnd, size_type numElements, ALLOCATOR allocator)
Definition bslalg_arrayprimitives.h:2282
std::ptrdiff_t difference_type
Definition bslalg_arrayprimitives.h:430
static void erase(typename bsl::allocator_traits< ALLOCATOR >::pointer first, typename bsl::allocator_traits< ALLOCATOR >::pointer middle, typename bsl::allocator_traits< ALLOCATOR >::pointer last, ALLOCATOR allocator)
Definition bslalg_arrayprimitives.h:2702
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
std::size_t size_type
Definition bslalg_arrayprimitives.h:429
static void rotate(TARGET_TYPE *first, TARGET_TYPE *middle, TARGET_TYPE *last)
Definition bslalg_arrayprimitives.h:3054
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
static MovableRef< t_TYPE > move(t_TYPE &reference) BSLS_KEYWORD_NOEXCEPT
Definition bslmf_movableref.h:1067
static t_TYPE & access(t_TYPE &ref) BSLS_KEYWORD_NOEXCEPT
Definition bslmf_movableref.h:1039
static bsl::enable_if<!bsl::is_nothrow_move_constructible< t_TYPE >::value &&bsl::is_copy_constructible< t_TYPE >::value, constt_TYPE & >::type move_if_noexcept(t_TYPE &lvalue) BSLS_KEYWORD_NOEXCEPT
Definition bslmf_movableref.h:919
@ BSLS_MAX_ALIGNMENT
Definition bsls_alignmentutil.h:300
unsigned long long Uint64
Definition bsls_types.h:139
long long Int64
Definition bsls_types.h:134
Definition bsls_objectbuffer.h:277
TYPE & object()
Definition bsls_objectbuffer.h:352