BDE 4.14.0 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// Include version that can be compiled with C++03
388// Generated on Thu Oct 21 10:11:37 2021
389// Command line: sim_cpp11_features.pl bslalg_arrayprimitives.h
390# define COMPILING_BSLALG_ARRAYPRIMITIVES_H
392# undef COMPILING_BSLALG_ARRAYPRIMITIVES_H
393#else
394
395#if defined(BSLS_PLATFORM_CMP_IBM) // IBM needs specific workarounds.
396# define BSLALG_ARRAYPRIMITIVES_CANNOT_REMOVE_POINTER_FROM_FUNCTION_POINTER 1
397 // xlC has problem removing pointer from function pointer types.
398
399# define BSLALG_ARRAYPRIMITIVES_NON_ZERO_NULL_VALUE_FOR_MEMBER_POINTERS 1
400 // xlC representation for a null member pointer is not all zero bits.
401#endif
402
403
404
405namespace bslalg {
406
407struct ArrayPrimitives_Imp;
408
409 // ======================
410 // struct ArrayPrimitives
411 // ======================
412
413/// This `struct` provides a namespace for a suite of independent utility
414/// functions that operate on arrays of elements of parameterized type
415/// `TARGET_TYPE`. Depending on the traits of `TARGET_TYPE`, the default
416/// and copy constructors, destructor, assignment operators, etcetera may
417/// not be invoked, optimized away by no-op or bit-wise move or copy.
419
420 public:
421 // TYPES
423 typedef std::size_t size_type;
424 typedef std::ptrdiff_t difference_type;
425
426 // CLASS METHODS
427
428 /// Copy the elements of type `allocator_traits<ALLOCATOR>::value_type`
429 /// in the range beginning at the specified `fromBegin` location and
430 /// ending immediately before the specified `fromEnd` location into the
431 /// uninitialized array beginning at the specified `toBegin` location,
432 /// using the specified `allocator` to supply memory (if required). If
433 /// a constructor throws an exception during this operation, the output
434 /// array is left in an uninitialized state. The behavior is undefined
435 /// unless `toBegin` refers to space sufficient to hold
436 /// `fromEnd - fromBegin` elements.
437 template <class ALLOCATOR, class FWD_ITER>
438 static void
441 FWD_ITER fromBegin,
442 FWD_ITER fromEnd,
443 ALLOCATOR allocator);
444 template <class ALLOCATOR, class SOURCE_TYPE>
445 static void
448 SOURCE_TYPE *fromBegin,
449 SOURCE_TYPE *fromEnd,
450 ALLOCATOR allocator);
451
452 /// Copy into an uninitialized array of (the template parameter)
453 /// `TARGET_TYPE` beginning at the specified `toBegin` address, the
454 /// elements in the array of `TARGET_TYPE` starting at the specified
455 /// `fromBegin` address and ending immediately before the specified
456 /// `fromEnd` address. If the (template parameter) `ALLOCATOR` type is
457 /// derived from `bslma::Allocator` and `TARGET_TYPE` supports `bslma`
458 /// allocators, then the specified `allocator` is passed to each
459 /// invocation of the `TARGET_TYPE` copy constructor. If a
460 /// `TARGET_TYPE` constructor throws an exception during the operation,
461 /// then the destructor is called on any newly-constructed elements,
462 /// leaving the output array in an uninitialized state.
463 template <class TARGET_TYPE, class FWD_ITER>
464 static void copyConstruct(TARGET_TYPE *toBegin,
465 FWD_ITER fromBegin,
466 FWD_ITER fromEnd,
467 bslma::Allocator *allocator);
468 template <class TARGET_TYPE, class SOURCE_TYPE>
469 static void copyConstruct(TARGET_TYPE *toBegin,
470 SOURCE_TYPE *fromBegin,
471 SOURCE_TYPE *fromEnd,
472 bslma::Allocator *allocator);
473
474 /// Move the elements of type `allocator_traits<ALLOCATOR>::value_type`
475 /// in the range beginning at the specified `fromBegin` location and
476 /// ending immediately before the specified `fromEnd` location into the
477 /// uninitialized array beginning at the specified `toBegin` location,
478 /// using the specified `allocator` to supply memory (if required). The
479 /// elements in the input array are left in a valid but unspecified
480 /// state. If a constructor throws an exception during this operation,
481 /// the output array is left in an uninitialized state. The behavior is
482 /// undefined unless `toBegin` refers to space sufficient to hold
483 /// `fromEnd - fromBegin` elements.
484 template <class ALLOCATOR>
485 static void
490 ALLOCATOR allocator);
491
492 /// Move the elements of the (template parameter) `TARGET_TYPE` starting
493 /// at the specified `fromBegin` address and ending immediately before
494 /// the specified `fromEnd` address into the uninitialized array of
495 /// `TARGET_TYPE` beginning at the specified `toBegin` address, using
496 /// the specified `allocator` to supply memory (if required). The
497 /// elements in the input array are left in a valid but unspecified
498 /// state. If a constructor throws an exception during this operation,
499 /// the output array is left in an uninitialized state. The behavior is
500 /// undefined unless `toBegin` refers to space sufficient to hold
501 /// `fromEnd - fromBegin` elements.
502 template <class TARGET_TYPE>
503 static void moveConstruct(TARGET_TYPE *toBegin,
504 TARGET_TYPE *fromBegin,
505 TARGET_TYPE *fromEnd,
506 bslma::Allocator *allocator);
507
508 /// Value-inititalize the specified `numElements` objects of type
509 /// `allocator_traits<ALLOCATOR>::value_type` into the uninitialized
510 /// array beginning at the specified `begin` location, using the
511 /// specified `allocator` to supply memory (if required). If a
512 /// constructor throws an exception during this operation, then the
513 /// destructor is called on any newly constructed elements, leaving the
514 /// output array in an uninitialized state. The behavior is undefined
515 /// unless the `begin` refers to space sufficient to hold `numElements`.
516 template <class ALLOCATOR>
517 static void defaultConstruct(
519 size_type numElements,
520 ALLOCATOR allocator);
521
522 /// Construct each of the elements of an array of the specified
523 /// `numElements` of the parameterized `TARGET_TYPE` starting at the
524 /// specified `begin` address by value-initialization. If the (template
525 /// parameter) `ALLOCATOR` type is derived from `bslma::Allocator` and
526 /// `TARGET_TYPE` supports `bslma` allocators, then the specified
527 /// `allocator` is passed to each `TARGET_TYPE` default constructor
528 /// call. The behavior is undefined unless the output array contains at
529 /// least `numElements` uninitialized elements after `begin`. If a
530 /// `TARGET_TYPE` constructor throws an exception during this operation,
531 /// then the destructor is called on any newly-constructed elements,
532 /// leaving the output array in an uninitialized state.
533 template <class TARGET_TYPE>
534 static void defaultConstruct(TARGET_TYPE *begin,
535 size_type numElements,
536 bslma::Allocator *allocator);
537
538 /// Move the elements of type `allocator_traits<ALLOCATOR>::value_type`
539 /// in the range beginning at the specified `fromBegin` location and
540 /// ending immediately before the specified `fromEnd` location into the
541 /// uninitialized array beginning at the specified `toBegin` location,
542 /// using the specified `allocator` to supply memory (if required). On
543 /// return, the elements in the input range are invalid, i.e., their
544 /// destructors must not be called after this operation returns. If a
545 /// constructor throws an exception during this operation, the output
546 /// array is left in an uninitialized state. If a constructor other
547 /// than the move constructor of a non-copy-constructible type throws
548 /// an exception during this operation, the input array is unaffected;
549 /// otherwise, if the move constructor of a non-copy-constructible type
550 /// throws an exception during this operation, the input array is left
551 /// in a valid but unspecified state. The behavior is undefined unless
552 /// `toBegin` refers to space sufficient to hold `fromEnd - fromBegin`
553 /// elements.
554 template <class ALLOCATOR>
555 static void destructiveMove(
559 ALLOCATOR allocator);
560
561 /// Move the elements of the parameterized `TARGET_TYPE` in the array
562 /// starting at the specified `fromBegin` address and ending immediately
563 /// before the specified `fromEnd` address into an uninitialized array
564 /// of `TARGET_TYPE` beginning at the specified `toBegin` address. On
565 /// return, the elements in the input range are invalid, i.e., their
566 /// destructors must not be called after this operation returns. If the
567 /// parameterized `ALLOCATOR` type is derived from `bslma::Allocator`
568 /// and `TARGET_TYPE` supports `bslma` allocators, then the specified
569 /// `allocator` is used by the objects in their new location. If an
570 /// exception is thrown by a `TARGET_TYPE` constructor during the
571 /// operation, then the output array is left in an uninitialized state
572 /// and the input elements remain in their original state.
573 template <class TARGET_TYPE>
574 static void destructiveMove(TARGET_TYPE *toBegin,
575 TARGET_TYPE *fromBegin,
576 TARGET_TYPE *fromEnd,
577 bslma::Allocator *allocator);
578
579#if !BSLS_COMPILERFEATURES_SIMULATE_CPP11_FEATURES // $var-args=10
580
581 /// Move the elements of type `allocator_traits<ALLOCATOR>::value_type`
582 /// in the specified range `[fromBegin .. fromEnd)` into the
583 /// uninitialized array beginning at the specified `toBegin` location,
584 /// using the specified `allocator` to supply memory (if required),
585 /// inserting at the specified `position` (after translating from
586 /// `fromBegin` to `toBegin`) a newly created object constructed by
587 /// forwarding `allocator` (if required) and the specified (variable
588 /// number of) `arguments` to the corresponding constructor of the
589 /// target type, ensuring that the specified `fromEndPtr` points to the
590 /// first uninitialized element in `[fromBegin .. fromEnd)` as the
591 /// elements are moved from source to destination. On return, the
592 /// elements in the input range are invalid, i.e., their destructors
593 /// must not be called after this operation returns. If a constructor
594 /// throws an exception during this operation, the output array is left
595 /// in an uninitialized state. If an exception is thrown during the
596 /// in-place construction of the new object, the input array is
597 /// unaffected; otherwise, if a (copy or move) constructor throws an
598 /// exception during this operation, the input elements in the range
599 /// `[fromBegin .. *fromEndPtr)` are left in a valid but unspecified
600 /// state and the remaining portion of the input array is left in an
601 /// uninitialized state. The behavior is undefined unless
602 /// `fromBegin <= position <= fromEnd` and `toBegin` refers to space
603 /// sufficient to hold `fromEnd - fromBegin + 1` elements.
604 template <class ALLOCATOR, class... ARGS>
605 static void destructiveMoveAndEmplace(
611 ALLOCATOR allocator,
612 ARGS&&... arguments);
613
614#endif
615
616 /// Move the elements of type `allocator_traits<ALLOCATOR>::value_type`
617 /// in the range beginning at the specified `fromBegin` location and
618 /// ending immediately before the specified `fromEnd` location into the
619 /// uninitialized array beginning at the specified `toBegin` location
620 /// using the specified `allocator` to supply memory (if required),
621 /// inserting at the specified `position` (after translating from
622 /// `fromBegin` to `toBegin`) the specified `numElements` objects
623 /// initialized to default values, ensuring that the specified
624 /// `fromEndPtr` points to the first uninitialized element in
625 /// `[fromBegin .. fromEnd)` as the elements are moved from source to
626 /// destination. On return, the elements in the input range are
627 /// invalid, i.e., their destructors must not be called after this
628 /// operation returns. If a constructor throws an exception during this
629 /// operation, the output array is left in an uninitialized state. If a
630 /// default constructor throws an exception, the input array is
631 /// unaffected; otherwise, if a (copy or move) constructor throws an
632 /// exception during this operation, the input elements in the range
633 /// `[fromBegin .. *fromEndPtr)` are left in a valid but unspecified
634 /// state and the remaining portion of the input array is left in an
635 /// uninitialized state. The behavior is undefined unless 'fromBegin <=
636 /// position <= fromEnd' and `toBegin` refers to space sufficient to
637 /// hold `fromEnd - fromBegin + 1` elements.
638 template <class ALLOCATOR>
639 static void destructiveMoveAndInsert(
645 size_type numElements,
646 ALLOCATOR allocator);
647
648 /// Move the elements of the (template parameter) `TARGET_TYPE` in the
649 /// starting at the specified `fromBegin` address and ending immediately
650 /// before the specified `fromEnd` address into the uninitialized array
651 /// beginning at the specified `toBegin` location using the specified
652 /// `allocator` to supply memory (if required), inserting at the
653 /// specified `position` (after translating from `fromBegin` to
654 /// `toBegin`) `numElements` objects initialized to default values,
655 /// ensuring that the specified `fromEndPtr` points to the first
656 /// uninitialized element in `[fromBegin .. fromEnd)` as the elements
657 /// are moved from source to destination. On return, the elements in
658 /// the input range are invalid, i.e., their destructors must not be
659 /// called after this operation returns. If a constructor throws an
660 /// exception during this operation, the output array is left in an
661 /// uninitialized state. If a default constructor throws an exception,
662 /// the input array is unaffected; otherwise, if a (copy or move)
663 /// constructor throws an exception during this operation, the input
664 /// elements in the range `[fromBegin .. *fromEndPtr)` are left in a
665 /// valid but unspecified state and the remaining portion of the input
666 /// array is left in an uninitialized state. The behavior is undefined
667 /// unless `fromBegin <= position <= fromEnd` and `toBegin` refers to
668 /// space sufficient to hold `fromEnd - fromBegin + numElements`
669 /// elements.
670 template <class TARGET_TYPE>
671 static void destructiveMoveAndInsert(TARGET_TYPE *toBegin,
672 TARGET_TYPE **fromEndPtr,
673 TARGET_TYPE *fromBegin,
674 TARGET_TYPE *position,
675 TARGET_TYPE *fromEnd,
676 size_type numElements,
677 bslma::Allocator *allocator);
678
679 /// Move the elements of type `allocator_traits<ALLOCATOR>::value_type`
680 /// in the range beginning at the specified `fromBegin` location and
681 /// ending immediately before the specified `fromEnd` location into the
682 /// uninitialized array beginning at the specified `toBegin` location
683 /// using the specified `allocator` to supply memory (if required),
684 /// inserting at the specified `position` (after translating from
685 /// `fromBegin` to `toBegin`) the specified `numElements` copies of the
686 /// specified `value`, ensuring that the specified `fromEndPtr` points
687 /// to the first uninitialized element in `[fromBegin .. fromEnd)` as
688 /// the elements are moved from source to destination. On return, the
689 /// elements in the input range are invalid, i.e., their destructors
690 /// must not be called after this operation returns. If a constructor
691 /// throws an exception during this operation, the output array is left
692 /// in an uninitialized state. If a (copy or move) constructor throws
693 /// an exception during this operation, the input elements in the range
694 /// `[fromBegin .. *fromEndPtr)` are left in a valid but unspecified
695 /// state and the remaining portion of the input array is left in an
696 /// uninitialized state. The behavior is undefined unless
697 /// `fromBegin <= position <= fromEnd` and `toBegin` refers to space
698 /// sufficient to hold `fromEnd - fromBegin + numElements` elements.
699 template <class ALLOCATOR>
700 static void destructiveMoveAndInsert(
707 size_type numElements,
708 ALLOCATOR allocator);
709
710 /// Move the elements of the parameterized `TARGET_TYPE` in the array
711 /// starting at the specified `fromBegin` address and ending immediately
712 /// before the specified `fromEnd` address into an uninitialized array
713 /// of `TARGET_TYPE` at the specified `toBegin` address, inserting at
714 /// the specified `position` (after translating from `fromBegin` to
715 /// `toBegin`) the specified `numElements` copies of the specified
716 /// `value`. Keep the pointer at the specified `fromEndPtr` address
717 /// pointing to the first uninitialized element in '[ fromBegin,
718 /// fromEnd)' as the elements are moved from source to destination. The
719 /// behavior is undefined unless `fromBegin <= position <= fromEnd` and
720 /// the destination array contains at least
721 /// `(fromEnd - fromBegin) + numElements` uninitialized elements. If a
722 /// copy constructor or assignment operator for `TARGET_TYPE` throws an
723 /// exception, then any elements created in the output array are
724 /// destroyed and the elements in the range `[ fromBegin, *fromEndPtr )`
725 /// will have unspecified but valid values.
726 template <class TARGET_TYPE>
727 static void destructiveMoveAndInsert(TARGET_TYPE *toBegin,
728 TARGET_TYPE **fromEndPtr,
729 TARGET_TYPE *fromBegin,
730 TARGET_TYPE *position,
731 TARGET_TYPE *fromEnd,
732 const TARGET_TYPE& value,
733 size_type numElements,
734 bslma::Allocator *allocator);
735
736 /// Move the elements of type `allocator_traits<ALLOCATOR>::value_type`
737 /// in the range beginning at the specified `fromBegin` location and
738 /// ending immediately before the specified `fromEnd` location into the
739 /// uninitialized array beginning at the specified `toBegin` location
740 /// using the specified `allocator` to supply memory (if required),
741 /// inserting at the specified `position` (after translating from
742 /// `fromBegin` to `toBegin`) the specified `numElements` copies of the
743 /// non-modifiable elements from the range starting at the specified
744 /// `first` iterator of (template parameter) type `FWD_ITER` and ending
745 /// immediately before the specified `last` iterator, ensuring that the
746 /// specified `fromEndPtr` points to the first uninitialized element in
747 /// `[fromBegin .. fromEnd)` as the elements are moved from source to
748 /// destination. On return, the elements in the input range are
749 /// invalid, i.e., their destructors must not be called after this
750 /// operation returns. If a constructor throws an exception during this
751 /// operation, the output array is left in an uninitialized state. If
752 /// a constructor other than the copy or move constructor throws an
753 /// exception during this operation, the input array is unaffected;
754 /// otherwise, if a copy or move constructor throws an exception during
755 /// this operation, the input elements in the range
756 /// `[fromBegin .. *fromEndPtr)` are left in a valid but unspecified
757 /// state and the remaining portion of the input array is left in an
758 /// uninitialized state. The behavior is undefined unless
759 /// `fromBegin <= position <= fromEnd` and `toBegin` refers to space
760 /// sufficient to hold `fromEnd - fromBegin + numElements` elements.
761 template <class ALLOCATOR, class FWD_ITER>
762 static void destructiveMoveAndInsert(
768 FWD_ITER first,
769 FWD_ITER last,
770 size_type numElements,
771 ALLOCATOR allocator);
772
773 /// Move the elements of the parameterized `TARGET_TYPE` in the array
774 /// starting at the specified `fromBegin` address and ending immediately
775 /// before the specified `fromEnd` address into an uninitialized array
776 /// of `TARGET_TYPE` at the specified `toBegin` address, inserting at
777 /// the specified `position` (after translating from `fromBegin` to
778 /// `toBegin`) the specified `numElements` copies of the non-modifiable
779 /// elements from the range starting at the specified `first` iterator
780 /// of the parameterized `FWD_ITER` type and ending immediately before
781 /// the specified `last` iterator. Keep the pointer at the specified
782 /// `fromEndPtr` to point to the first uninitialized element in
783 /// `[fromBegin, fromEnd)` as the elements are moved from source to
784 /// destination. The behavior is undefined unless
785 /// `fromBegin <= position <= fromEnd`, the destination array contains
786 /// at least `(fromEnd - fromBegin) + numElements` uninitialized
787 /// elements after `toBegin`, and `numElements` is the distance from
788 /// `first` to `last`. If a copy constructor or assignment operator for
789 /// `TARGET_TYPE` throws an exception, then any elements created in the
790 /// output array are destroyed and the elements in the range
791 /// `[ fromBegin, *fromEndPtr )` will have unspecified but valid values.
792 template <class TARGET_TYPE, class FWD_ITER>
793 static void destructiveMoveAndInsert(TARGET_TYPE *toBegin,
794 TARGET_TYPE **fromEndPtr,
795 TARGET_TYPE *fromBegin,
796 TARGET_TYPE *position,
797 TARGET_TYPE *fromEnd,
798 FWD_ITER first,
799 FWD_ITER last,
800 size_type numElements,
801 bslma::Allocator *allocator);
802
803 /// TBD: improve comment
804 /// Move, into an uninitialized array beginning at the specified
805 /// `toBegin` pointer, elements of type given by the `allocator_traits`
806 /// class template for (template parameter) `ALLOCATOR`, from elements
807 /// starting at the specified `fromBegin` pointer and ending immediately
808 /// before the specified `fromEnd` address, moving into the specified
809 /// `position` (after translating from `fromBegin` to `toBegin`) the
810 /// specified `numElements` elements starting at the specified `first`
811 /// pointer and ending immediately before the specified `last` pointer.
812 /// Keep the pointer at the specified `fromEndPtr` address pointing to
813 /// the first uninitialized element in `[ fromBegin, fromEnd)` as the
814 /// elements are moved from source to destination. The behavior is
815 /// undefined unless `fromBegin <= position <= fromEnd` and the
816 /// destination array contains at least
817 /// `(fromEnd - fromBegin) + numElements` uninitialized elements. If a
818 /// constructor or assignment operator for the target type throws an
819 /// exception, then any elements created in the output array are
820 /// destroyed and the elements in the range `[ fromBegin, *fromEndPtr )`
821 /// will have valid but unspecified values.
822 template <class ALLOCATOR>
832 size_type numElements,
833 ALLOCATOR allocator);
834
835 /// Move the elements of (template parameter) `TARGET_TYPE` in the array
836 /// starting at the specified `fromBegin` address and ending immediately
837 /// before the specified `fromEnd` address into an uninitialized array
838 /// of `TARGET_TYPE` at the specified `toBegin` address, moving into the
839 /// specified `position` (after translating from `fromBegin` to
840 /// `toBegin`) the specified `numElements` of the `TARGET_TYPE` from the
841 /// array starting at the specified `first` address and ending
842 /// immediately before the specified `last` address. Keep the pointer
843 /// at the specified `fromEndPtr` address pointing to the first
844 /// uninitialized element in `[fromBegin, fromEnd)`, and the pointer at
845 /// the specified `lastPtr` address pointing to the end of the moved
846 /// range as the elements from the range `[ first, last)` are moved from
847 /// source to destination. The behavior is undefined unless
848 /// `fromBegin <= position <= fromEnd`, the destination array contains
849 /// at least `(fromEnd - fromBegin) + numElements` uninitialized
850 /// elements after `toBegin`, and `numElements` is the distance from
851 /// `first` to `last`. If a copy constructor or assignment operator for
852 /// `TARGET_TYPE` throws an exception, then any elements in
853 /// `[ *lastPtr, last )` as well as in `[ toBegin, ... )` are destroyed,
854 /// and the elements in the ranges `[ first, *lastPtr )` and
855 /// `[ fromBegin, *fromEndPtr )` will have unspecified but valid values.
856 template <class TARGET_TYPE>
857 static void destructiveMoveAndMoveInsert(TARGET_TYPE *toBegin,
858 TARGET_TYPE **fromEndPtr,
859 TARGET_TYPE **lastPtr,
860 TARGET_TYPE *fromBegin,
861 TARGET_TYPE *position,
862 TARGET_TYPE *fromEnd,
863 TARGET_TYPE *first,
864 TARGET_TYPE *last,
865 size_type numElements,
866 bslma::Allocator *allocator);
867
868#if !BSLS_COMPILERFEATURES_SIMULATE_CPP11_FEATURES // $var-args=10
869
870 /// Insert a newly created `allocator_traits<ALLOCATOR>::value_type`
871 /// object, constructed by forwarding the specified `allocator` (if
872 /// required) and the specified (variable number of) `arguments` to the
873 /// corresponding constructor of
874 /// `allocator_traits<ALLOCATOR>::value_type`, into the array at the
875 /// specified `toBegin` location, shifting forward the elements from
876 /// `toBegin` to the specified `toEnd` location by one position. If an
877 /// exception is thrown during the in-place construction of the new
878 /// object, the elements in the range `[toBegin .. toEnd)` are
879 /// unaffected; otherwise, if a (copy or move) constructor or a (copy or
880 /// move) assignment operator throws an exception, then any elements
881 /// created after `toEnd` are destroyed and the elements in the range
882 /// `[toBegin .. toEnd )` are left in a valid but unspecified state.
883 /// The behavior is undefined unless `toBegin` refers to sufficient
884 /// space to hold at least `toEnd - toBegin + 1` elements.
885 template <class ALLOCATOR, class... ARGS>
886 static void emplace(
889 ALLOCATOR allocator,
890 ARGS&&... arguments);
891
892 /// Insert a newly created object of the (template parameter) type
893 /// `TARGET_TYPE`, constructed by forwarding the specified `allocator`
894 /// (if required) and the specified (variable number of) `arguments` to
895 /// the corresponding constructor of `TARGET_TYPE`, into the array at
896 /// the specified `toBegin` address, shifting the elements from
897 /// `toBegin` to the specified `toEnd` address up one position towards
898 /// larger addresses. If an exception is thrown during the in-place
899 /// construction of the new object, the elements in the range
900 /// `[toBegin .. toEnd)` are unaffected; otherwise, if a (copy or move)
901 /// constructor or a (copy or move) assignment operator throws an
902 /// exception, then any elements created after `toEnd` are destroyed and
903 /// the elements in the range `[toBegin .. toEnd )` are left in a valid
904 /// but unspecified state. The behavior is undefined unless `toBegin`
905 /// refers to sufficient space to hold at least `toEnd - toBegin + 1`
906 /// elements.
907 template <class TARGET_TYPE, class... ARGS>
908 static void emplace(TARGET_TYPE *toBegin,
909 TARGET_TYPE *toEnd,
910 bslma::Allocator *allocator,
911 ARGS&&... args);
912
913#endif
914
915#if defined(BSLS_PLATFORM_CMP_MSVC) && BSLS_PLATFORM_CMP_VERSION < 1900
916 template <class CLASS_TYPE, class MEMBER_TYPE, class... ARGS>
917 static void emplace(MEMBER_TYPE CLASS_TYPE::* *toBegin,
918 MEMBER_TYPE CLASS_TYPE::* *toEnd,
919 bslma::Allocator *allocator)
920 // Old Microsoft compilers need help value-initializing elements that
921 // are pointer-to-member types.
922 {
923 emplace(toBegin, toEnd, allocator, nullptr);
924 }
925#endif
926
927 /// TBD: improve comment
928 /// Destroy the elements of type given by the `allocator_traits` class
929 /// template for (template parameter) `ALLOCATOR` starting at the
930 /// specified `first` `first` pointer and ending immediately before the
931 /// specified `middle` pointer, and move the elements in the array
932 /// starting at `middle` and ending at the specified `last` pointer down
933 /// to the `first` pointer. If an assignment throws an exception during
934 /// this process, all of the elements in the range `[ first, last )`
935 /// will have unspecified but valid values, and no elements are
936 /// destroyed. The behavior is undefined unless
937 /// `first <= middle <= last`.
938 template <class ALLOCATOR>
939 static void
943 ALLOCATOR allocator);
944
945 /// Destroy the elements of the parameterized `TARGET_TYPE` in the array
946 /// starting at the specified `first` address and ending immediately
947 /// before the specified `middle` address, and move the elements in the
948 /// array starting at `middle` and ending at the specified `last`
949 /// address down to the `first` address. If an assignment throws an
950 /// exception during this process, all of the elements in the range
951 /// `[ first, last )` will have unspecified but valid values, and no
952 /// elements are destroyed. The behavior is undefined unless
953 /// `first <= middle <= last`.
954 template <class TARGET_TYPE>
955 static void erase(TARGET_TYPE *first,
956 TARGET_TYPE *middle,
957 TARGET_TYPE *last,
958 bslma::Allocator *allocator = 0);
959
960 /// Insert the specified `value` into the array of
961 /// `allocator_traits<ALLOCATOR>::value_type` objects at the specified
962 /// `toBegin` location, shifting forward the elements from `toBegin` to
963 /// the specified `toEnd` location by one position. `value` is left in
964 /// a valid but unspecified state. If a (copy or move) constructor or a
965 /// (copy or move) assignment operator throws an exception, then any
966 /// elements created after `toEnd` are destroyed and the elements in the
967 /// range `[toBegin .. toEnd )` are left in a valid but unspecified
968 /// state. The behavior is undefined unless `toBegin` refers to
969 /// sufficient space to hold at least `toEnd - toBegin + 1` elements.
970 template <class ALLOCATOR>
971 static void
976 ALLOCATOR allocator);
977
978 /// Insert the specified `value` into the array of the (template
979 /// parameter) type `TARGET_TYPE` at the specified `toBegin` address,
980 /// shifting the elements from `toBegin` to the specified `toEnd`
981 /// address by one position towards larger addresses. `value` is left
982 /// in a valid but unspecified state. If a (copy or move) constructor
983 /// or a (copy or move) assignment operator throws an exception, then
984 /// any elements created after `toEnd` are destroyed and the elements in
985 /// the range `[toBegin .. toEnd )` are left in a valid but unspecified
986 /// state. The behavior is undefined unless `toBegin` refers to
987 /// sufficient space to hold at least `toEnd - toBegin + 1` elements.
988 template <class TARGET_TYPE>
989 static void insert(TARGET_TYPE *toBegin,
990 TARGET_TYPE *toEnd,
992 bslma::Allocator *allocator);
993
994 /// Insert the specified `numElements` copies of the specified `value`
995 /// into the array of type `allocator_traits<ALLOCATOR>::value_type`
996 /// starting at the specified `toBegin` location, shifting forward the
997 /// elements from `toBegin` to the specified `toEnd` location by
998 /// `numElements` positions. If a (copy or move) constructor or a (copy
999 /// or move) assignment operator throws an exception, any elements
1000 /// created after `toEnd` are destroyed and the elements in the range
1001 /// `[toBegin .. toEnd)` are left in a valid but unspecified state. The
1002 /// behavior is undefined unless `toBegin` refers to space sufficient to
1003 /// hold at least `toEnd - toBegin + numElements` elements.
1004 template <class ALLOCATOR>
1005 static void
1006 insert(
1010 size_type numElements,
1011 ALLOCATOR allocator);
1012
1013 /// Insert the specified `numElements` copies of the specified `value`
1014 /// into the array of (template parameter) `TARGET_TYPE` starting at the
1015 /// specified `toBegin` address and ending immediately before the
1016 /// specified `toEnd` address, shifting the elements in the array by
1017 /// `numElements` positions towards larger addresses. The behavior is
1018 /// undefined unless the destination array contains at least
1019 /// `numElements` uninitialized elements after `toEnd`. If a copy
1020 /// constructor or assignment operator for `TARGET_TYPE` throws an
1021 /// exception, then any elements created after `toEnd` are destroyed and
1022 /// the elements in the range `[ toBegin, toEnd )` will have
1023 /// unspecified, but valid, values.
1024 template <class TARGET_TYPE>
1025 static void insert(TARGET_TYPE *toBegin,
1026 TARGET_TYPE *toEnd,
1027 const TARGET_TYPE& value,
1028 size_type numElements,
1029 bslma::Allocator *allocator);
1030
1031 /// TBD: improve comment
1032 /// Insert the specified `numElements` from the range starting at the
1033 /// specified `fromBegin` and ending immediately before the specified
1034 /// `fromEnd` iterators of (template parameter) `FWD_ITER` type (or
1035 /// template parameter `SOURCE_TYPE *`), into the array of elements of
1036 /// type given by the `allocator_traits` class template for (template
1037 /// parameter) `ALLOCATOR`, starting at the specified `toBegin` address,
1038 /// shifting forward the elements in the array by `numElements`
1039 /// positions. The behavior is undefined unless the destination array
1040 /// contains `numElements` uninitialized elements after `toEnd`,
1041 /// `numElements` is the distance between `fromBegin` and `fromEnd`,
1042 /// and the input array and the destination array do not overlap. If a
1043 /// copy constructor or assignment operator throws an exception, then
1044 /// any elements created after `toEnd` are destroyed and the elements in
1045 /// the range `[ toBegin, toEnd )` will have valid but unspecified
1046 /// values.
1047 template <class ALLOCATOR, class FWD_ITER>
1048 static void
1051 FWD_ITER fromBegin,
1052 FWD_ITER fromEnd,
1053 size_type numElements,
1054 ALLOCATOR allocator);
1055 template <class ALLOCATOR, class SOURCE_TYPE>
1056 static void
1059 SOURCE_TYPE *fromBegin,
1060 SOURCE_TYPE *fromEnd,
1061 size_type numElements,
1062 ALLOCATOR allocator);
1063
1064 /// Insert, into the array at the specified `toBegin` location, the
1065 /// specified `numElements` from the range starting at the specified
1066 /// `fromBegin` and ending immediately before the specified `fromEnd`
1067 /// iterators of the (template parameter) `FWD_ITER` type (or the
1068 /// (template parameter) `SOURCE_TYPE *`), into the array of elements of
1069 /// the parameterized `TARGET_TYPE` starting at the specified `toBegin`
1070 /// address and ending immediately before the specified `toEnd` address,
1071 /// shifting the elements in the array by `numElements` positions
1072 /// towards larger addresses. The behavior is undefined unless the
1073 /// destination array contains `numElements` uninitialized elements
1074 /// after `toEnd`, `numElements` is the distance between `fromBegin` and
1075 /// `fromEnd`, and the input array and the destination array do not
1076 /// overlap. If a copy constructor or assignment operator for
1077 /// `TARGET_TYPE` throws an exception, then any elements created after
1078 /// `toEnd` are destroyed and the elements in the range
1079 /// `[ toBegin, toEnd )` will have unspecified, but valid, values.
1080 template <class TARGET_TYPE, class FWD_ITER>
1081 static void insert(TARGET_TYPE *toBegin,
1082 TARGET_TYPE *toEnd,
1083 FWD_ITER fromBegin,
1084 FWD_ITER fromEnd,
1085 size_type numElements,
1086 bslma::Allocator *allocator);
1087 template <class TARGET_TYPE, class SOURCE_TYPE>
1088 static void insert(TARGET_TYPE *toBegin,
1089 TARGET_TYPE *toEnd,
1090 SOURCE_TYPE *fromBegin,
1091 SOURCE_TYPE *fromEnd,
1092 size_type numElements,
1093 bslma::Allocator *allocator);
1094
1095 /// TBD: improve comment
1096 /// Move the elements of type given by the `allocator_traits` class
1097 /// template for (template parameter) `ALLOCATOR` in the array starting
1098 /// at the specified `toBegin` location and ending immediately before
1099 /// the specified `toEnd` location by the specified `numElements`
1100 /// positions towards larger addresses, and fill the `numElements` at
1101 /// the `toBegin` location by moving the elements from the array
1102 /// starting at the specified `fromBegin` and ending immediately before
1103 /// the specified `fromEnd` location. Keep the iterator at the
1104 /// specified `fromEndPtr` address pointing to the end of the range as
1105 /// the elements from `[ fromBegin, fromEnd )` are moved from source to
1106 /// destination. The behavior is undefined unless the destination array
1107 /// contains `numElements` uninitialized elements after `toEnd`,
1108 /// `numElements` is the distance from `fromBegin` to `fromEnd`, and the
1109 /// input and destination arrays do not overlap. If a copy constructor
1110 /// or assignment operator for `TARGET_TYPE` throws an exception, then
1111 /// any elements created after `toEnd` are destroyed, the elements in
1112 /// the ranges `[ toBegin, toEnd)` and `[ fromBegin, *fromEndPtr )` will
1113 /// have unspecified, but valid, values, and the elements in
1114 /// `[ *fromEndPtr, fromEnd )` will be destroyed.
1115 template <class ALLOCATOR>
1116 static void moveInsert(
1119 typename bsl::allocator_traits<ALLOCATOR>::pointer *fromEndPtr,
1122 size_type numElements,
1123 ALLOCATOR allocator);
1124
1125 /// Move the elements of the (template parameter) `TARGET_TYPE` in the
1126 /// array starting at the specified `toBegin` address and ending
1127 /// immediately before the specified `toEnd` address by the specified
1128 /// `numElements` positions towards larger addresses, and fill the
1129 /// `numElements` at the `toBegin` address by moving the elements from
1130 /// the array starting at the specified `fromBegin` and ending
1131 /// immediately before the specified `fromEnd` address. Keep the
1132 /// iterator at the specified `fromEndPtr` address pointing to the end
1133 /// of the range as the elements from `[ fromBegin, fromEnd )` are moved
1134 /// from source to destination. The behavior is undefined unless the
1135 /// destination array contains `numElements` uninitialized elements
1136 /// after `toEnd`, `numElements` is the distance from `fromBegin` to
1137 /// `fromEnd`, and the input and destination arrays do not overlap. If
1138 /// a copy constructor or assignment operator for `TARGET_TYPE` throws
1139 /// an exception, then any elements created after `toEnd` are destroyed,
1140 /// the elements in the ranges `[ toBegin, toEnd)` and
1141 /// `[ fromBegin, *fromEndPtr )` will have unspecified, but valid,
1142 /// values, and the elements in `[ *fromEndPtr, fromEnd )` will be
1143 /// destroyed.
1144 template <class TARGET_TYPE>
1145 static void moveInsert(TARGET_TYPE *toBegin,
1146 TARGET_TYPE *toEnd,
1147 TARGET_TYPE **fromEndPtr,
1148 TARGET_TYPE *fromBegin,
1149 TARGET_TYPE *fromEnd,
1150 size_type numElements,
1151 bslma::Allocator *allocator);
1152
1153 /// Move the elements of the parameterized `TARGET_TYPE` in the array
1154 /// starting at the specified `first` address and ending immediately
1155 /// before the specified `middle` address to the array of the same
1156 /// length ending at the specified `last` address (and thus starting at
1157 /// the `last - (middle - first)` address), and move the elements
1158 /// previously in the array starting at `middle` and ending at `last`
1159 /// down to the `first` address. If the assignment operator throws an
1160 /// exception during this process, all of the elements in
1161 /// `[ first, last )` will have unspecified, but valid, values. The
1162 /// behavior is undefined unless `first <= middle <= last`.
1163 template <class TARGET_TYPE>
1164 static void rotate(TARGET_TYPE *first,
1165 TARGET_TYPE *middle,
1166 TARGET_TYPE *last);
1167
1168 /// TBD: improve comment
1169 /// Construct copies of the specified `value` of type given by the
1170 /// `allocator_traits` class template for (template parameter)
1171 /// `ALLOCATOR` into the uninitialized array containing the specified
1172 /// `numElements` starting at the specified `begin` location. The
1173 /// behavior is undefined unless the output array contains at least
1174 /// `numElements` uninitialized elements after `begin`. If a
1175 /// constructor throws an exception during the operation, then the
1176 /// destructor is called on any newly-constructed elements, leaving the
1177 /// output array in an uninitialized state.
1178 template <class ALLOCATOR>
1179 static void uninitializedFillN(
1181 size_type numElements,
1183 ALLOCATOR allocator);
1184
1185 /// Construct copies of the specified `value` of the parameterized type
1186 /// `TARGET_TYPE` into the uninitialized array containing the specified
1187 /// `numElements` starting at the specified `begin` address. If the
1188 /// (template parameter) `ALLOCATOR` type is derived from
1189 /// `bslma::Allocator` and `TARGET_TYPE` supports `bslma` allocators,
1190 /// then the specified `allocator` is passed to each invocation of the
1191 /// `TARGET_TYPE` copy constructor. The behavior is undefined unless
1192 /// the output array contains at least `numElements` uninitialized
1193 /// elements after `begin`. If a `TARGET_TYPE` constructor throws an
1194 /// exception during the operation, then the destructor is called on any
1195 /// newly-constructed elements, leaving the output array in an
1196 /// uninitialized state. Note that the argument order was chosen to
1197 /// maintain compatibility with the existing `bslalg`.
1198 template <class TARGET_TYPE>
1199 static void uninitializedFillN(TARGET_TYPE *begin,
1200 size_type numElements,
1201 const TARGET_TYPE& value,
1202 bslma::Allocator *allocator);
1203};
1204
1205 // ==========================
1206 // struct ArrayPrimitives_Imp
1207 // ==========================
1208
1209/// This `struct` provides a namespace for a suite of independent utility
1210/// functions that operate on arrays of elements of a parameterized
1211/// `TARGET_TYPE`. These utility functions are only for the purpose of
1212/// implementing those in the `ArrayPrimitives` utility. For brevity, we do
1213/// not repeat the main contracts here, but instead refer to the
1214/// corresponding contract in the `ArrayPrimitives` utility.
1216
1217 private:
1218 // PRIVATE METHODS
1219
1220 /// Copy-assign the specified `value` to the range starting at the
1221 /// specified `srcStart` and ending immediately before the specified
1222 /// `srcEnd`. Note that the (template parameter) `TARGET_TYPE` must be
1223 /// copy-assignable. Also note that `value` should not be an element in
1224 /// the range `[srcStart, srcEnd)`.
1225 template <class TARGET_TYPE>
1226 static void assign(TARGET_TYPE *srcStart,
1227 TARGET_TYPE *srcEnd,
1228 TARGET_TYPE& value);
1229
1230 /// Copy-assign the elements in reverse order from the range starting at
1231 /// the specified `srcStart` and ending immediately before the specified
1232 /// `srcEnd` to the range starting at the specified `dest` and ending
1233 /// immediately before `dest + (srcEnd - srcStart)`. The behavior is
1234 /// undefined unless each element is both range `[srcStart, srcEnd)` and
1235 /// range `[dest, dest + (srcEnd - srcStart))` is valid. Note that the
1236 /// (template parameter) `TARGET_TYPE` must be copy-assignable. Also
1237 /// note that this method is intended to support range assignment when
1238 /// the two ranges may be overlapped, and `srcStart <= dest`.
1239 template <class TARGET_TYPE>
1240 static void reverseAssign(TARGET_TYPE *dest,
1241 TARGET_TYPE *srcStart,
1242 TARGET_TYPE *srcEnd);
1243
1244 public:
1245 // TYPES
1248
1249 enum {
1250 // These constants are used in the overloads below, when the last
1251 // argument is of type 'bslmf::integral_constant<int,N>', indicating
1252 // that 'TARGET_TYPE' has the traits for which the enumerator equal to
1253 // 'N' is named.
1254
1261 e_NIL_TRAITS = 0
1263
1264 enum {
1265 // Number of bytes for which a stack-allocated buffer can be
1266 // comfortably obtained to optimize bitwise moves.
1267
1270
1271 // CLASS METHODS
1272
1273 /// Fill the specified `numBytes` in the array starting at the specified
1274 /// `begin` address, as if by bit-wise copying the specified
1275 /// `numBytesInitialized` at every offset that is a multiple of
1276 /// `numBytesInitialized` within the output array. The behavior is
1277 /// undefined unless `numBytesInitialized <= numBytes`. Note that
1278 /// `numBytes` usually is, but does not have to be, a multiple of
1279 /// `numBytesInitialized`.
1280 static void bitwiseFillN(char *begin,
1281 size_type numBytesInitialized,
1282 size_type numBytes);
1283
1284 static void uninitializedFillN(
1285 bool *begin,
1286 bool value,
1287 size_type numElements,
1288 void * = 0,
1291 static void uninitializedFillN(
1292 char *begin,
1293 char value,
1294 size_type numElements,
1295 void * = 0,
1298 static void uninitializedFillN(
1299 unsigned char *begin,
1300 unsigned char value,
1301 size_type numElements,
1302 void * = 0,
1305 static void uninitializedFillN(
1306 signed char *begin,
1307 signed char value,
1308 size_type numElements,
1309 void * = 0,
1312 static void uninitializedFillN(
1313 wchar_t *begin,
1314 wchar_t value,
1315 size_type numElements,
1316 void * = 0,
1320 short *begin,
1321 short value,
1322 size_type numElements,
1323 void * = 0,
1326 static void uninitializedFillN(
1327 unsigned short *begin,
1328 unsigned short value,
1329 size_type numElements,
1330 void * = 0,
1334 int *begin,
1335 int value,
1336 size_type numElements,
1337 void * = 0,
1340 static void uninitializedFillN(
1341 unsigned int *begin,
1342 unsigned int value,
1343 size_type numElements,
1344 void * = 0,
1347 static void uninitializedFillN(
1348 long *begin,
1349 long value,
1350 size_type numElements,
1351 void * = 0,
1354 static void uninitializedFillN(
1355 unsigned long *begin,
1356 unsigned long value,
1357 size_type numElements,
1358 void * = 0,
1362 bsls::Types::Int64 *begin,
1363 bsls::Types::Int64 value,
1364 size_type numElements,
1365 void * = 0,
1368 static void uninitializedFillN(
1369 bsls::Types::Uint64 *begin,
1370 bsls::Types::Uint64 value,
1371 size_type numElements,
1372 void * = 0,
1376 float *begin,
1377 float value,
1378 size_type numElements,
1379 void * = 0,
1383 double *begin,
1384 double value,
1385 size_type numElements,
1386 void * = 0,
1390 long double *begin,
1391 long double value,
1392 size_type numElements,
1393 void * = 0,
1397 void **begin,
1398 void *value,
1399 size_type numElements,
1400 void * = 0,
1404 const void **begin,
1405 const void *value,
1406 size_type numElements,
1407 void * = 0,
1411 volatile void **begin,
1412 volatile void *value,
1413 size_type numElements,
1414 void * = 0,
1417 /// Copy the specified `value` of the parameterized `TARGET_TYPE` into
1418 /// every of the specified `numElements` in the array starting at the
1419 /// specified `begin` address. Pass the specified `allocator` to the
1420 /// copy constructor if appropriate. Note that if `TARGET_TYPE` is
1421 /// bit-wise copyable or is not based on `bslma::Allocator`, `allocator`
1422 /// is ignored. The last argument is for removing overload ambiguities
1423 /// and is not used.
1425 const volatile void **begin,
1426 const volatile void *value,
1427 size_type numElements,
1428 void * = 0,
1431 template <class TARGET_TYPE>
1432 static void uninitializedFillN(
1433 TARGET_TYPE **begin,
1434 TARGET_TYPE *value,
1435 size_type numElements,
1436 void * = 0,
1439 template <class TARGET_TYPE>
1440 static void uninitializedFillN(
1441 const TARGET_TYPE **begin,
1442 const TARGET_TYPE *value,
1443 size_type numElements,
1444 void * = 0,
1447 template <class TARGET_TYPE>
1448 static void uninitializedFillN(
1449 volatile TARGET_TYPE **begin,
1450 volatile TARGET_TYPE *value,
1451 size_type numElements,
1452 void * = 0,
1455 template <class TARGET_TYPE>
1456 static void uninitializedFillN(
1457 const volatile TARGET_TYPE **begin,
1458 const volatile TARGET_TYPE *value,
1459 size_type numElements,
1460 void * = 0,
1463 template <class TARGET_TYPE, class ALLOCATOR>
1464 static void uninitializedFillN(
1465 TARGET_TYPE *begin,
1466 const TARGET_TYPE& value,
1467 size_type numElements,
1468 ALLOCATOR *allocator,
1470 template <class TARGET_TYPE, class ALLOCATOR>
1471 static void uninitializedFillN(
1472 TARGET_TYPE *begin,
1473 const TARGET_TYPE& value,
1474 size_type numElements,
1475 ALLOCATOR *allocator,
1477
1478 /// These functions follow the `copyConstruct` contract. If the
1479 /// (template parameter) `ALLOCATOR` type is based on `bslma::Allocator`
1480 /// and the `TARGET_TYPE` constructors take an allocator argument, then
1481 /// pass the specified `allocator` to the copy constructor. The
1482 /// behavior is undefined unless the output array has length at least
1483 /// the distance from the specified `fromBegin` to the specified
1484 /// `fromEnd`. Note that if `FWD_ITER` is the `TARGET_TYPE *` pointer
1485 /// type and `TARGET_TYPE` is bit-wise copyable, then this operation is
1486 /// simply `memcpy`. The last argument is for removing overload
1487 /// ambiguities and is not used.
1488 template <class TARGET_TYPE, class FWD_ITER, class ALLOCATOR>
1489 static void copyConstruct(
1490 TARGET_TYPE *toBegin,
1491 FWD_ITER fromBegin,
1492 FWD_ITER fromEnd,
1493 ALLOCATOR allocator,
1495 template <class TARGET_TYPE, class ALLOCATOR>
1496 static void copyConstruct(
1497 TARGET_TYPE *toBegin,
1498 const TARGET_TYPE *fromBegin,
1499 const TARGET_TYPE *fromEnd,
1500 ALLOCATOR allocator,
1502 template <class TARGET_TYPE, class FWD_ITER, class ALLOCATOR>
1503 static void copyConstruct(
1504 TARGET_TYPE *toBegin,
1505 FWD_ITER fromBegin,
1506 FWD_ITER fromEnd,
1507 ALLOCATOR allocator,
1509 template <class FWD_ITER, class ALLOCATOR>
1510 static void copyConstruct(
1511 void **toBegin,
1512 FWD_ITER fromBegin,
1513 FWD_ITER fromEnd,
1514 ALLOCATOR allocator,
1516 template <class TARGET_TYPE, class FWD_ITER, class ALLOCATOR>
1517 static void copyConstruct(
1518 TARGET_TYPE *toBegin,
1519 FWD_ITER fromBegin,
1520 FWD_ITER fromEnd,
1521 ALLOCATOR allocator,
1523
1524 /// TBD: improve comment
1525 /// Move-insert into an uninitialized array beginning at the specified
1526 /// `toBegin` pointer, elements of type given by the `allocator_traits`
1527 /// class template for (template parameter) `ALLOCATOR` from elements
1528 /// starting at the specified `fromBegin` pointer and ending immediately
1529 /// before the specified `fromEnd` pointer. The elements in the range
1530 /// `[fromBegin...fromEnd)` are left in a valid but unspecified state.
1531 /// If a constructor throws an exception during the operation, then the
1532 /// destructor is called on any newly-constructed elements, leaving the
1533 /// output array in an uninitialized state. The behavior is undefined
1534 /// unless `toBegin` refers to space sufficient to hold
1535 /// `fromEnd - fromBegin` elements.
1536 template <class TARGET_TYPE, class ALLOCATOR>
1537 static void moveConstruct(
1538 TARGET_TYPE *toBegin,
1539 TARGET_TYPE *fromBegin,
1540 TARGET_TYPE *fromEnd,
1541 ALLOCATOR allocator,
1543 template <class TARGET_TYPE, class ALLOCATOR>
1544 static void moveConstruct(
1545 TARGET_TYPE *toBegin,
1546 TARGET_TYPE *fromBegin,
1547 TARGET_TYPE *fromEnd,
1548 ALLOCATOR allocator,
1550
1551 /// TBD: improve comment
1552 /// Either move- or copy-insert into an uninitialized array beginning at
1553 /// the specified `toBegin` pointer, elements of type given by the
1554 /// `allocator_traits` class template for (template parameter)
1555 /// `ALLOCATOR` from elements starting at the specified `fromBegin`
1556 /// pointer and ending immediately before the specified `fromEnd`
1557 /// pointer. The elements in the range `[fromBegin...fromEnd)` are left
1558 /// in a valid but unspecified state. Use the move constructor if it is
1559 /// guaranteed to not throw or if the target type does not define a copy
1560 /// constructor; otherwise use the copy constructor. If a constructor
1561 /// throws an exception during the operation, then the destructor is
1562 /// called on any newly-constructed elements, leaving the output array
1563 /// in an uninitialized state. The behavior is undefined unless
1564 /// `toBegin` refers to space sufficient to hold `fromEnd - fromBegin`
1565 /// elements.
1566 template <class TARGET_TYPE, class ALLOCATOR>
1567 static void moveIfNoexcept(
1568 TARGET_TYPE *toBegin,
1569 TARGET_TYPE *fromBegin,
1570 TARGET_TYPE *fromEnd,
1571 ALLOCATOR allocator,
1573
1574 /// Use the default constructor of the (template parameter)
1575 /// `TARGET_TYPE` (or `memset` to 0 if `TARGET_TYPE` has a trivial
1576 /// default constructor) on each element of the array starting at the
1577 /// specified `begin` address and ending immediately before the `end`
1578 /// address. Pass the specified `allocator` to the default constructor
1579 /// if appropriate. The last argument is for traits overloading
1580 /// resolution only and its value is ignored.
1581 template <class TARGET_TYPE, class ALLOCATOR>
1582 static void defaultConstruct(
1583 TARGET_TYPE *begin,
1584 size_type numElements,
1585 ALLOCATOR allocator,
1587 template <class TARGET_TYPE, class ALLOCATOR>
1588 static void defaultConstruct(
1589 TARGET_TYPE *begin,
1590 size_type numElements,
1591 ALLOCATOR allocator,
1593 template <class TARGET_TYPE, class ALLOCATOR>
1594 static void defaultConstruct(
1595 TARGET_TYPE *begin,
1596 size_type numElements,
1597 ALLOCATOR allocator,
1599
1600 /// These functions follow the `destructiveMove` contract. Note that
1601 /// both arrays cannot overlap (one contains only initialized elements
1602 /// and the other only uninitialized elements), and that if
1603 /// `TARGET_TYPE` is bit-wise moveable, then this operation is simply
1604 /// `memcpy`. The last argument is for removing overload ambiguities
1605 /// and is not used.
1606 template <class TARGET_TYPE, class ALLOCATOR>
1607 static void destructiveMove(
1608 TARGET_TYPE *toBegin,
1609 TARGET_TYPE *fromBegin,
1610 TARGET_TYPE *fromEnd,
1611 ALLOCATOR allocator,
1613 template <class TARGET_TYPE, class ALLOCATOR>
1614 static void destructiveMove(
1615 TARGET_TYPE *toBegin,
1616 TARGET_TYPE *fromBegin,
1617 TARGET_TYPE *fromEnd,
1618 ALLOCATOR allocator,
1620
1621#if !BSLS_COMPILERFEATURES_SIMULATE_CPP11_FEATURES
1622 /// TBD: document this
1623 template <class TARGET_TYPE, class ALLOCATOR, class... ARGS>
1624 static void emplace(
1625 TARGET_TYPE *toBegin,
1626 TARGET_TYPE *toEnd,
1627 ALLOCATOR allocator,
1629 ARGS&&... args);
1630 template <class TARGET_TYPE, class ALLOCATOR, class... ARGS>
1631 static void emplace(
1632 TARGET_TYPE *toBegin,
1633 TARGET_TYPE *toEnd,
1634 ALLOCATOR allocator,
1636 ARGS&&... args);
1637 template <class TARGET_TYPE, class ALLOCATOR, class... ARGS>
1638 static void emplace(
1639 TARGET_TYPE *toBegin,
1640 TARGET_TYPE *toEnd,
1641 ALLOCATOR allocator,
1643 ARGS&&... args);
1644#endif
1645
1646 /// These functions follow the `erase` contract. Note that if (template
1647 /// parameter) `TARGET_TYPE` is bit-wise moveable, then this operation
1648 /// can be implemented by first bit-wise moving the elements in
1649 /// `[middle, last)` towards first, and destroying
1650 /// `[ last - (middle - first), last)`; note that this cannot throw
1651 /// exceptions.
1652 template <class TARGET_TYPE, class ALLOCATOR>
1653 static void erase(
1654 TARGET_TYPE *first,
1655 TARGET_TYPE *middle,
1656 TARGET_TYPE *last,
1657 ALLOCATOR allocator,
1659 template <class TARGET_TYPE, class ALLOCATOR>
1660 static void erase(
1661 TARGET_TYPE *first,
1662 TARGET_TYPE *middle,
1663 TARGET_TYPE *last,
1664 ALLOCATOR allocator,
1666
1667 /// These functions follow the `insert` contract. Note that if
1668 /// `TARGET_TYPE` is bit-wise copyable, then this operation is simply
1669 /// `memmove` followed by `bitwiseFillN`. If `TARGET_TYPE` is bit-wise
1670 /// moveable, then this operation can still be optimized using `memmove`
1671 /// followed by repeated assignments, but a guard needs to be set up.
1672 /// The last argument is for removing overload ambiguities and is not
1673 /// used.
1674 template <class TARGET_TYPE, class ALLOCATOR>
1675 static void insert(
1676 TARGET_TYPE *toBegin,
1677 TARGET_TYPE *toEnd,
1678 const TARGET_TYPE& value,
1679 size_type numElements,
1680 ALLOCATOR allocator,
1682 template <class TARGET_TYPE, class ALLOCATOR>
1683 static void insert(
1684 TARGET_TYPE *toBegin,
1685 TARGET_TYPE *toEnd,
1686 const TARGET_TYPE& value,
1687 size_type numElements,
1688 ALLOCATOR allocator,
1690 template <class TARGET_TYPE, class ALLOCATOR>
1691 static void insert(
1692 TARGET_TYPE *toBegin,
1693 TARGET_TYPE *toEnd,
1694 const TARGET_TYPE& value,
1695 size_type numElements,
1696 ALLOCATOR allocator,
1698
1699 /// These functions follow the `insert` contract. Note that if
1700 /// `TARGET_TYPE` is bit-wise copyable and `FWD_ITER` is convertible to
1701 /// `const TARGET_TYPE *`, then this operation is simply `memmove`
1702 /// followed by `memcpy`. If `TARGET_TYPE` is bit-wise moveable and
1703 /// `FWD_ITER` is convertible to `const TARGET_TYPE *`, then this
1704 /// operation can still be optimized using `memmove` followed by
1705 /// repeated copies. The last argument is for removing overload
1706 /// ambiguities and is not used.
1707 template <class TARGET_TYPE, class FWD_ITER, class ALLOCATOR>
1708 static void insert(
1709 TARGET_TYPE *toBegin,
1710 TARGET_TYPE *toEnd,
1711 FWD_ITER fromBegin,
1712 FWD_ITER fromEnd,
1713 size_type numElements,
1714 ALLOCATOR allocator,
1716 template <class TARGET_TYPE, class ALLOCATOR>
1717 static void insert(
1718 TARGET_TYPE *toBegin,
1719 TARGET_TYPE *toEnd,
1720 const TARGET_TYPE *fromBegin,
1721 const TARGET_TYPE *fromEnd,
1722 size_type numElements,
1723 ALLOCATOR allocator,
1725 template <class TARGET_TYPE, class FWD_ITER, class ALLOCATOR>
1726 static void insert(
1727 TARGET_TYPE *toBegin,
1728 TARGET_TYPE *toEnd,
1729 FWD_ITER fromBegin,
1730 FWD_ITER fromEnd,
1731 size_type numElements,
1732 ALLOCATOR allocator,
1734 template <class FWD_ITER, class ALLOCATOR>
1735 static void insert(
1736 void **toBegin,
1737 void **toEnd,
1738 FWD_ITER fromBegin,
1739 FWD_ITER fromEnd,
1740 size_type numElements,
1741 ALLOCATOR allocator,
1743 template <class TARGET_TYPE, class FWD_ITER, class ALLOCATOR>
1744 static void insert(
1745 TARGET_TYPE *toBegin,
1746 TARGET_TYPE *toEnd,
1747 FWD_ITER fromBegin,
1748 FWD_ITER fromEnd,
1749 size_type numElements,
1750 ALLOCATOR allocator,
1752
1753 /// These functions follow the `moveInsert` contract. Note that if
1754 /// `TARGET_TYPE` is at least bit-wise moveable, then this operation is
1755 /// simply `memmove` followed by `memcpy`.
1756 template <class TARGET_TYPE, class ALLOCATOR>
1757 static void moveInsert(
1758 TARGET_TYPE *toBegin,
1759 TARGET_TYPE *toEnd,
1760 TARGET_TYPE **lastPtr,
1761 TARGET_TYPE *first,
1762 TARGET_TYPE *last,
1763 size_type numElements,
1764 ALLOCATOR allocator,
1766 template <class TARGET_TYPE, class ALLOCATOR>
1767 static void moveInsert(
1768 TARGET_TYPE *toBegin,
1769 TARGET_TYPE *toEnd,
1770 TARGET_TYPE **lastPtr,
1771 TARGET_TYPE *first,
1772 TARGET_TYPE *last,
1773 size_type numElements,
1774 ALLOCATOR allocator,
1776
1777 /// These functions follow the `rotate` contract, but the first overload
1778 /// is optimized when the parameterized `TARGET_TYPE` is bit-wise
1779 /// moveable. The last argument is for removing overload ambiguities
1780 /// and is not used. Note that if `TARGET_TYPE` is bit-wise moveable,
1781 /// the `rotate(char*, char*, char*)` can be used, enabling to take the
1782 /// whole implementation out-of-line.
1783 template <class TARGET_TYPE>
1784 static void rotate(
1785 TARGET_TYPE *begin,
1786 TARGET_TYPE *middle,
1787 TARGET_TYPE *end,
1789 template <class TARGET_TYPE>
1790 static void rotate(
1791 TARGET_TYPE *begin,
1792 TARGET_TYPE *middle,
1793 TARGET_TYPE *end,
1795
1796 /// Shift the specified `[begin, end)` sequence one position right, then
1797 /// insert the specified `value` at the position pointed by `begin`.
1798 /// The specified `allocator` is used for the element construction. The
1799 /// behavior is undefined unless the specified `[begin, end)` sequence
1800 /// contains at least one element.
1801 template <class ALLOCATOR>
1802 static void shiftAndInsert(
1807 ALLOCATOR allocator,
1809 template <class ALLOCATOR>
1810 static void shiftAndInsert(
1815 ALLOCATOR allocator,
1817 template <class ALLOCATOR>
1818 static void shiftAndInsert(
1823 ALLOCATOR allocator,
1825
1826 // 'bitwise' METHODS
1827
1828 /// This function follows the `rotate` contract, but by using bit-wise
1829 /// moves on the underlying `char` array.
1830 static void bitwiseRotate(char *begin, char *middle, char *end);
1831
1832 /// Move the characters in the array starting at the specified `first`
1833 /// address and ending immediately before the specified `middle` address
1834 /// to the array of the same length ending at the specified `last`
1835 /// address (and thus starting at the `last - (middle - first)`
1836 /// address), and move the elements previously in the array starting at
1837 /// `middle` and ending at `last` down to the `first` address. The
1838 /// behavior is undefined unless
1839 /// `middle - begin <= k_INPLACE_BUFFER_SIZE`.
1840 static void bitwiseRotateBackward(char *begin, char *middle, char *end);
1841
1842 /// Move the characters in the array starting at the specified `first`
1843 /// address and ending immediately before the specified `middle` address
1844 /// to the array of the same length ending at the specified `last`
1845 /// address (and thus starting at the `last - (middle - first)`
1846 /// address), and move the elements previously in the array starting at
1847 /// `middle` and ending at `last` down to the `first` address. The
1848 /// behavior is undefined unless
1849 /// `end - middle <= k_INPLACE_BUFFER_SIZE`.
1850 static void bitwiseRotateForward(char *begin, char *middle, char *end);
1851
1852 /// Swap the characters in the array starting at the specified `first`
1853 /// address and ending immediately before the specified `middle` address
1854 /// with the array of the same length starting at the `middle` address
1855 /// and ending at the specified `last` address. The behavior is
1856 /// undefined unless `middle - begin == end - middle`.
1857 static void bitwiseSwapRanges(char *begin, char *middle, char *end);
1858
1859 /// Return `true` if the specified `begin` and the specified `end`
1860 /// provably do not form a valid semi-open range, `[begin, end)`, and
1861 /// `false` otherwise. Note that `begin == null == end` produces a
1862 /// valid range, and any other use of the null pointer value will return
1863 /// `true`. Also note that this function is intended to support
1864 /// testing, primarily through assertions, so will return `false` unless
1865 /// it can *prove* that the passed range is invalid. Currently, this
1866 /// function can prove invalid ranges only for pointers, although should
1867 /// also encompass generic random access iterators in a future update,
1868 /// where iterator tag types are levelized below `bslalg`.
1869 template <class FORWARD_ITERATOR>
1870 static bool isInvalidRange(FORWARD_ITERATOR begin, FORWARD_ITERATOR end);
1871 template <class TARGET_TYPE>
1872 static bool isInvalidRange(TARGET_TYPE *begin, TARGET_TYPE *end);
1873};
1874
1875// ============================================================================
1876// INLINE FUNCTION DEFINITIONS
1877// ============================================================================
1878// IMPLEMENTATION NOTES: Specializations of 'uninitializedFillN' for most
1879// fundamental types are not templates nor inline, and thus can be found in the
1880// '.cpp' file.
1881
1882 // =====================================
1883 // struct ArrayPrimitives_CanBitwiseCopy
1884 // =====================================
1885
1886template <class FROM_TYPE, class TO_TYPE>
1889 bsl::is_same<
1890 typename bsl::remove_const<FROM_TYPE>::type,
1891 typename bsl::remove_const<TO_TYPE >::type>
1892 ::value
1893 && bslmf::IsBitwiseCopyable<
1894 typename bsl::remove_const<TO_TYPE >::type>
1895 ::value
1896 > {
1897};
1898
1899 // ----------------------
1900 // struct ArrayPrimitives
1901 // ----------------------
1902
1903template <class ALLOCATOR>
1904inline
1907 size_type numElements,
1909 ALLOCATOR allocator)
1910{
1911 BSLS_ASSERT_SAFE(begin || 0 == numElements);
1913
1914 typedef typename bsl::allocator_traits<ALLOCATOR>::value_type TargetType;
1915
1916 enum {
1917 // We provide specialized overloads of 'uninitializedFillN' for
1918 // fundamental and pointer types. However, function pointers can have
1919 // extern "C" linkage and SunPro doesn't match them properly with the
1920 // pointer template function overload in 'Imp', so we resort to the
1921 // general case for those.
1922
1923 k_IS_FUNCTION_POINTER = bslmf::IsFunctionPointer<TargetType>::value,
1924 k_IS_FUNDAMENTAL = bsl::is_fundamental<TargetType>::value,
1926
1927 k_IS_FUNDAMENTAL_OR_POINTER = k_IS_FUNDAMENTAL ||
1928 (k_IS_POINTER && !k_IS_FUNCTION_POINTER),
1929
1930 k_IS_BITWISECOPYABLE = bslmf::IsBitwiseCopyable<TargetType>::value,
1931
1932 k_VALUE =
1933 k_IS_FUNDAMENTAL_OR_POINTER ? Imp::e_IS_FUNDAMENTAL_OR_POINTER
1934 : k_IS_BITWISECOPYABLE ? Imp::e_BITWISE_COPYABLE_TRAITS
1936 };
1938 begin,
1939 value,
1940 numElements,
1941 &allocator,
1943}
1944
1945template <class TARGET_TYPE>
1946inline
1948 size_type numElements,
1949 const TARGET_TYPE& value,
1950 bslma::Allocator *basicAllocator)
1951{
1952 uninitializedFillN<bsl::allocator<TARGET_TYPE> >(begin,
1953 numElements,
1954 value,
1955 basicAllocator);
1956}
1957
1958template <class ALLOCATOR, class FWD_ITER>
1961 FWD_ITER fromBegin,
1962 FWD_ITER fromEnd,
1963 ALLOCATOR allocator)
1964{
1965 BSLS_ASSERT_SAFE(toBegin || fromBegin == fromEnd);
1966
1968 typedef typename bsl::allocator_traits<ALLOCATOR>::value_type TargetType;
1969
1970 /// Overload resolution will handle the case where `FWD_ITER` is a raw
1971 /// pointer, so we need handle only user-defined iterators. As `bslalg`
1972 /// is levelized below `bslstl` we cannot use `iterator_traits`, but
1973 /// rely on the same property as `iterator_traits` that this typedef
1974 /// must be defined for any standard-conforming iterator, unless the
1975 /// iterator explicitly specialized the `std::iterator_traits` template.
1976 /// In practice, iterators always prefer to provide the member typedef
1977 /// than specialize the traits as it is a much simpler implementation,
1978 /// so this assumption is good enough.
1979 ///
1980 /// Also note that as we know that `FWD_ITER` is not a pointer, then we
1981 /// cannot take advantage of bitwise copying as we do not have pointers
1982 /// to pass to the `memcpy` describing the whole range. It is not worth
1983 /// the effort to try to bitwise copy one element at a time.
1984 typedef typename FWD_ITER::value_type FwdTarget;
1985
1986 /// We want to detect the special case of copying function pointers to
1987 /// `void *` or `const void *` pointers.
1988 typedef typename bsl::remove_pointer<TargetType>::type RemovePtrTarget;
1989
1990 enum {
1991 k_ITER_TO_FUNC_PTRS = bslmf::IsFunctionPointer<FwdTarget>::value,
1992 k_TARGET_IS_VOID_PTR = bsl::is_pointer<TargetType>::value &&
1994
1995 k_VALUE = k_ITER_TO_FUNC_PTRS && k_TARGET_IS_VOID_PTR
1998 };
1999
2001 fromBegin,
2002 fromEnd,
2003 allocator,
2005}
2006
2007template <class TARGET_TYPE, class FWD_ITER>
2008inline
2009void ArrayPrimitives::copyConstruct(TARGET_TYPE *toBegin,
2010 FWD_ITER fromBegin,
2011 FWD_ITER fromEnd,
2012 bslma::Allocator *basicAllocator)
2013{
2014 copyConstruct<bsl::allocator<TARGET_TYPE> >(toBegin,
2015 fromBegin,
2016 fromEnd,
2017 basicAllocator);
2018}
2019
2020template <class ALLOCATOR, class SOURCE_TYPE>
2021inline
2024 SOURCE_TYPE *fromBegin,
2025 SOURCE_TYPE *fromEnd,
2026 ALLOCATOR allocator)
2027{
2028 BSLS_ASSERT_SAFE(toBegin || fromBegin == fromEnd);
2029
2030 typedef typename bsl::allocator_traits<ALLOCATOR>::value_type TargetType;
2031
2032 enum {
2033 k_ARE_PTRS_TO_PTRS = bsl::is_pointer<TargetType>::value &&
2035 k_IS_BITWISECOPYABLE =
2037 k_VALUE = k_ARE_PTRS_TO_PTRS ? Imp::e_IS_POINTER_TO_POINTER
2038 : k_IS_BITWISECOPYABLE ? Imp::e_BITWISE_COPYABLE_TRAITS
2040 };
2041
2043 fromBegin,
2044 fromEnd,
2045 allocator,
2047}
2048
2049template <class TARGET_TYPE, class SOURCE_TYPE>
2050inline
2051void ArrayPrimitives::copyConstruct(TARGET_TYPE *toBegin,
2052 SOURCE_TYPE *fromBegin,
2053 SOURCE_TYPE *fromEnd,
2054 bslma::Allocator *basicAllocator)
2055{
2056 copyConstruct<bsl::allocator<TARGET_TYPE> >(toBegin,
2057 fromBegin,
2058 fromEnd,
2059 basicAllocator);
2060}
2061
2062template <class ALLOCATOR>
2063inline
2066 size_type numElements,
2067 ALLOCATOR allocator)
2068{
2070 BSLS_ASSERT_SAFE(begin || 0 == numElements);
2071
2072 typedef typename bsl::allocator_traits<ALLOCATOR>::value_type TargetType;
2073
2074 enum {
2078#if !defined(BSLALG_ARRAYPRIMITIVES_NON_ZERO_NULL_VALUE_FOR_MEMBER_POINTERS)
2080#endif
2086 };
2088 begin,
2089 numElements,
2090 allocator,
2092}
2093
2094template <class TARGET_TYPE>
2095inline
2097 size_type numElements,
2098 bslma::Allocator *basicAllocator)
2099{
2100 defaultConstruct<bsl::allocator<TARGET_TYPE> >(begin,
2101 numElements,
2102 basicAllocator);
2103}
2104
2105template <class ALLOCATOR>
2106inline
2111 ALLOCATOR allocator)
2112{
2113 BSLS_ASSERT_SAFE(toBegin || fromBegin == fromEnd);
2115
2116 typedef typename bsl::allocator_traits<ALLOCATOR>::value_type TargetType;
2117
2118 enum {
2122 };
2124 toBegin,
2125 fromBegin,
2126 fromEnd,
2127 allocator,
2129}
2130
2131template <class TARGET_TYPE>
2132inline
2133void ArrayPrimitives::destructiveMove(TARGET_TYPE *toBegin,
2134 TARGET_TYPE *fromBegin,
2135 TARGET_TYPE *fromEnd,
2136 bslma::Allocator *basicAllocator)
2137{
2138 destructiveMove<bsl::allocator<TARGET_TYPE> >(toBegin,
2139 fromBegin,
2140 fromEnd,
2141 basicAllocator);
2142}
2143
2144#if !BSLS_COMPILERFEATURES_SIMULATE_CPP11_FEATURES // $var-args=10
2145template <class ALLOCATOR, class... ARGS>
2148 typename bsl::allocator_traits<ALLOCATOR>::pointer *fromEndPtr,
2152 ALLOCATOR allocator,
2153 ARGS&&... arguments)
2154{
2155 // Key to the transformation diagrams:
2156 //..
2157 // A...H original contents of '[fromBegin, fromEnd)' ("source")
2158 // v...v default-constructed values ("input")
2159 // ; ... contents of '[toBegin, toEnd)' ("destination")
2160 // ..:.. position of 'fromEndPtr' in the input
2161 // _____ uninitialized array elements
2162 // [...] part of array protected by an exception guard object
2163 //..
2164
2165 typedef typename bsl::allocator_traits<ALLOCATOR>::value_type TargetType;
2166
2167 *fromEndPtr = fromEnd;
2168
2169 // Note: Construct new element.
2170 //..
2171 // Transformation: ABCDEFGH: ; ___________[]
2172 // => ABCDEFGH: ; ____[v]____
2173 //..
2174
2175 TargetType *toPositionBegin = toBegin + (position - fromBegin);
2176
2178 allocator,
2179 toPositionBegin,
2180 BSLS_COMPILERFEATURES_FORWARD(ARGS,arguments)...);
2181
2182 TargetType *toPositionEnd = toPositionBegin + 1;
2183
2184 AutoArrayDestructor<TargetType, ALLOCATOR> guard(toPositionBegin,
2185 toPositionEnd,
2186 allocator);
2187
2188 //..
2189 // Transformation: ABCDEFGH: ; ____[v]____
2190 // => ABCD:____ ; ____[vEFGH]
2191 //..
2192
2193 destructiveMove(toPositionEnd,
2194 position,
2195 fromEnd,
2196 allocator);
2197
2198 *fromEndPtr = position; // shorten input range after partial destruction
2199 guard.moveEnd(fromEnd - position); // toEnd
2200
2201 //..
2202 // Transformation: ABCD:____ ; ____[vEFGH]
2203 // => :________ ; ABCDvEFGH[]
2204 //..
2205
2206 destructiveMove(toBegin,
2207 fromBegin,
2208 position,
2209 allocator);
2210
2211 *fromEndPtr = fromBegin; // empty input range after final destruction
2212 guard.release();
2213}
2214#endif
2215
2216template <class ALLOCATOR>
2219 typename bsl::allocator_traits<ALLOCATOR>::pointer *fromEndPtr,
2223 size_type numElements,
2224 ALLOCATOR allocator)
2225{
2226 // Key to the transformation diagrams:
2227 //..
2228 // A...H original contents of '[fromBegin, fromEnd)' ("source")
2229 // v...v default-constructed values ("input")
2230 // ; ... contents of '[toBegin, toEnd)' ("destination")
2231 // ..:.. position of 'fromEndPtr' in the input
2232 // _____ uninitialized array elements
2233 // [...] part of array protected by an exception guard object
2234 //..
2235
2236 typedef typename bsl::allocator_traits<ALLOCATOR>::value_type TargetType;
2237
2238 *fromEndPtr = fromEnd;
2239
2240 // Note: Construct default values.
2241 //..
2242 // Transformation: ABCDEFGH: ; _____________[]
2243 // => ABCDEFGH: ; ____[vvvvv]____
2244 //..
2245
2246 TargetType *toPositionBegin = toBegin + (position - fromBegin);
2247 defaultConstruct(toPositionBegin, numElements, allocator);
2248
2249 TargetType *toPositionEnd = toPositionBegin + numElements;
2250
2251 AutoArrayDestructor<TargetType, ALLOCATOR> guard(toPositionBegin,
2252 toPositionEnd,
2253 allocator);
2254
2255 //..
2256 // Transformation: ABCDEFGH: ; ____[vvvvv]____
2257 // => ABCD:____ ; ____[vvvvvEFGH]
2258 //..
2259
2260 destructiveMove(toPositionEnd,
2261 position,
2262 fromEnd,
2263 allocator);
2264
2265 *fromEndPtr = position; // shorten input range after partial destruction
2266 guard.moveEnd(fromEnd - position); // toEnd
2267
2268 //..
2269 // Transformation: ABCD:____ ; ____[vvvvvEFGH]
2270 // => :________ ; ABCDvvvvvEFGH[]
2271 //..
2272
2273 destructiveMove(toBegin,
2274 fromBegin,
2275 position,
2276 allocator);
2277
2278 *fromEndPtr = fromBegin; // empty input range after final destruction
2279 guard.release();
2280}
2281
2282template <class TARGET_TYPE>
2283inline
2285 TARGET_TYPE *toBegin,
2286 TARGET_TYPE **fromEndPtr,
2287 TARGET_TYPE *fromBegin,
2288 TARGET_TYPE *position,
2289 TARGET_TYPE *fromEnd,
2290 size_type numElements,
2291 bslma::Allocator *basicAllocator)
2292{
2293 destructiveMoveAndInsert<bsl::allocator<TARGET_TYPE> >(toBegin,
2294 fromEndPtr,
2295 fromBegin,
2296 position,
2297 fromEnd,
2298 numElements,
2299 basicAllocator);
2300}
2301
2302template <class ALLOCATOR>
2305 typename bsl::allocator_traits<ALLOCATOR>::pointer *fromEndPtr,
2310 size_type numElements,
2311 ALLOCATOR allocator)
2312{
2313 // Key to the transformation diagrams:
2314 //..
2315 // A...H original contents of '[fromBegin, fromEnd)' ("source")
2316 // v...v copies of 'value' ("input")
2317 // ; ... contents of '[toBegin, toEnd)' ("destination")
2318 // ..:.. position of 'fromEndPtr' in the input
2319 // _____ uninitialized array elements
2320 // [...] part of array protected by an exception guard object
2321 //..
2322
2323 typedef typename bsl::allocator_traits<ALLOCATOR>::value_type TargetType;
2324
2325 *fromEndPtr = fromEnd;
2326
2327 // Note: Construct copies of 'value' first in case 'value' is a reference
2328 // in the input range, which would be invalidated by any of the following
2329 // moves.
2330 //
2331 //..
2332 // Transformation: ABCDEFGH: ; _____________[]
2333 // => ABCDEFGH: ; ____[vvvvv]____
2334 //..
2335
2336 TargetType *toPositionBegin = toBegin + (position - fromBegin);
2337 uninitializedFillN(toPositionBegin, numElements, value, allocator);
2338
2339 TargetType *toPositionEnd = toPositionBegin + numElements;
2340
2341 AutoArrayDestructor<TargetType, ALLOCATOR> guard(toPositionBegin,
2342 toPositionEnd,
2343 allocator);
2344
2345 //..
2346 // Transformation: ABCDEFGH: ; ____[vvvvv]____
2347 // => ABCD:____ ; ____[vvvvvEFGH]
2348 //..
2349
2350 destructiveMove(toPositionEnd,
2351 position,
2352 fromEnd,
2353 allocator);
2354
2355 *fromEndPtr = position; // shorten input range after partial destruction
2356 guard.moveEnd(fromEnd - position); // toEnd
2357
2358 //..
2359 // Transformation: ABCD:____ ; ____[vvvvvEFGH]
2360 // => :________ ; ABCDvvvvvEFGH[]
2361 //..
2362
2363 destructiveMove(toBegin,
2364 fromBegin,
2365 position,
2366 allocator);
2367
2368 *fromEndPtr = fromBegin; // empty input range after final destruction
2369 guard.release();
2370}
2371
2372template <class TARGET_TYPE>
2374 TARGET_TYPE *toBegin,
2375 TARGET_TYPE **fromEndPtr,
2376 TARGET_TYPE *fromBegin,
2377 TARGET_TYPE *position,
2378 TARGET_TYPE *fromEnd,
2379 const TARGET_TYPE& value,
2380 size_type numElements,
2381 bslma::Allocator *basicAllocator)
2382{
2383 destructiveMoveAndInsert<bsl::allocator<TARGET_TYPE> >(toBegin,
2384 fromEndPtr,
2385 fromBegin,
2386 position,
2387 fromEnd,
2388 value,
2389 numElements,
2390 basicAllocator);
2391}
2392
2393template <class ALLOCATOR, class FWD_ITER>
2396 typename bsl::allocator_traits<ALLOCATOR>::pointer *fromEndPtr,
2400 FWD_ITER first,
2401 FWD_ITER last,
2402 size_type numElements,
2403 ALLOCATOR allocator)
2404{
2405 // Key to the transformation diagrams:
2406 //..
2407 // A...H original contents of '[fromBegin, fromEnd)' ("source")
2408 // t...z original contents of '[first, last)' ("input")
2409 // ; ... contents of '[toBegin, toEnd)' ("destination")
2410 // ..:.. position of 'fromEndPtr' in the input
2411 // _____ uninitialized array elements
2412 // [...] part of array protected by an exception guard object
2413 //..
2414
2415 typedef typename bsl::allocator_traits<ALLOCATOR>::value_type TargetType;
2416
2417 *fromEndPtr = fromEnd;
2418
2419 // Note: Construct copies of 'value' first in case 'value' is a reference
2420 // in the input range, which would be invalidated by any of the following
2421 // moves:
2422 //..
2423 // Transformation: ABCDEFGH: ; _________[]____
2424 // => ABCDEFGH: ; ____[tuvxy]____
2425 //..
2426
2427 TargetType *toPositionBegin = toBegin + (position - fromBegin);
2428 copyConstruct(toPositionBegin, first, last, allocator);
2429
2430 TargetType *toPositionEnd = toPositionBegin + numElements;
2431
2432 AutoArrayDestructor<TargetType, ALLOCATOR> guard(toPositionBegin,
2433 toPositionEnd,
2434 allocator);
2435
2436 //..
2437 // Transformation: ABCDEFGH: ; ____[tuvxy]____
2438 // => ABCD:____ ; ____[tuvxyEFGH]
2439 //..
2440
2441 destructiveMove(toPositionEnd,
2442 position,
2443 fromEnd,
2444 allocator);
2445
2446 *fromEndPtr = position; // shorten input range after partial destruction
2447 guard.moveEnd(fromEnd - position); // toEnd
2448
2449 //..
2450 // Transformation: ABCD:____ ; ____[tuvxyEFGH]
2451 // => :________ ; ABCDtuvxyEFGH[]
2452 //..
2453
2454 destructiveMove(toBegin,
2455 fromBegin,
2456 position,
2457 allocator);
2458
2459 *fromEndPtr = fromBegin; // empty input range after final destruction
2460 guard.release();
2461}
2462
2463template <class TARGET_TYPE, class FWD_ITER>
2464inline
2466 TARGET_TYPE *toBegin,
2467 TARGET_TYPE **fromEndPtr,
2468 TARGET_TYPE *fromBegin,
2469 TARGET_TYPE *position,
2470 TARGET_TYPE *fromEnd,
2471 FWD_ITER first,
2472 FWD_ITER last,
2473 size_type numElements,
2474 bslma::Allocator *basicAllocator)
2475{
2476 destructiveMoveAndInsert<bsl::allocator<TARGET_TYPE> >(toBegin,
2477 fromEndPtr,
2478 fromBegin,
2479 position,
2480 fromEnd,
2481 first,
2482 last,
2483 numElements,
2484 basicAllocator);
2485}
2486
2487template <class ALLOCATOR>
2490 typename bsl::allocator_traits<ALLOCATOR>::pointer *fromEndPtr,
2497 size_type numElements,
2498 ALLOCATOR allocator)
2499{
2500 // Key to the transformation diagrams:
2501 //..
2502 // A...H original contents of '[fromBegin, fromEnd)' ("source")
2503 // t...z original contents of '[first, last)' ("input")
2504 // ; ... contents of '[toBegin, toEnd)' ("destination")
2505 // ..:.. position of 'fromEndPtr' in the input
2506 // _____ uninitialized array elements
2507 // [...] part of array protected by an exception guard object
2508 //..
2509
2510 typedef typename bsl::allocator_traits<ALLOCATOR>::value_type TargetType;
2511
2512 *lastPtr = last;
2513 *fromEndPtr = fromEnd;
2514
2515 //..
2516 // Transformation: ABCDEFGH: ; _____________[]
2517 // => ABCD:____ ; _________[EFGH]
2518 //..
2519
2520 TargetType *toPositionBegin = toBegin + (position - fromBegin);
2521 TargetType *toPositionEnd = toPositionBegin + numElements;
2522
2523 destructiveMove(toPositionEnd,
2524 position,
2525 fromEnd,
2526 allocator);
2527
2528 *fromEndPtr = position; // shorten input range after partial destruction
2529
2531 guard(toPositionEnd,
2532 toPositionEnd + (fromEnd - position),
2533 allocator);
2534
2535 //..
2536 // Transformation: ABCD:____ ; _________[EFGH]
2537 // => ABCD:____ ; _____[tuvwEFGH]
2538 //..
2539
2540 destructiveMove(toPositionBegin,
2541 first,
2542 last,
2543 allocator);
2544
2545 *lastPtr = first;
2546 guard.moveBegin(-static_cast<difference_type>(numElements));
2547
2548 //..
2549 // Transformation: ABCD:____ ; ____[tuvwEFGH]
2550 // => :________ ; ABCDtuvwEFGH[]
2551 //..
2552
2553 destructiveMove(toBegin,
2554 fromBegin,
2555 position,
2556 allocator);
2557
2558 *fromEndPtr = fromBegin; // empty input range after final destruction
2559 guard.release();
2560}
2561
2562template <class TARGET_TYPE>
2563inline
2565 TARGET_TYPE *toBegin,
2566 TARGET_TYPE **fromEndPtr,
2567 TARGET_TYPE **lastPtr,
2568 TARGET_TYPE *fromBegin,
2569 TARGET_TYPE *position,
2570 TARGET_TYPE *fromEnd,
2571 TARGET_TYPE *first,
2572 TARGET_TYPE *last,
2573 size_type numElements,
2574 bslma::Allocator *basicAllocator)
2575{
2576 destructiveMoveAndMoveInsert<bsl::allocator<TARGET_TYPE> >(toBegin,
2577 fromEndPtr,
2578 lastPtr,
2579 fromBegin,
2580 position,
2581 fromEnd,
2582 first,
2583 last,
2584 numElements,
2585 basicAllocator);
2586}
2587
2588#if !BSLS_COMPILERFEATURES_SIMULATE_CPP11_FEATURES
2589template <class ALLOCATOR, class... ARGS>
2590inline
2594 ALLOCATOR allocator,
2595 ARGS&&... args)
2596{
2598 toEnd));
2600
2601 typedef typename bsl::allocator_traits<ALLOCATOR>::value_type TargetType;
2602
2603 enum {
2609 };
2610
2612 toBegin,
2613 toEnd,
2614 allocator,
2616 BSLS_COMPILERFEATURES_FORWARD(ARGS, args)...);
2617}
2618
2619template <class TARGET_TYPE, class... ARGS>
2620inline
2621void ArrayPrimitives::emplace(TARGET_TYPE *toBegin,
2622 TARGET_TYPE *toEnd,
2623 bslma::Allocator *basicAllocator,
2624 ARGS&&... args)
2625{
2626 emplace<bsl::allocator<TARGET_TYPE> >(
2627 toBegin,
2628 toEnd,
2629 basicAllocator,
2630 BSLS_COMPILERFEATURES_FORWARD(ARGS, args)...);
2631}
2632
2633#endif
2634
2635template <class ALLOCATOR>
2636inline
2641 ALLOCATOR allocator)
2642{
2645
2646 typedef typename bsl::allocator_traits<ALLOCATOR>::value_type TargetType;
2647
2648 if (first == middle) { // erasing empty range O(1) versus O(N): Do not
2649 // remove!
2650 return; // RETURN
2651 }
2652
2653 enum {
2657 };
2659 middle,
2660 last,
2661 allocator,
2663}
2664
2665template <class TARGET_TYPE>
2666inline
2667void ArrayPrimitives::erase(TARGET_TYPE *first,
2668 TARGET_TYPE *middle,
2669 TARGET_TYPE *last,
2670 bslma::Allocator *basicAllocator)
2671{
2672 erase<bsl::allocator<TARGET_TYPE> >(first,
2673 middle,
2674 last,
2675 basicAllocator);
2676}
2677
2678template <class ALLOCATOR>
2679inline
2685 ALLOCATOR allocator)
2686{
2689
2690 typedef typename bsl::allocator_traits<ALLOCATOR>::value_type TargetType;
2691
2692 if (toBegin != toEnd) {
2693 // Insert in the middle. Note that there is no strong exception
2694 // guarantee if copy constructor, move constructor, or assignment
2695 // operator throw.
2696
2697 enum {
2703 };
2704
2706 toBegin,
2707 toEnd,
2709 allocator,
2711 }
2712 else { // toBegin == toEnd
2714 allocator, toBegin, bslmf::MovableRefUtil::move(value));
2715 }
2716}
2717
2718template <class TARGET_TYPE>
2719inline
2720void ArrayPrimitives::insert(TARGET_TYPE *toBegin,
2721 TARGET_TYPE *toEnd,
2723 bslma::Allocator *basicAllocator)
2724{
2725 insert<bsl::allocator<TARGET_TYPE> >(toBegin,
2726 toEnd,
2728 basicAllocator);
2729}
2730
2731template <class ALLOCATOR>
2736 size_type numElements,
2737 ALLOCATOR allocator)
2738{
2741
2742 typedef typename bsl::allocator_traits<ALLOCATOR>::value_type TargetType;
2743
2744 if (0 == numElements) {
2745 return; // RETURN
2746 }
2747
2748 enum {
2754 };
2756 toEnd,
2757 value,
2758 numElements,
2759 allocator,
2761}
2762
2763template <class TARGET_TYPE>
2764inline
2765void ArrayPrimitives::insert(TARGET_TYPE *toBegin,
2766 TARGET_TYPE *toEnd,
2767 const TARGET_TYPE& value,
2768 size_type numElements,
2769 bslma::Allocator *basicAllocator)
2770{
2771 insert<bsl::allocator<TARGET_TYPE> >(toBegin,
2772 toEnd,
2773 value,
2774 numElements,
2775 basicAllocator);
2776}
2777
2778template <class ALLOCATOR, class FWD_ITER>
2782 FWD_ITER fromBegin,
2783 FWD_ITER fromEnd,
2784 size_type numElements,
2785 ALLOCATOR allocator)
2786{
2787 if (0 == numElements) {
2788 return; // RETURN
2789 }
2790
2791 typedef typename bsl::allocator_traits<ALLOCATOR>::value_type TargetType;
2792
2794
2795 /// Overload resolution will handle the case where `FWD_ITER` is a raw
2796 /// pointer, so we need handle only user-defined iterators. As `bslalg`
2797 /// is levelized below `bslstl` we cannot use `iterator_traits`, but
2798 /// rely on the same property as `iterator_traits` that this typedef
2799 /// must be defined for any standard-conforming iterator, unless the
2800 /// iterator explicitly specialized the `std::iterator_traits` template.
2801 /// In practice, iterators always prefer to provide the member typedef
2802 /// than specialize the traits as it is a much simpler implementation,
2803 /// so this assumption is good enough.
2804 ///
2805 /// Also note that as we know that `FWD_ITER` is not a pointer, then we
2806 /// cannot take advantage of bitwise copying as we do not have pointers
2807 /// to pass to the `memcpy` describing the whole range. It is not worth
2808 /// the effort to try to bitwise copy one element at a time.
2809 typedef typename FWD_ITER::value_type FwdTarget;
2810
2811 /// We want to detect the special case of copying function pointers to
2812 /// `void *` or `const void *` pointers.
2813 typedef typename bsl::remove_pointer<TargetType>::type RemovePtrTarget;
2814
2815 enum {
2816 k_ITER_TO_FUNC_PTRS = bslmf::IsFunctionPointer<FwdTarget>::value,
2817 k_TARGET_IS_VOID_PTR = bsl::is_pointer<TargetType>::value &&
2819
2820 k_VALUE = k_ITER_TO_FUNC_PTRS && k_TARGET_IS_VOID_PTR
2823 };
2825 toEnd,
2826 fromBegin,
2827 fromEnd,
2828 numElements,
2829 allocator,
2831}
2832
2833template <class TARGET_TYPE, class FWD_ITER>
2834inline
2835void ArrayPrimitives::insert(TARGET_TYPE *toBegin,
2836 TARGET_TYPE *toEnd,
2837 FWD_ITER fromBegin,
2838 FWD_ITER fromEnd,
2839 size_type numElements,
2840 bslma::Allocator *basicAllocator)
2841{
2842 insert<bsl::allocator<TARGET_TYPE> >(toBegin,
2843 toEnd,
2844 fromBegin,
2845 fromEnd,
2846 numElements,
2847 basicAllocator);
2848}
2849
2850template <class ALLOCATOR, class SOURCE_TYPE>
2854 SOURCE_TYPE *fromBegin,
2855 SOURCE_TYPE *fromEnd,
2856 size_type numElements,
2857 ALLOCATOR allocator)
2858{
2859 if (0 == numElements) {
2860 return; // RETURN
2861 }
2862
2863 typedef typename bsl::allocator_traits<ALLOCATOR>::value_type TargetType;
2864
2865 enum {
2866 k_ARE_PTRS_TO_PTRS = bsl::is_pointer<TargetType>::value &&
2868 k_IS_BITWISEMOVEABLE = bslmf::IsBitwiseMoveable<TargetType>::value,
2869 k_IS_BITWISECOPYABLE =
2871 k_VALUE = k_ARE_PTRS_TO_PTRS ? Imp::e_IS_POINTER_TO_POINTER
2872 : k_IS_BITWISECOPYABLE ? Imp::e_BITWISE_COPYABLE_TRAITS
2873 : k_IS_BITWISEMOVEABLE ? Imp::e_BITWISE_MOVEABLE_TRAITS
2875 };
2877 toEnd,
2878 fromBegin,
2879 fromEnd,
2880 numElements,
2881 allocator,
2883}
2884
2885template <class TARGET_TYPE, class SOURCE_TYPE>
2886inline
2887void ArrayPrimitives::insert(TARGET_TYPE *toBegin,
2888 TARGET_TYPE *toEnd,
2889 SOURCE_TYPE *fromBegin,
2890 SOURCE_TYPE *fromEnd,
2891 size_type numElements,
2892 bslma::Allocator *basicAllocator)
2893{
2894 insert<bsl::allocator<TARGET_TYPE> >(toBegin,
2895 toEnd,
2896 fromBegin,
2897 fromEnd,
2898 numElements,
2899 basicAllocator);
2900}
2901
2902template <class ALLOCATOR>
2903inline
2908 ALLOCATOR allocator)
2909{
2910 BSLS_ASSERT_SAFE(toBegin || fromBegin == fromEnd);
2911
2912 typedef typename bsl::allocator_traits<ALLOCATOR>::value_type TargetType;
2913
2914 enum {
2918 };
2919
2921 fromBegin,
2922 fromEnd,
2923 allocator,
2925}
2926
2927template <class TARGET_TYPE>
2928inline
2929void ArrayPrimitives::moveConstruct(TARGET_TYPE *toBegin,
2930 TARGET_TYPE *fromBegin,
2931 TARGET_TYPE *fromEnd,
2932 bslma::Allocator *basicAllocator)
2933{
2934 moveConstruct<bsl::allocator<TARGET_TYPE> >(toBegin,
2935 fromBegin,
2936 fromEnd,
2937 basicAllocator);
2938}
2939
2940template <class ALLOCATOR>
2941inline
2945 typename bsl::allocator_traits<ALLOCATOR>::pointer *fromEndPtr,
2948 size_type numElements,
2949 ALLOCATOR allocator)
2950{
2951 typedef typename bsl::allocator_traits<ALLOCATOR>::value_type TargetType;
2952
2953 enum {
2957 };
2959 toEnd,
2960 fromEndPtr,
2961 fromBegin,
2962 fromEnd,
2963 numElements,
2964 allocator,
2966}
2967
2968template <class TARGET_TYPE>
2969inline
2970void ArrayPrimitives::moveInsert(TARGET_TYPE *toBegin,
2971 TARGET_TYPE *toEnd,
2972 TARGET_TYPE **fromEndPtr,
2973 TARGET_TYPE *fromBegin,
2974 TARGET_TYPE *fromEnd,
2975 size_type numElements,
2976 bslma::Allocator *basicAllocator)
2977{
2978 moveInsert<bsl::allocator<TARGET_TYPE> >(toBegin,
2979 toEnd,
2980 fromEndPtr,
2981 fromBegin,
2982 fromEnd,
2983 numElements,
2984 basicAllocator);
2985}
2986
2987template <class TARGET_TYPE>
2988inline
2989void ArrayPrimitives::rotate(TARGET_TYPE *first,
2990 TARGET_TYPE *middle,
2991 TARGET_TYPE *last)
2992{
2994 middle));
2996 last));
2997
2998 enum {
3002 };
3004 middle,
3005 last,
3007}
3008
3009 // --------------------------
3010 // struct ArrayPrimitives_Imp
3011 // --------------------------
3012
3013// CLASS METHODS
3014template <class TARGET_TYPE>
3015inline
3016void ArrayPrimitives_Imp::assign(TARGET_TYPE *srcStart,
3017 TARGET_TYPE *srcEnd,
3018 TARGET_TYPE& value)
3019{
3020 for ( ; srcStart != srcEnd; ++srcStart) {
3021 *srcStart = value;
3022 }
3023}
3024
3025template <class FORWARD_ITERATOR>
3026inline
3028 FORWARD_ITERATOR)
3029{
3030 // Ideally would dispatch on random_access_iterator_tag to support
3031 // generalized random access iterators, but we are constrained by 'bsl'
3032 // levelization to not depend on 'bsl_iterator.h'. As the intent is to
3033 // detect invalid ranges in assertions, the conservative choice is to
3034 // return 'false' always. Note that this differs from the pointers case
3035 // below, which also disallows empty ranges.
3036
3037 return false;
3038}
3039
3040template <class TARGET_TYPE>
3041inline
3043 TARGET_TYPE *end)
3044{
3045 return !begin != !end || begin > end;
3046}
3047
3048template <class TARGET_TYPE>
3049inline
3050void ArrayPrimitives_Imp::reverseAssign(TARGET_TYPE *dest,
3051 TARGET_TYPE *srcStart,
3052 TARGET_TYPE *srcEnd)
3053{
3054 TARGET_TYPE *destEnd = srcEnd - srcStart + dest;
3055 while (srcStart != srcEnd) {
3056 *--destEnd = *--srcEnd;
3057 }
3058}
3059
3060
3061 // *** 'uninitializedFillN' overloads: ***
3062
3063inline
3065 bool *begin,
3066 bool value,
3067 size_type numElements,
3068 void *,
3070{
3071 BSLS_ASSERT_SAFE(begin || 0 == numElements);
3073 BSLMF_ASSERT(sizeof(bool) == 1);
3074
3075 if (BSLS_PERFORMANCEHINT_PREDICT_LIKELY(numElements != 0)) {
3076 std::memset(reinterpret_cast<char *>(begin), // odd, why not 'void *'?
3077 static_cast<char>(value),
3078 numElements);
3079 }
3080}
3081
3082inline
3084 char *begin,
3085 char value,
3086 size_type numElements,
3087 void *,
3089{
3090 BSLS_ASSERT_SAFE(begin || 0 == numElements);
3092
3093 if (BSLS_PERFORMANCEHINT_PREDICT_LIKELY(numElements != 0)) {
3094 std::memset(begin, value, numElements);
3095 }
3096}
3097
3098inline
3100 unsigned char *begin,
3101 unsigned char value,
3102 size_type numElements,
3103 void *,
3105{
3106 BSLS_ASSERT_SAFE(begin || 0 == numElements);
3108
3109 if (BSLS_PERFORMANCEHINT_PREDICT_LIKELY(numElements != 0)) {
3110 std::memset(begin, value, numElements);
3111 }
3112}
3113
3114inline
3116 signed char *begin,
3117 signed char value,
3118 size_type numElements,
3119 void *,
3121{
3122 BSLS_ASSERT_SAFE(begin || 0 == numElements);
3124
3125 if (BSLS_PERFORMANCEHINT_PREDICT_LIKELY(numElements != 0)) {
3126 std::memset(begin, value, numElements);
3127 }
3128}
3129
3130inline
3132 wchar_t *begin,
3133 wchar_t value,
3134 size_type numElements,
3135 void *,
3137{
3138 BSLS_ASSERT_SAFE(begin || 0 == numElements);
3140
3141 if (BSLS_PERFORMANCEHINT_PREDICT_LIKELY(numElements != 0)) {
3142 std::wmemset(begin, value, numElements);
3143 }
3144}
3145
3146inline
3148 unsigned short *begin,
3149 unsigned short value,
3150 size_type numElements,
3151 void *,
3153{
3154 BSLS_ASSERT_SAFE(begin || 0 == numElements);
3156
3158 reinterpret_cast<short *>(begin),
3159 static_cast<short>(value),
3160 numElements,
3161 (void *)0,
3163}
3164
3165inline
3167 unsigned int *begin,
3168 unsigned int value,
3169 size_type numElements,
3170 void *,
3172{
3173 BSLS_ASSERT_SAFE(begin || 0 == numElements);
3175
3177 reinterpret_cast<int *>(begin),
3178 static_cast<int>(value),
3179 numElements,
3180 (void *)0,
3182}
3183
3184inline
3186 long *begin,
3187 long value,
3188 size_type numElements,
3189 void *,
3191{
3192 BSLS_ASSERT_SAFE(begin || 0 == numElements);
3194
3195#if defined(BSLS_PLATFORM_CPU_64_BIT) && !defined(BSLS_PLATFORM_OS_WINDOWS)
3196 uninitializedFillN(reinterpret_cast<bsls::Types::Int64 *>(begin),
3197 static_cast<bsls::Types::Int64>(value),
3198 numElements);
3199#else
3201 reinterpret_cast<int *>(begin),
3202 static_cast<int>(value),
3203 numElements,
3204 (void *)0,
3206#endif
3207}
3208
3209inline
3211 unsigned long *begin,
3212 unsigned long value,
3213 size_type numElements,
3214 void *,
3216{
3217 BSLS_ASSERT_SAFE(begin || 0 == numElements);
3219
3220#if defined(BSLS_PLATFORM_CPU_64_BIT) && !defined(BSLS_PLATFORM_OS_WINDOWS)
3222 reinterpret_cast<bsls::Types::Int64 *>(begin),
3223 static_cast<bsls::Types::Int64>(value),
3224 numElements,
3225 (void *)0,
3227#else
3229 reinterpret_cast<int *>(begin),
3230 static_cast<int>(value),
3231 numElements,
3232 (void *)0,
3234#endif
3235}
3236
3237inline
3239 bsls::Types::Uint64 *begin,
3240 bsls::Types::Uint64 value,
3241 size_type numElements,
3242 void *,
3244{
3245 BSLS_ASSERT_SAFE(begin || 0 == numElements);
3247
3249 reinterpret_cast<bsls::Types::Int64 *>(begin),
3250 value,
3251 numElements,
3252 (void *)0,
3254}
3255
3256template <class TARGET_TYPE>
3257inline
3259 TARGET_TYPE **begin,
3260 TARGET_TYPE *value,
3261 size_type numElements,
3262 void *,
3264{
3265 BSLS_ASSERT_SAFE(begin || 0 == numElements);
3267
3268 // Note: 'const'-correctness is respected because the next overload picks
3269 // up the 'const TARGET_TYPE' and will be a better match. Note that we
3270 // cannot cast to 'const void **' (one would have to add 'const' at every
3271 // level, not just the innermost; i.e., 'const void *const *' would be
3272 // correct, 'const void **' is not [C++ Standard, 4.4 Qualification
3273 // conversions]).
3274
3276 reinterpret_cast<void **>(begin),
3277 static_cast<void *>(value),
3278 numElements,
3279 (void *)0,
3281}
3282
3283template <class TARGET_TYPE>
3284inline
3286 const TARGET_TYPE **begin,
3287 const TARGET_TYPE *value,
3288 size_type numElements,
3289 void *,
3291{
3292 BSLS_ASSERT_SAFE(begin || 0 == numElements);
3294
3295 // While it seems that this overload is subsumed by the previous template,
3296 // SunPro does not detect it.
3297
3299 reinterpret_cast<const void **>(begin),
3300 static_cast<const void *>(value),
3301 numElements,
3302 (void *)0,
3304}
3305
3306template <class TARGET_TYPE>
3307inline
3309 volatile TARGET_TYPE **begin,
3310 volatile TARGET_TYPE *value,
3311 size_type numElements,
3312 void *,
3314{
3315 BSLS_ASSERT_SAFE(begin || 0 == numElements);
3317
3318 // While it seems that this overload is subsumed by the previous template,
3319 // SunPro does not detect it.
3320
3322 reinterpret_cast<volatile void **>(begin),
3323 static_cast<volatile void *>(value),
3324 numElements,
3325 (void *)0,
3327}
3328
3329template <class TARGET_TYPE>
3330inline
3332 const volatile TARGET_TYPE **begin,
3333 const volatile TARGET_TYPE *value,
3334 size_type numElements,
3335 void *,
3337{
3338 BSLS_ASSERT_SAFE(begin || 0 == numElements);
3340
3341 // While it seems that this overload is subsumed by the previous template,
3342 // SunPro does not detect it.
3343
3345 reinterpret_cast<const volatile void **>(begin),
3346 static_cast<const volatile void *>(value),
3347 numElements,
3348 (void *)0,
3350}
3351
3352template <class TARGET_TYPE, class ALLOCATOR>
3354 TARGET_TYPE *begin,
3355 const TARGET_TYPE& value,
3356 size_type numElements,
3357 ALLOCATOR *,
3359{
3360 BSLS_ASSERT_SAFE(begin || 0 == numElements);
3362
3363 if (0 == numElements) {
3364 return; // RETURN
3365 }
3366
3367 const char *valueBuffer =
3368 reinterpret_cast<const char *>(BSLS_UTIL_ADDRESSOF(value));
3369
3370 std::memcpy((void *)begin, valueBuffer, sizeof(TARGET_TYPE));
3371 bitwiseFillN(reinterpret_cast<char *>(begin),
3372 sizeof(TARGET_TYPE),
3373 sizeof(TARGET_TYPE) * numElements);
3374}
3375
3376template <class TARGET_TYPE, class ALLOCATOR>
3378 TARGET_TYPE *begin,
3379 const TARGET_TYPE& value,
3380 size_type numElements,
3381 ALLOCATOR *allocator,
3383{
3384 BSLS_ASSERT_SAFE(begin || 0 == numElements);
3386 BSLS_ASSERT_SAFE(allocator);
3387
3388 if (0 == numElements) {
3389 return; // RETURN
3390 }
3392 begin,
3393 *allocator);
3394
3395 TARGET_TYPE *end = begin + numElements;
3396 do {
3397 bsl::allocator_traits<ALLOCATOR>::construct(*allocator, begin, value);
3398 begin = guard.moveEnd(1);
3399 } while (begin != end);
3400 guard.release();
3401}
3402
3403 // *** 'copyConstruct' overloads: ***
3404
3405template <class TARGET_TYPE, class FWD_ITER, class ALLOCATOR>
3406inline
3408 TARGET_TYPE *toBegin,
3409 FWD_ITER fromBegin,
3410 FWD_ITER fromEnd,
3411 ALLOCATOR allocator,
3413{
3414 // We may be casting a function pointer to a 'void *' here, so this won't
3415 // work if we port to an architecture where the two are of different sizes.
3416
3417 BSLMF_ASSERT(sizeof(void *) == sizeof(void (*)()));
3418
3419 typedef typename bsl::remove_cv<
3420 typename bsl::remove_pointer<TARGET_TYPE>::type>::type NcPtrType;
3421
3422 typedef typename bsl::remove_cv<
3423 typename bsl::remove_pointer<
3424 typename bsl::remove_pointer<FWD_ITER>::type>::type>::type NcIter;
3425
3426#if defined(BSLALG_ARRAYPRIMITIVES_CANNOT_REMOVE_POINTER_FROM_FUNCTION_POINTER)
3427 // fall back on traditional C-style casts.
3428 copyConstruct((void * *)toBegin,
3429 (void * const *)fromBegin,
3430 (void * const *)fromEnd,
3431 allocator,
3433#else
3435 reinterpret_cast<void * *>(const_cast<NcPtrType **>(toBegin)),
3436 reinterpret_cast<void * const *>(const_cast<NcIter * const *>(fromBegin)),
3437 reinterpret_cast<void * const *>(const_cast<NcIter * const *>(fromEnd)),
3438 allocator,
3440#endif
3441}
3442
3443template <class FWD_ITER, class ALLOCATOR>
3445 void **toBegin,
3446 FWD_ITER fromBegin,
3447 FWD_ITER fromEnd,
3448 ALLOCATOR,
3450{
3451 BSLMF_ASSERT(sizeof(void *) == sizeof(void (*)()));
3452 // We will be casting a function pointer to a 'void *', so this won't
3453 // work if we port to an architecture where the two are of different
3454 // sizes.
3455
3456 BSLS_ASSERT_SAFE(toBegin || fromBegin == fromEnd);
3458
3459 while (fromBegin != fromEnd) {
3460 // 'fromBegin' iterates over pointers to functions, which must be
3461 // @ref reinterpret_cast to 'void *'.
3462
3463 *toBegin = reinterpret_cast<void *>(*fromBegin);
3464 ++fromBegin;
3465 ++toBegin;
3466 }
3467}
3468
3469template <class TARGET_TYPE, class ALLOCATOR>
3470inline
3472 TARGET_TYPE *toBegin,
3473 const TARGET_TYPE *fromBegin,
3474 const TARGET_TYPE *fromEnd,
3475 ALLOCATOR,
3477{
3478 BSLS_ASSERT_SAFE(toBegin);
3480 fromEnd));
3481
3482 const size_type numBytes = reinterpret_cast<const char*>(fromEnd)
3483 - reinterpret_cast<const char*>(fromBegin);
3484 if (BSLS_PERFORMANCEHINT_PREDICT_LIKELY(numBytes != 0)) {
3485 std::memcpy((void *)toBegin, fromBegin, numBytes);
3486 }
3487}
3488
3489template <class TARGET_TYPE, class FWD_ITER, class ALLOCATOR>
3491 TARGET_TYPE *toBegin,
3492 FWD_ITER fromBegin,
3493 FWD_ITER fromEnd,
3494 ALLOCATOR allocator,
3496{
3497 BSLS_ASSERT_SAFE(toBegin || fromBegin == fromEnd);
3499 fromEnd));
3500
3501 AutoArrayDestructor<TARGET_TYPE, ALLOCATOR> guard(toBegin, toBegin,
3502 allocator);
3503
3504 while (fromBegin != fromEnd) {
3505 // Note: We are not sure the value type of 'FWD_ITER' is convertible to
3506 // 'TARGET_TYPE'. Use 'construct' instead.
3507
3509 toBegin,
3510 *fromBegin);
3511 ++fromBegin;
3512 toBegin = guard.moveEnd(1);
3513 }
3514 guard.release();
3515}
3516
3517 // *** 'moveConstruct' overloads: ***
3518template <class TARGET_TYPE, class ALLOCATOR>
3519inline
3521 TARGET_TYPE *toBegin,
3522 TARGET_TYPE *fromBegin,
3523 TARGET_TYPE *fromEnd,
3524 ALLOCATOR,
3526{
3527 BSLS_ASSERT_SAFE(toBegin);
3529 fromEnd));
3530
3531 const size_type numBytes = reinterpret_cast<const char*>(fromEnd)
3532 - reinterpret_cast<const char*>(fromBegin);
3533 if (BSLS_PERFORMANCEHINT_PREDICT_LIKELY(numBytes != 0)) {
3534 std::memcpy((void *)toBegin, fromBegin, numBytes);
3535 }
3536}
3537
3538template <class TARGET_TYPE, class ALLOCATOR>
3540 TARGET_TYPE *toBegin,
3541 TARGET_TYPE *fromBegin,
3542 TARGET_TYPE *fromEnd,
3543 ALLOCATOR allocator,
3545{
3546 BSLS_ASSERT_SAFE(toBegin || fromBegin == fromEnd);
3548 fromEnd));
3549
3550 AutoArrayDestructor<TARGET_TYPE, ALLOCATOR> guard(toBegin, toBegin,
3551 allocator);
3552
3553 while (fromBegin != fromEnd) {
3555 allocator,
3556 toBegin,
3557 bslmf::MovableRefUtil::move(*fromBegin));
3558 ++fromBegin;
3559 toBegin = guard.moveEnd(1);
3560 }
3561 guard.release();
3562}
3563
3564template <class TARGET_TYPE, class ALLOCATOR>
3566 TARGET_TYPE *toBegin,
3567 TARGET_TYPE *fromBegin,
3568 TARGET_TYPE *fromEnd,
3569 ALLOCATOR allocator,
3571{
3572 BSLS_ASSERT_SAFE(toBegin || fromBegin == fromEnd);
3574 fromEnd));
3575
3576 AutoArrayDestructor<TARGET_TYPE, ALLOCATOR> guard(toBegin, toBegin,
3577 allocator);
3578
3579 while (fromBegin != fromEnd) {
3581 allocator,
3582 toBegin,
3584 ++fromBegin;
3585 toBegin = guard.moveEnd(1);
3586 }
3587 guard.release();
3588}
3589
3590
3591 // *** 'defaultConstruct' overloads: ***
3592
3593template <class TARGET_TYPE, class ALLOCATOR>
3594inline
3596 TARGET_TYPE *begin,
3597 size_type numElements,
3598 ALLOCATOR,
3600{
3601 BSLS_ASSERT_SAFE(begin || 0 == numElements);
3603
3604 if (BSLS_PERFORMANCEHINT_PREDICT_LIKELY(numElements != 0)) {
3605 std::memset(static_cast<void *>(begin),
3606 0,
3607 sizeof(TARGET_TYPE) * numElements);
3608 }
3609}
3610
3611template <class TARGET_TYPE, class ALLOCATOR>
3612inline
3614 TARGET_TYPE *begin,
3615 size_type numElements,
3616 ALLOCATOR allocator,
3618{
3619 BSLS_ASSERT_SAFE(begin || 0 == numElements);
3621
3622 if (0 < numElements) {
3624 bitwiseFillN(reinterpret_cast<char *>(begin),
3625 sizeof(TARGET_TYPE),
3626 numElements * sizeof(TARGET_TYPE));
3627 }
3628}
3629
3630template <class TARGET_TYPE, class ALLOCATOR>
3632 TARGET_TYPE *begin,
3633 size_type numElements,
3634 ALLOCATOR allocator,
3636{
3637 BSLS_ASSERT_SAFE(begin || 0 == numElements);
3639
3640 AutoArrayDestructor<TARGET_TYPE, ALLOCATOR> guard(begin, begin, allocator);
3641
3642 const TARGET_TYPE *end = begin + numElements;
3643 while (begin != end) {
3645 begin = guard.moveEnd(1);
3646 }
3647 guard.release();
3648}
3649
3650 // *** 'destructiveMove' overloads: ***
3651
3652template <class TARGET_TYPE, class ALLOCATOR>
3653inline
3655 TARGET_TYPE *toBegin,
3656 TARGET_TYPE *fromBegin,
3657 TARGET_TYPE *fromEnd,
3658 ALLOCATOR,
3660{
3661 BSLS_ASSERT_SAFE(toBegin || fromBegin == fromEnd);
3663 fromEnd));
3664
3665 const size_type numBytes = reinterpret_cast<const char*>(fromEnd)
3666 - reinterpret_cast<const char*>(fromBegin);
3667 if (BSLS_PERFORMANCEHINT_PREDICT_LIKELY(numBytes != 0)) {
3668 std::memcpy((void *)toBegin, fromBegin, numBytes);
3669 }
3670}
3671
3672template <class TARGET_TYPE, class ALLOCATOR>
3673inline
3675 TARGET_TYPE *toBegin,
3676 TARGET_TYPE *fromBegin,
3677 TARGET_TYPE *fromEnd,
3678 ALLOCATOR allocator,
3680{
3681 BSLS_ASSERT_SAFE(toBegin || fromBegin == fromEnd);
3683 fromEnd));
3684
3685 // 'TARGET_TYPE' certainly cannot be bit-wise copyable, so we can save the
3686 // compiler some work.
3687
3688 moveIfNoexcept(toBegin, fromBegin, fromEnd, allocator,
3690 ArrayDestructionPrimitives::destroy(fromBegin, fromEnd, allocator);
3691}
3692
3693 // *** 'emplace' with 'args' overloads: ***
3694
3695#if !BSLS_COMPILERFEATURES_SIMULATE_CPP11_FEATURES
3696template <class TARGET_TYPE, class ALLOCATOR, class... ARGS>
3697inline
3699 TARGET_TYPE *toBegin,
3700 TARGET_TYPE *toEnd,
3701 ALLOCATOR allocator,
3703 ARGS&&... args)
3704{
3705 // TBD: The implementation is exactly the same as 'BITWISE_MOVEABLE_TRAITS'
3706 // unless 'AutoArrayMoveDestructor' has a 'release' method so the guard can
3707 // be called off after one in-place construction. Then an optimization
3708 // using 'bitwiseFillN' is possible.
3709
3711 toBegin,
3712 toEnd,
3713 allocator,
3715 BSLS_COMPILERFEATURES_FORWARD(ARGS, args)...);
3716}
3717
3718template <class TARGET_TYPE, class ALLOCATOR, class... ARGS>
3720 TARGET_TYPE *toBegin,
3721 TARGET_TYPE *toEnd,
3722 ALLOCATOR allocator,
3724 ARGS&&... args)
3725{
3727 toEnd));
3729
3730 // TBD: fix to reflect that its only a single item....
3731 size_type numElements = 1;
3732
3733 // Key to the transformation diagrams:
3734 //..
3735 // A...G original contents of '[toBegin, toEnd)' ("tail")
3736 // v...v contents of '[fromBegin, fromEnd)' ("input")
3737 // _____ uninitialized array element
3738 // [...] part of an array guarded by an exception guard object
3739 // |.(.,.) part of array guarded by move guard
3740 // (middle indicated by ',' and dest by '|')
3741 //..
3742
3743 size_type tailLen = toEnd - toBegin;
3744 size_type numGuarded = tailLen < numElements ? tailLen : numElements;
3745
3746 //..
3747 // Transformation: ABCDE_______ => _______ABCDE (might overlap)
3748 //..
3749
3750 TARGET_TYPE *destBegin = toBegin + numElements;
3751 if (BSLS_PERFORMANCEHINT_PREDICT_LIKELY(tailLen != 0)) {
3752 std::memmove((void *)destBegin,
3753 toBegin,
3754 tailLen * sizeof(TARGET_TYPE));
3755 }
3756
3757 //..
3758 // Transformation: |_______(,ABCDE) => vvvvv|__(ABCDE,)
3759 //..
3760
3761 TARGET_TYPE *destEnd = toEnd + numElements;
3762
3764 destEnd - numGuarded,
3765 destEnd - numGuarded,
3766 destEnd,
3767 allocator);
3768
3769 while (guard.middle() != guard.end()) {
3771 guard.destination(),
3772 BSLS_COMPILERFEATURES_FORWARD(ARGS, args)...);
3773 guard.advance();
3774 }
3775
3776 // The bitwise 'guard' is now inactive, since 'middle() == end()' and
3777 // 'guard.destination()' is the smaller of 'destBegin' or 'toEnd'.
3778
3779 if (tailLen < numElements) {
3780 // There still is a gap of 'numElements - tailLen' to fill in between
3781 // 'toEnd' and 'destBegin'. The elements that have been 'memmove'-ed
3782 // need to be guarded, we fill the gap backward from there to keep
3783 // guarded portion in one piece.
3784
3786 destEnd,
3787 allocator);
3788
3789 //..
3790 // Transformation: vvvvv__[ABCDE] => vvvvv[vvABCDE]
3791 //..
3792
3793 while (toEnd != destBegin) {
3795 --destBegin,
3796 BSLS_COMPILERFEATURES_FORWARD(ARGS,args)...);
3797
3798 endGuard.moveBegin(-1);
3799 }
3800 endGuard.release();
3801 }
3802}
3803
3804template <class TARGET_TYPE, class ALLOCATOR, class... ARGS>
3806 TARGET_TYPE *toBegin,
3807 TARGET_TYPE *toEnd,
3808 ALLOCATOR allocator,
3810 ARGS&&... args)
3811{
3813 toEnd));
3815
3816 // Key to the transformation diagrams:
3817 //..
3818 // A...G original contents of '[toBegin, toEnd)' ("tail")
3819 // v...v copies of 'value' ("input")
3820 // _____ uninitialized array elements
3821 // [...] part of array protected by an exception guard object
3822 //..
3823
3824 if (toEnd > toBegin) {
3825 // Insert in the middle. First, construct a temporary object from the
3826 // parameter pack of the strong exception guarantee if the construction
3827 // throws. A welcome consequence is that the parameter pack may refer
3828 // (directly or indirectly) into a container element.
3829
3832 allocator,
3833 BSLS_UTIL_ADDRESSOF(space.object()),
3834 BSLS_COMPILERFEATURES_FORWARD(ARGS, args)...);
3836 BSLS_UTIL_ADDRESSOF(space.object()));
3837
3838 //..
3839 // Transformation: ABCDEFG_[] => ABCDEFG[G].
3840 //..
3841
3843 allocator,
3844 toEnd,
3846
3848 toEnd + 1,
3849 allocator);
3850
3851 //..
3852 // Transformation: ABCDEFG[G] => AABCDEF[G].
3853 //..
3854
3855 TARGET_TYPE *destEnd = toEnd;
3856 TARGET_TYPE *srcEnd = toEnd - 1;
3857 while (toBegin != srcEnd) {
3858 *--destEnd = bslmf::MovableRefUtil::move_if_noexcept(*--srcEnd);
3859 }
3860
3861 //..
3862 // Transformation: AABCDEFG[G] => vABCDEF[G].
3863 //..
3864
3866
3867 guard.release();
3868 }
3869 else {
3870 //..
3871 // Transformation: _ => v.
3872 //..
3873
3875 allocator, toEnd, BSLS_COMPILERFEATURES_FORWARD(ARGS, args)...);
3876 }
3877}
3878#endif
3879
3880 // *** 'erase' overloads: ***
3881
3882template <class TARGET_TYPE, class ALLOCATOR>
3884 TARGET_TYPE *first,
3885 TARGET_TYPE *middle,
3886 TARGET_TYPE *last,
3887 ALLOCATOR allocator,
3889{
3892
3893 // Key to the transformation diagrams:
3894 //..
3895 // t...z Original contents of '[first, middle)'
3896 // A...G Original contents of '[middle, last)'
3897 // _ Destroyed array element
3898 //..
3899
3900 //..
3901 // Transformation: tuvABCDEFG => ___ABCDEFG (no throw)
3902 //..
3903 ArrayDestructionPrimitives::destroy(first, middle, allocator);
3904
3905 //..
3906 // Transformation: ___ABCDEFG => ABCDEFG___ (might overlap, but no throw)
3907 //..
3908 size_type numBytes = reinterpret_cast<const char *>(last)
3909 - reinterpret_cast<const char *>(middle);
3910 if (BSLS_PERFORMANCEHINT_PREDICT_LIKELY(numBytes != 0)) {
3911 std::memmove((void *)first, middle, numBytes);
3912 }
3913}
3914
3915template <class TARGET_TYPE, class ALLOCATOR>
3917 TARGET_TYPE *first,
3918 TARGET_TYPE *middle,
3919 TARGET_TYPE *last,
3920 ALLOCATOR allocator,
3922{
3925
3926 // Key to the transformation diagrams:
3927 //..
3928 // t...z Original contents of '[first, middle)'
3929 // A...G Original contents of '[middle, last)'
3930 // _ Destructed array element
3931 //..
3932
3933 //..
3934 // Transformation: tuvABCDEFG => ABCDEFGEFG.
3935 //..
3936
3937 while (middle != last) {
3938 *first++ = bslmf::MovableRefUtil::move_if_noexcept(*middle++);
3939 }
3940
3941 //..
3942 // Transformation: ABCDEFGEFG => ABCDEFG___.
3943 //..
3944
3945 ArrayDestructionPrimitives::destroy(first, middle, allocator);
3946}
3947
3948 // *** 'insert' with 'value' overloads: ***
3949
3950template <class TARGET_TYPE, class ALLOCATOR>
3951inline
3953 TARGET_TYPE *toBegin,
3954 TARGET_TYPE *toEnd,
3955 const TARGET_TYPE& value,
3956 size_type numElements,
3957 ALLOCATOR allocator,
3959{
3962
3963 // Key to the transformation diagrams:
3964 //..
3965 // A...G original contents of '[toBegin, toEnd)' ("tail")
3966 // v...v contents of '[fromBegin, fromEnd)' ("input")
3967 // _____ uninitialized array element
3968 //..
3969
3970 // ALIASING: If 'value' is a reference into the array 'toBegin..toEnd',
3971 // then moving the array first might introduce a change in 'value'. Since
3972 // type is bitwise copyable, then no memory changes outside the array, so
3973 // the test below is sufficient to discover all the possible aliasing.
3974 // Note that we never make a copy.
3975
3976 const TARGET_TYPE *tempValuePtr = BSLS_UTIL_ADDRESSOF(value);
3977 if (toBegin <= tempValuePtr && tempValuePtr < toEnd ) {
3978 // Adjust pointer for shifting after the move.
3979
3980 tempValuePtr += numElements;
3981 }
3982
3983 //..
3984 // Transformation: ABCDE___ => ___ABCDE (might overlap).
3985 //..
3986
3987 const size_type numBytes = reinterpret_cast<const char*>(toEnd)
3988 - reinterpret_cast<const char*>(toBegin);
3989 if (BSLS_PERFORMANCEHINT_PREDICT_LIKELY(numBytes != 0)) {
3990 std::memmove((void *)(toBegin + numElements), toBegin, numBytes);
3991 }
3992
3993 //..
3994 // Transformation: ___ABCDE => v__ABCDE (no overlap).
3995 //..
3996
3997 // Use 'copyConstruct' instead of 'memcpy' because the former optimizes for
3998 // fundamental types using 'operator=' instead, which avoid the 'memcpy'
3999 // function call.
4000
4002 toBegin,
4003 *tempValuePtr);
4004 //..
4005 // Transformation: v__ABCDE => vvvABCDE.
4006 //..
4007
4008 bitwiseFillN(reinterpret_cast<char *>(toBegin),
4009 sizeof value,
4010 numElements * sizeof value);
4011}
4012
4013template <class TARGET_TYPE, class ALLOCATOR>
4015 TARGET_TYPE *toBegin,
4016 TARGET_TYPE *toEnd,
4017 const TARGET_TYPE& value,
4018 size_type numElements,
4019 ALLOCATOR allocator,
4021{
4024
4025 // Key to the transformation diagrams:
4026 //..
4027 // A...G original contents of '[toBegin, toEnd)' ("tail")
4028 // v...v contents of '[fromBegin, fromEnd)' ("input")
4029 // _____ uninitialized array element
4030 // [...] part of an array guarded by an exception guard object
4031 // |.(.,.) part of array guarded by move guard
4032 // (middle indicated by ',' and dest by '|')
4033 //..
4034
4035 const TARGET_TYPE *tempValuePtr = BSLS_UTIL_ADDRESSOF(value);
4036 if (toBegin <= tempValuePtr && tempValuePtr < toEnd + numElements) {
4037 // Adjust pointer for shifting after the move.
4038
4039 tempValuePtr += numElements;
4040 }
4041
4042 size_type tailLen = toEnd - toBegin;
4043 size_type numGuarded = tailLen < numElements ? tailLen : numElements;
4044
4045 //..
4046 // Transformation: ABCDE_______ => _______ABCDE (might overlap)
4047 //..
4048
4049 TARGET_TYPE *destBegin = toBegin + numElements;
4050 if (BSLS_PERFORMANCEHINT_PREDICT_LIKELY(tailLen != 0)) {
4051 std::memmove((void *)destBegin,
4052 toBegin,
4053 tailLen * sizeof(TARGET_TYPE));
4054 }
4055
4056 //..
4057 // Transformation: |_______(,ABCDE) => vvvvv|__(ABCDE,)
4058 //..
4059
4060 TARGET_TYPE *destEnd = toEnd + numElements;
4061
4063 destEnd - numGuarded,
4064 destEnd - numGuarded,
4065 destEnd,
4066 allocator);
4067
4068 while (guard.middle() != guard.end()) {
4070 guard.destination(),
4071 *tempValuePtr);
4072 guard.advance();
4073 }
4074
4075 // The bitwise 'guard' is now inactive, since 'middle() == end()' and
4076 // 'guard.destination()' is the smaller of 'destBegin' or 'toEnd'.
4077
4078 if (tailLen < numElements) {
4079 // There still is a gap of 'numElements - tailLen' to fill in between
4080 // 'toEnd' and 'destBegin'. The elements that have been 'memmove'-ed
4081 // need to be guarded, we fill the gap backward from there to keep
4082 // guarded portion in one piece.
4083
4085 destEnd,
4086 allocator);
4087
4088 //..
4089 // Transformation: vvvvv__[ABCDE] => vvvvv[vvABCDE]
4090 //..
4091
4092 while (toEnd != destBegin) {
4094 --destBegin,
4095 *tempValuePtr);
4096
4097 endGuard.moveBegin(-1);
4098 }
4099 endGuard.release();
4100 }
4101}
4102
4103template <class TARGET_TYPE, class ALLOCATOR>
4105 TARGET_TYPE *toBegin,
4106 TARGET_TYPE *toEnd,
4107 const TARGET_TYPE& value,
4108 size_type numElements,
4109 ALLOCATOR allocator,
4111{
4114
4115 // Aliasing: Make a temp copy of 'value' (always). The reason is that
4116 // 'value' could be a reference inside the input range, or even outside
4117 // but with lifetime controlled by one of these values, and so the next
4118 // transformation could invalidate 'value'. Note: One cannot rely on
4119 // 'TARGET_TYPE' to have a single-argument copy constructor (i.e.,
4120 // default allocator argument to 0) if it takes an allocator; hence the
4121 // constructor proxy.
4122
4126 value);
4128 BSLS_UTIL_ADDRESSOF(space.object()));
4129
4130 // Key to the transformation diagrams:
4131 //..
4132 // A...G original contents of '[toBegin, toEnd)' ("tail")
4133 // v...v copies of 'value' ("input")
4134 // _____ uninitialized array elements
4135 // [...] part of array protected by an exception guard object
4136 //..
4137
4138 const size_type tailLen = toEnd - toBegin;
4139 if (tailLen >= numElements) {
4140 // Tail is not shorter than input.
4141
4142 //..
4143 // Transformation: ABCDEFG___[] => ABCDEFG[EFG].
4144 //..
4145
4146 moveIfNoexcept(toEnd, // destination
4147 toEnd - numElements, // source
4148 toEnd, // end source
4149 allocator,
4151
4153 toEnd + numElements,
4154 allocator);
4155
4156 // TBD: this does the same thing as the old code - don't like that we
4157 // circumvent the whole allocator thing, but for now, let's keep it
4158 // consistent.
4159 // ConstructorProxy<TARGET_TYPE>
4160 // tempValue(value, bslma::Default::allocator());
4161
4162 //..
4163 // Transformation: ABCDEFG[EFG] => ABCABCD[EFG].
4164 //..
4165
4166 TARGET_TYPE *src = toEnd - numElements;
4167 TARGET_TYPE *dest = toEnd;
4168 while (toBegin != src) {
4170 }
4171
4172 //..
4173 // Transformation: ABCABCD[EFG] => vvvABCD[EFG].
4174 //..
4175
4176 for ( ; toBegin != dest; ++toBegin) {
4177 *toBegin = space.object();
4178 }
4179 // TBD: this can't be good
4180 guard.release();
4181 }
4182 else {
4183 // Tail is shorter than input. We can avoid the temp copy of value
4184 // since there will be space to make a first copy after the tail, and
4185 // use that to make the subsequent copies.
4186 //
4187 // TBD: Update comment now that the assumption is no longer true, and
4188 // we make a copy at the top of the call, regardless. We could
4189 // restore this optimization if we use metaprogramming to check if
4190 // 'moveIfNoexcept' will move or copy, but not convinced it is worth
4191 // the complexity.
4192
4193 difference_type remElements = numElements - tailLen;
4194
4195 //..
4196 // Transformation: ABC_______[] => ABC____[ABC].
4197 //..
4198
4199 moveIfNoexcept(toBegin + numElements, // destination
4200 toBegin, // source
4201 toEnd, // end source
4202 allocator,
4204
4205 AutoArrayDestructor<TARGET_TYPE, ALLOCATOR> guard(toEnd + remElements,
4206 toEnd + numElements,
4207 allocator);
4208
4209 //..
4210 // Transformation: ABC____[ABC] => ABC[vvvvABC].
4211 //..
4212
4213 uninitializedFillN(toEnd,
4214 space.object(),
4215 remElements,
4216 &allocator,
4218 guard.moveBegin(-remElements);
4219
4220 //..
4221 // Transformation: ABC[vvvvABC] => vvv[vvvvABC].
4222 //..
4223
4224 for ( ; toBegin != toEnd; ++toBegin) {
4225 *toBegin = space.object();
4226 }
4227
4228 guard.release();
4229 }
4230}
4231
4232 // *** 'insert' with 'FWD_ITER' overloads: ***
4233
4234
4235template <class TARGET_TYPE, class FWD_ITER, class ALLOCATOR>
4236inline
4238 TARGET_TYPE *toBegin,
4239 TARGET_TYPE *toEnd,
4240 FWD_ITER fromBegin,
4241 FWD_ITER fromEnd,
4242 size_type numElements,
4243 ALLOCATOR allocator,
4245{
4246 // We may be casting a function pointer to a 'void *' here, so this won't
4247 // work if we port to an architecture where the two are of different sizes.
4248
4249 BSLMF_ASSERT(sizeof(void *) == sizeof(void (*)()));
4250
4251#if defined(BSLALG_ARRAYPRIMITIVES_CANNOT_REMOVE_POINTER_FROM_FUNCTION_POINTER)
4252 // fall back on traditional C-style casts.
4253 insert((void * *)toBegin,
4254 (void * *)toEnd,
4255 (void * const *)fromBegin,
4256 (void * const *)fromEnd,
4257 numElements,
4258 allocator,
4260#else
4261 typedef typename bsl::remove_cv<
4262 typename bsl::remove_pointer<TARGET_TYPE>::type>::type NcPtrType;
4263
4264 typedef typename bsl::remove_cv<
4265 typename bsl::remove_pointer<
4266 typename bsl::remove_pointer<FWD_ITER>::type>::type>::type NcIter;
4267
4268 insert(
4269 reinterpret_cast<void * *>(const_cast<NcPtrType **>(toBegin)),
4270 reinterpret_cast<void * *>(const_cast<NcPtrType **>(toEnd)),
4271 reinterpret_cast<void * const *>(const_cast<NcIter * const *>(fromBegin)),
4272 reinterpret_cast<void * const *>(const_cast<NcIter * const *>(fromEnd)),
4273 numElements,
4274 allocator,
4276#endif
4277}
4278
4279template <class TARGET_TYPE, class ALLOCATOR>
4280inline
4282 TARGET_TYPE *toBegin,
4283 TARGET_TYPE *toEnd,
4284 const TARGET_TYPE *fromBegin,
4285 const TARGET_TYPE *fromEnd,
4286 size_type numElements,
4287 ALLOCATOR,
4289{
4291
4292 // 'FWD_ITER' has been converted to a 'const TARGET_TYPE *' and
4293 // 'TARGET_TYPE' is bit-wise copyable.
4296 BSLS_ASSERT_SAFE(fromBegin || 0 == numElements);
4297
4298 BSLS_ASSERT_SAFE(fromBegin + numElements == fromEnd);
4299 BSLS_ASSERT_SAFE(fromEnd <= toBegin || toEnd + numElements <= fromBegin);
4300
4301 (void) fromEnd; // quell warning when 'BSLS_ASSERT_SAFE' is compiled out
4302
4303 // Key to the transformation diagrams:
4304 //..
4305 // A...G original contents of '[toBegin, toEnd)' ("tail")
4306 // t...z contents of '[fromBegin, fromEnd)' ("input")
4307 // _____ uninitialized array element
4308 //..
4309
4310 //..
4311 // Transformation: ABCDE_______ => _______ABCDE (might overlap).
4312 //..
4313
4314 const size_type numBytes = reinterpret_cast<const char*>(toEnd)
4315 - reinterpret_cast<const char*>(toBegin);
4316 if (BSLS_PERFORMANCEHINT_PREDICT_LIKELY(numBytes != 0)) {
4317 std::memmove((void *)(toBegin + numElements), toBegin, numBytes);
4318 }
4319
4320 //..
4321 // Transformation: _______ABCDE => tuvwxyzABCDE (no overlap).
4322 //..
4323
4324 if (BSLS_PERFORMANCEHINT_PREDICT_LIKELY(numElements != 0)) {
4325 std::memcpy((void *)toBegin,
4326 fromBegin,
4327 numElements * sizeof(TARGET_TYPE));
4328 }
4329}
4330
4331template <class TARGET_TYPE, class FWD_ITER, class ALLOCATOR>
4333 TARGET_TYPE *toBegin,
4334 TARGET_TYPE *toEnd,
4335 FWD_ITER fromBegin,
4336 FWD_ITER,
4337 size_type numElements,
4338 ALLOCATOR allocator,
4340{
4341 // 'TARGET_TYPE' is bit-wise moveable.
4344
4345 if (0 == numElements) {
4346 return; // RETURN
4347 }
4348
4349 // The following assertions make sense only if 'FWD_ITER' is a pointer to a
4350 // possibly cv-qualified 'TARGET_TYPE', and are tested in that overload
4351 // (see above).
4352 //..
4353 // BSLS_ASSERT(fromBegin + numElements == fromEnd);
4354 // BSLS_ASSERT(fromEnd <= toBegin || toEnd + numElements <= fromBegin);
4355 //..
4356
4357 // Key to the transformation diagrams:
4358 //..
4359 // A...G original contents of '[toBegin, toEnd)' ("tail")
4360 // t...z contents of '[fromBegin, fromEnd)' ("input")
4361 // _____ uninitialized array element
4362 // [...] part of array guarded by exception guard
4363 // |.(.,.) part of array guarded by move guard
4364 // (middle indicated by ',' and dest by '|')
4365 //..
4366
4367 const size_type tailLen = toEnd - toBegin;
4368 const size_type numGuarded = tailLen < numElements ? tailLen : numElements;
4369
4370 //..
4371 // Transformation: ABCDE____ => ____ABCDE (might overlap).
4372 //..
4373
4374 TARGET_TYPE *destBegin = toBegin + numElements;
4375 if (BSLS_PERFORMANCEHINT_PREDICT_LIKELY(tailLen != 0)) {
4376 std::memmove((void *)destBegin,
4377 toBegin,
4378 tailLen * sizeof(TARGET_TYPE));
4379 }
4380
4381 //..
4382 // Transformation: |_______(,ABCDE) => tuvwx|__(ABCDE,).
4383 //..
4384
4385 TARGET_TYPE *destEnd = toEnd + numElements;
4386
4388 destEnd - numGuarded,
4389 destEnd - numGuarded,
4390 destEnd,
4391 allocator);
4392
4393 for (; guard.middle() != guard.end(); ++fromBegin) {
4395 guard.destination(),
4396 *fromBegin);
4397 guard.advance();
4398 }
4399
4400 // The bitwise 'guard' is now inactive, since 'middle() == end()', and
4401 // 'guard.destination()' is the smaller of 'destBegin' or 'toEnd'.
4402
4403 if (tailLen < numElements) {
4404 // There still is a gap of 'numElements - tailLen' to fill in between
4405 // 'toEnd' and 'destBegin'. The elements that have been 'memmove'-ed
4406 // need to be guarded, and we need to continue to fill the hole at the
4407 // same guarding the copied elements as well.
4408
4410 toEnd,
4411 allocator);
4413 destEnd,
4414 allocator);
4415
4416 //..
4417 // Transformation: tuvwx[]__[ABCDE] => tuvwx[yz][ABCDE].
4418 //..
4419
4420 for (; toEnd != destBegin; ++fromBegin) {
4422 toEnd,
4423 *fromBegin);
4424 toEnd = endGuard1.moveEnd(1);
4425 }
4426 endGuard1.release();
4427 endGuard2.release();
4428 }
4429}
4430
4431template <class TARGET_TYPE, class FWD_ITER, class ALLOCATOR>
4433 TARGET_TYPE *toBegin,
4434 TARGET_TYPE *toEnd,
4435 FWD_ITER fromBegin,
4436 FWD_ITER fromEnd,
4437 size_type numElements,
4438 ALLOCATOR allocator,
4440{
4443
4444 if (0 == numElements) {
4445 return; // RETURN
4446 }
4447
4448 // Key to the transformation diagrams:
4449 //..
4450 // A...G original contents of '[toBegin, toEnd)' ("tail")
4451 // t...z contents of '[fromBegin, fromEnd)' ("input")
4452 // _____ uninitialized array elements
4453 // [...] part of array protected by a guard object
4454 //..
4455
4456 const size_type tailLen = toEnd - toBegin;
4457 if (tailLen > numElements) {
4458 // Tail is longer than input.
4459
4460 //..
4461 // Transformation: ABCDEFG___[] => ABCDEFG[EFG].
4462 //..
4463
4464 moveIfNoexcept(toEnd, // destination
4465 toEnd - numElements, // source
4466 toEnd, // end source
4467 allocator,
4469
4471 toEnd + numElements,
4472 allocator);
4473
4474 //..
4475 // Transformation: ABCDEFG[EFG] => ABCABCD[EFG].
4476 //..
4477
4478 TARGET_TYPE *src = toEnd - numElements;
4479 TARGET_TYPE *dest = toEnd;
4480 while (toBegin != src) {
4482 }
4483
4484 //..
4485 // Transformation: ABCABCD[EFG] => tuvABCD[EFG].
4486 //..
4487
4488 for (; toBegin != dest; ++toBegin, ++fromBegin) {
4489 *toBegin = *fromBegin;
4490 }
4491
4492 guard.release();
4493 }
4494 else {
4495 // Tail is not longer than input (numElements).
4496
4497 difference_type remElements = numElements - tailLen;
4498
4499 //..
4500 // Transformation: ABC_______[] => ABC____[ABC]
4501 //..
4502
4503 moveIfNoexcept(toBegin + numElements, // destination
4504 toBegin, // source
4505 toEnd, // end source
4506 allocator,
4508
4509 AutoArrayDestructor<TARGET_TYPE, ALLOCATOR> guard(toEnd + remElements,
4510 toEnd + numElements,
4511 allocator);
4512
4513 //..
4514 // Transformation: ABC____[ABC] => tuv____[ABC].
4515 //..
4516
4517 for (; toBegin != toEnd; ++fromBegin, ++toBegin) {
4518 *toBegin = *fromBegin;
4519 }
4520
4521 //..
4522 // Transformation: tuv____[ABC] => tuvwxyzABC[].
4523 //..
4524 copyConstruct(toBegin,
4525 fromBegin,
4526 fromEnd,
4527 allocator,
4529
4530 guard.release();
4531 }
4532}
4533
4534template <class FWD_ITER, class ALLOCATOR>
4536 void **toBegin,
4537 void **toEnd,
4538 FWD_ITER fromBegin,
4539 FWD_ITER,
4540 size_type numElements,
4541 ALLOCATOR,
4543{
4544 // This very specific overload is required for the case that 'FWD_ITER' is
4545 // an iterator that is not a pointer, iterating over a sequence of function
4546 // pointers. The implementation relies on the conditionally-supported
4547 // behavior that any function pointer can be @ref reinterpret_cast to
4548 // 'void *'.
4549
4550 // 'TARGET_TYPE' is bit-wise moveable.
4553
4554 if (0 == numElements) {
4555 return; // RETURN
4556 }
4557
4558 // The following assertions make sense only if 'FWD_ITER' is a pointer to a
4559 // possibly cv-qualified 'TARGET_TYPE', and are tested in that overload
4560 // (see above).
4561 //..
4562 // BSLS_ASSERT(fromBegin + numElements == fromEnd);
4563 // BSLS_ASSERT(fromEnd <= toBegin || toEnd + numElements <= fromBegin);
4564 //..
4565
4566 // Key to the transformation diagrams:
4567 //..
4568 // A...G original contents of '[toBegin, toEnd)' ("tail")
4569 // t...z contents of '[fromBegin, fromEnd)' ("input")
4570 // _____ uninitialized array element
4571 // [...] part of array guarded by exception guard
4572 // |.(.,.) part of array guarded by move guard
4573 // (middle indicated by ',' and dest by '|')
4574 //..
4575
4576 const size_type tailLen = toEnd - toBegin;
4577
4578 //..
4579 // Transformation: ABCDE____ => ____ABCDE (might overlap).
4580 //..
4581
4582 void **destBegin = toBegin + numElements;
4583
4584 if (BSLS_PERFORMANCEHINT_PREDICT_LIKELY(tailLen != 0)) {
4585 std::memmove(destBegin, toBegin, tailLen * sizeof(void **));
4586 }
4587
4588 for (size_type i = 0; i < numElements; ++i) {
4589 *toBegin = reinterpret_cast<void *>(*fromBegin);
4590
4591 ++fromBegin;
4592 ++toBegin;
4593 }
4594}
4595
4596 // *** 'moveInsert' overloads: ***
4597
4598template <class TARGET_TYPE, class ALLOCATOR>
4599inline
4601 TARGET_TYPE *toBegin,
4602 TARGET_TYPE *toEnd,
4603 TARGET_TYPE **lastPtr,
4604 TARGET_TYPE *first,
4605 TARGET_TYPE *last,
4606 size_type numElements,
4607 ALLOCATOR allocator,
4609{
4612 BSLS_ASSERT_SAFE(first || 0 == numElements);
4614 BSLS_ASSERT_SAFE(lastPtr);
4615
4616 // Functionally indistinguishable from this:
4617
4618 *lastPtr = last;
4619 insert(toBegin, toEnd, first, last, numElements, allocator,
4621 *lastPtr = first;
4622}
4623
4624template <class TARGET_TYPE, class ALLOCATOR>
4625inline
4627 TARGET_TYPE *toBegin,
4628 TARGET_TYPE *toEnd,
4629 TARGET_TYPE **lastPtr,
4630 TARGET_TYPE *first,
4631 TARGET_TYPE *last,
4632 size_type numElements,
4633 ALLOCATOR allocator,
4635{
4638 BSLS_ASSERT_SAFE(first || 0 == numElements);
4640 BSLS_ASSERT_SAFE(lastPtr);
4641
4642 // There isn't any advantage at destroying [first,last) one by one as we're
4643 // moving it, except perhaps for slightly better memory usage.
4644
4645 *lastPtr = last;
4646 insert(toBegin, toEnd, first, last, numElements, allocator,
4648 ArrayDestructionPrimitives::destroy(first, last, allocator);
4649 *lastPtr = first;
4650}
4651
4652 // *** 'rotate' overloads: ***
4653
4654template <class TARGET_TYPE>
4655inline
4657 TARGET_TYPE *begin,
4658 TARGET_TYPE *middle,
4659 TARGET_TYPE *end,
4661{
4664
4665 bitwiseRotate(reinterpret_cast<char *>(begin),
4666 reinterpret_cast<char *>(middle),
4667 reinterpret_cast<char *>(end));
4668}
4669
4670template <class TARGET_TYPE>
4672 TARGET_TYPE *begin,
4673 TARGET_TYPE *middle,
4674 TARGET_TYPE *end,
4676{
4679
4680 if (begin == middle || middle == end) {
4681 // This test changes into O(1) what would otherwise be O(N): Do not
4682 // remove!
4683
4684 return; // RETURN
4685 }
4686
4687 // This case is simple enough, it should be taken care of on its own.
4688
4689 const std::size_t numElements = middle - begin;
4690 const std::size_t remElements = end - middle;
4691
4692 if (numElements == remElements) {
4693 for (; middle != end; ++begin, ++middle) {
4694 TARGET_TYPE tmp(*middle);
4695 *middle = *begin;
4696 *begin = tmp;
4697 }
4698 return; // RETURN
4699 }
4700
4701 // This algorithm proceeds by decomposing the rotation into cycles, which
4702 // can then be rotated using a single element buffer. First we compute the
4703 // 'gcd(end - begin, numElements)' which is the number of cycles in the
4704 // rotation.
4705
4706 std::size_t numCycles = end - begin;
4707 std::size_t remainder = numElements;
4708 while (remainder != 0) {
4709 std::size_t t = numCycles % remainder;
4710 numCycles = remainder;
4711 remainder = t;
4712 }
4713
4714 // Key to the transformation diagrams:
4715 //..
4716 // A...D Contents of the current cycle
4717 // W...Z Contents of another cycle
4718 // _ Elements not in the current cycle
4719 //..
4720
4721 for (std::size_t i = 0; i < numCycles; ++i) {
4722 // Let the current cycle be initially 'A__B__C__D__', (note that its
4723 // stride is 'length / numCycles') and let (*) denote the current
4724 // position of 'ptr'.
4725
4726 TARGET_TYPE *ptr = begin; // seed for current cycle: A(*)__B__C__D__
4727 TARGET_TYPE tmp = *ptr; // value held at the seed: tmp == A
4728
4729 if (numElements < remElements) {
4730 // Rotate the cycle forward by numElements positions (or backward
4731 // by -(length-numElements)=-remElements positions if crossing the
4732 // boundary forward). The transformation is:
4733 //..
4734 // A(*)__B__C__D__ => B__B(*)__C__D__
4735 // => B__C__C(*)__D__
4736 // => B__C__D__D(*)__
4737 //..
4738 // The length of the cycle is always 'length / numCycles', but it
4739 // crosses the range boundaries 'numElements / numCycles' times,
4740 // each triggering an extra assignment in the 'if' clause below, so
4741 // the loop must only be executed:
4742 //..
4743 // (length - numElements) / numCycles = remElements / numCycles
4744 //..
4745 // times.
4746
4747 std::size_t cycleSize = remElements / numCycles;
4748
4749 for (std::size_t j = 0; j < cycleSize; ++j) {
4750 if (ptr > begin + remElements) {
4751 // Wrap around the range boundaries. (Note that
4752 // '-remElements == numElements - (end - begin)'.)
4753
4754 *ptr = *(ptr - remElements);
4755 ptr -= remElements;
4756 }
4757
4758 *ptr = *(ptr + numElements);
4759 ptr += numElements;
4760 }
4761 }
4762 else {
4763 // Rotate the cycle backward by '-remElements' positions (or
4764 // forward by 'numElements' positions if crossing the boundary
4765 // backward). The transformation is:
4766 //..
4767 // A(*)__B__C__D__ => D__B__C__D(*)__
4768 // => D__B__C(*)__C__
4769 // => D__B(*)__B__C__
4770 //..
4771 // The length of the cycle is always 'length/numCycles', but going
4772 // backward (which adds an initial extra crossing) crosses the
4773 // range boundaries 'remElements/numCycles+1' times each of which
4774 // trigger an extra assignment in the 'if' clause below, so the
4775 // loop must only be executed:
4776 //..
4777 // (length - remElements) / numCycles - 1 =
4778 // numElements / numCycles - 1
4779 //..
4780 // times.
4781
4782 std::size_t cycleSize = numElements / numCycles - 1;
4783
4784 for (std::size_t j = 0; j < cycleSize; ++j) {
4785 if (ptr < end - numElements) {
4786 *ptr = *(ptr + numElements);
4787 ptr += numElements;
4788 }
4789
4790 *ptr = *(ptr - remElements);
4791 ptr -= remElements;
4792 }
4793 }
4794
4795 *ptr = tmp; // Close the cycle, e.g.:
4796 //..
4797 // (first case): B__C__D__D(*)__ => B__C__D__A__
4798 // (second case): D__D(*)__B__C__ => D__A__B__C__
4799 //..
4800 ++begin; // and move on to the next cycle:
4801 //..
4802 // => _W__X__Y__Z_
4803 //..
4804 }
4805}
4806
4807 // *** 'shiftAndInsert' overloads: ***
4808
4809template <class ALLOCATOR>
4810inline
4816 ALLOCATOR allocator,
4818{
4819 BSLS_ASSERT_SAFE(begin != end); // the range is non-empty
4820
4821 typedef typename bsl::allocator_traits<ALLOCATOR>::value_type ValueType;
4822
4823 // ALIASING: If 'value' is a reference into the array '[begin, end)',
4824 // then moving the array first might introduce a change in 'value'.
4825 // Fortunately we can easily predict its new position after the shift.
4826
4827 ValueType *valuePtr =
4829 if (begin <= valuePtr && valuePtr < end) {
4830 valuePtr += 1; // new address after the shift
4831 }
4832
4833#if defined(BSLS_PLATFORM_PRAGMA_GCC_DIAGNOSTIC_GCC)
4834// clang does not support this pragma
4835#pragma GCC diagnostic push
4836#pragma GCC diagnostic ignored "-Wclass-memaccess"
4837#endif
4838
4839 // shift
4840 std::memmove(begin + 1, begin, (end - begin) * sizeof(ValueType));
4841
4842 // insert
4844 allocator,
4845 begin,
4847
4848#if defined(BSLS_PLATFORM_PRAGMA_GCC_DIAGNOSTIC_GCC)
4849#pragma GCC diagnostic pop
4850#endif
4851}
4852
4853template <class ALLOCATOR>
4854inline
4860 ALLOCATOR allocator,
4862{
4863 BSLS_ASSERT_SAFE(begin != end); // the range is non-empty
4864
4865 typedef typename bsl::allocator_traits<ALLOCATOR>::value_type ValueType;
4866
4867 // ALIASING: If 'value' is a reference into the array '[begin, end)',
4868 // then moving the array first might introduce a change in 'value'.
4869 // Fortunately we can easily predict its new position after the shift.
4870
4871 ValueType *valuePtr =
4873 if (begin <= valuePtr && valuePtr < end) {
4874 valuePtr += 1; // new address after the shift
4875 }
4876
4877 // shift
4878 size_t bytesNum = (end - begin) * sizeof(ValueType);
4879
4880
4881#if defined(BSLS_PLATFORM_PRAGMA_GCC_DIAGNOSTIC_GCC)
4882// clang does not support this pragma
4883#pragma GCC diagnostic push
4884#pragma GCC diagnostic ignored "-Wclass-memaccess"
4885#endif
4886
4887 std::memmove(begin + 1, begin, bytesNum);
4888
4889
4890 /// Moves the elements back if `construct` throws.
4891 ///
4892 /// See @ref bslalg_arrayprimitives
4893 class ElementsProctor {
4894
4895 // DATA
4896 ValueType *d_begin;
4897 size_t d_bytesNum;
4898 public:
4899 // CREATORS
4900 ElementsProctor(ValueType *p, size_t n) : d_begin(p), d_bytesNum(n) {}
4901 ~ElementsProctor()
4902 {
4903 if(d_bytesNum) std::memmove(d_begin, d_begin + 1, d_bytesNum);
4904 }
4905 // MANIPULATORS
4906 void release() { d_bytesNum = 0; }
4907 } proctor(begin, bytesNum);
4908
4909
4910 // insert
4912 allocator,
4913 begin,
4915 proctor.release();
4916#if defined(BSLS_PLATFORM_PRAGMA_GCC_DIAGNOSTIC_GCC)
4917#pragma GCC diagnostic pop
4918#endif
4919}
4920
4921template <class ALLOCATOR>
4922inline
4928 ALLOCATOR allocator,
4930{
4931 BSLS_ASSERT_SAFE(begin != end); // the range is non-empty
4932
4933 typedef typename bsl::allocator_traits<ALLOCATOR>::value_type ValueType;
4934
4935 // ALIASING: If 'value' is a reference into the array '[begin, end)',
4936 // then moving the array first might introduce a change in 'value'.
4937 // Fortunately we can easily predict its new position after the shift.
4938
4939 ValueType *valuePtr =
4941 if (begin <= valuePtr && valuePtr < end) {
4942 valuePtr += 1; // new address after the shift
4943 }
4944
4945 // Key to the transformation diagrams:
4946 //..
4947 // A...G original contents of '[toBegin, toEnd)' ("tail")
4948 // a...g moved-from or copied values
4949 // v moved 'value' ("input")
4950 // _____ uninitialized array elements
4951 // [...] part of array protected by an exception guard object
4952 //..
4953
4954 //..
4955 // Transformation: ABCDEFG_[] => ABCDEFg[G].
4956 //..
4957
4959 allocator,
4960 end,
4962
4964 end, end + 1, allocator);
4965
4966 //..
4967 // Transformation: ABCDEFg[G] => aABCDEF[G].
4968 //..
4969
4970 ValueType *dst = end;
4971 ValueType *src = end - 1;
4972 while (src != begin) {
4974 }
4975
4976 //..
4977 // Transformation: aABCDEFG[G] => vABCDEF[G].
4978 //..
4979
4980 *begin = bslmf::MovableRefUtil::move_if_noexcept(*valuePtr);
4981
4982 guard.release();
4983}
4984
4985} // close package namespace
4986
4987#ifndef BDE_OPENSOURCE_PUBLICATION // BACKWARD_COMPATIBILITY
4988// ============================================================================
4989// BACKWARD COMPATIBILITY
4990// ============================================================================
4991
4992/// This alias is defined for backward compatibility.
4994#endif // BDE_OPENSOURCE_PUBLICATION -- BACKWARD_COMPATIBILITY
4995
4996
4997
4998#if defined(BSLALG_ARRAYPRIMITIVES_CANNOT_REMOVE_POINTER_FROM_FUNCTION_POINTER)
4999# undef BSLALG_ARRAYPRIMITIVES_CANNOT_REMOVE_POINTER_FROM_FUNCTION_POINTER
5000#endif
5001
5002#endif // End C++11 code
5003
5004#endif
5005
5006// ----------------------------------------------------------------------------
5007// Copyright 2013 Bloomberg Finance L.P.
5008//
5009// Licensed under the Apache License, Version 2.0 (the "License");
5010// you may not use this file except in compliance with the License.
5011// You may obtain a copy of the License at
5012//
5013// http://www.apache.org/licenses/LICENSE-2.0
5014//
5015// Unless required by applicable law or agreed to in writing, software
5016// distributed under the License is distributed on an "AS IS" BASIS,
5017// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
5018// See the License for the specific language governing permissions and
5019// limitations under the License.
5020// ----------------------------- END-OF-FILE ----------------------------------
5021
5022/** @} */
5023/** @} */
5024/** @} */
Definition bslalg_autoarraydestructor.h:232
OBJECT_TYPE * moveEnd(difference_type offset=1)
Definition bslalg_autoarraydestructor.h:329
OBJECT_TYPE * moveBegin(difference_type offset=-1)
Definition bslalg_autoarraydestructor.h:316
void release()
Definition bslalg_autoarraydestructor.h:340
Definition bslalg_autoarraymovedestructor.h:418
OBJECT_TYPE * middle() const
Return the address at the middle of the guarded range.
Definition bslalg_autoarraymovedestructor.h:579
OBJECT_TYPE * destination() const
Definition bslalg_autoarraymovedestructor.h:565
void advance()
Definition bslalg_autoarraymovedestructor.h:544
OBJECT_TYPE * end() const
Return the address at the end of the guarded range.
Definition bslalg_autoarraymovedestructor.h:572
Definition bslma_allocator.h:457
Definition bslma_destructorproctor.h:259
Definition bslmf_movableref.h:751
bslalg::ArrayPrimitives bslalg_ArrayPrimitives
This alias is defined for backward compatibility.
Definition bslalg_arrayprimitives.h:4993
#define BSLMF_ASSERT(expr)
Definition bslmf_assert.h:229
#define BSLS_ASSERT_SAFE(X)
Definition bsls_assert.h:1762
#define BSLS_COMPILERFEATURES_FORWARD(T, V)
Definition bsls_compilerfeatures.h:2018
#define BSLS_IDENT(str)
Definition bsls_ident.h:195
#define BSLS_PERFORMANCEHINT_PREDICT_LIKELY(expr)
Definition bsls_performancehint.h:451
#define BSLS_UTIL_ADDRESSOF(OBJ)
Definition bsls_util.h:289
Definition bdlc_flathashmap.h:1805
Definition balxml_encoderoptions.h:68
static void construct(ALLOCATOR_TYPE &basicAllocator, ELEMENT_TYPE *elementAddr, Args &&... arguments)
Definition bslma_allocatortraits.h:1472
BloombergLP::bslma::AllocatorTraits_PointerType< ALLOCATOR_TYPE >::type pointer
Definition bslma_allocatortraits.h:1149
ALLOCATOR_TYPE::value_type value_type
Definition bslma_allocatortraits.h:1145
Definition bslmf_integralconstant.h:244
Definition bslmf_isenum.h:270
Definition bslmf_isfundamental.h:329
Definition bslmf_ismemberpointer.h:143
Definition bslmf_ispointer.h:138
Definition bslmf_issame.h:146
Definition bslmf_istriviallydefaultconstructible.h:293
Definition bslmf_isvoid.h:138
Definition bslmf_removecv.h:118
Definition bslmf_removepointer.h:255
BloombergLP::bslmf::RemovePointer_Imp< t_TYPE >::Type type
Definition bslmf_removepointer.h:267
static void destroy(TARGET_TYPE *begin, TARGET_TYPE *end, ALLOCATOR allocator, bsl::true_type)
Definition bslalg_arraydestructionprimitives.h:232
Definition bslalg_arrayprimitives.h:1896
Definition bslalg_arrayprimitives.h:1215
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:3698
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:3520
static bool isInvalidRange(FORWARD_ITERATOR begin, FORWARD_ITERATOR end)
Definition bslalg_arrayprimitives.h:3027
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)
@ e_BITWISE_MOVEABLE_TRAITS
Definition bslalg_arrayprimitives.h:1260
@ e_HAS_TRIVIAL_DEFAULT_CTOR_TRAITS
Definition bslalg_arrayprimitives.h:1258
@ e_NIL_TRAITS
Definition bslalg_arrayprimitives.h:1261
@ e_BITWISE_COPYABLE_TRAITS
Definition bslalg_arrayprimitives.h:1259
@ e_IS_FUNDAMENTAL_OR_POINTER
Definition bslalg_arrayprimitives.h:1257
@ e_IS_ITERATOR_TO_FUNCTION_POINTER
Definition bslalg_arrayprimitives.h:1255
@ e_IS_POINTER_TO_POINTER
Definition bslalg_arrayprimitives.h:1256
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:4811
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:3064
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:4600
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:3565
ArrayPrimitives::difference_type difference_type
Definition bslalg_arrayprimitives.h:1247
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 >())
static void copyConstruct(TARGET_TYPE *toBegin, FWD_ITER fromBegin, FWD_ITER fromEnd, ALLOCATOR allocator, bsl::integral_constant< int, e_IS_POINTER_TO_POINTER >)
Definition bslalg_arrayprimitives.h:3407
ArrayPrimitives::size_type size_type
Definition bslalg_arrayprimitives.h:1246
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:3654
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 >())
@ k_INPLACE_BUFFER_SIZE
Definition bslalg_arrayprimitives.h:1268
static void copyConstruct(TARGET_TYPE *toBegin, FWD_ITER fromBegin, FWD_ITER fromEnd, ALLOCATOR allocator, bsl::integral_constant< int, e_IS_ITERATOR_TO_FUNCTION_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:3883
static void rotate(TARGET_TYPE *begin, TARGET_TYPE *middle, TARGET_TYPE *end, bsl::integral_constant< int, e_BITWISE_MOVEABLE_TRAITS >)
Definition bslalg_arrayprimitives.h:4656
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:3952
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:3595
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:418
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:2488
static void copyConstruct(typename bsl::allocator_traits< ALLOCATOR >::pointer toBegin, FWD_ITER fromBegin, FWD_ITER fromEnd, ALLOCATOR allocator)
Definition bslalg_arrayprimitives.h:1959
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:2146
ArrayPrimitives_Imp Imp
Definition bslalg_arrayprimitives.h:422
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:2680
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:2107
static void defaultConstruct(typename bsl::allocator_traits< ALLOCATOR >::pointer begin, size_type numElements, ALLOCATOR allocator)
Definition bslalg_arrayprimitives.h:2064
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:2942
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:2591
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:2904
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:2217
std::ptrdiff_t difference_type
Definition bslalg_arrayprimitives.h:424
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:2637
static void uninitializedFillN(typename bsl::allocator_traits< ALLOCATOR >::pointer begin, size_type numElements, const typename bsl::allocator_traits< ALLOCATOR >::value_type &value, ALLOCATOR allocator)
Definition bslalg_arrayprimitives.h:1905
std::size_t size_type
Definition bslalg_arrayprimitives.h:423
static void rotate(TARGET_TYPE *first, TARGET_TYPE *middle, TARGET_TYPE *last)
Definition bslalg_arrayprimitives.h:2989
static void construct(TARGET_TYPE *address, const ALLOCATOR &allocator)
Definition bslma_constructionutil.h:1243
static Allocator * allocator(Allocator *basicAllocator=0)
Definition bslma_default.h:897
Definition bslmf_isbitwisecopyable.h:298
Definition bslmf_isbitwisemoveable.h:718
Definition bslmf_functionpointertraits.h:153
static MovableRef< t_TYPE > move(t_TYPE &reference) BSLS_KEYWORD_NOEXCEPT
Definition bslmf_movableref.h:1060
static t_TYPE & access(t_TYPE &ref) BSLS_KEYWORD_NOEXCEPT
Definition bslmf_movableref.h:1032
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:915
@ BSLS_MAX_ALIGNMENT
Definition bsls_alignmentutil.h:275
unsigned long long Uint64
Definition bsls_types.h:137
long long Int64
Definition bsls_types.h:132
Definition bsls_objectbuffer.h:276
TYPE & object()
Definition bsls_objectbuffer.h:351