Outline
Purpose
Provide primitive algorithms that operate on arrays.
Classes
- See also
- bslalg_dequeprimitives, bslma_constructionutil
Description
This component provides utilities to initialize, move, and otherwise perform various primitive manipulations on arrays with a uniform interface, but selecting a different implementation according to the various traits possessed by the underlying type. Such primitives are exceptionally useful for implementing generic components such as containers.
Several algorithms are provided, with the following short synopsis describing the observable behavior and mentioning the relevant traits. See the full function-level contract for detailed description, including exception-safety guarantees. In the description below, ADP
stands for bslalg::ArrayDestructionPrimitives
. Note that some algorithms (e.g., insert
) are explained in terms of previous algorithms (e.g., destructiveMove
).
Algorithm Short description of observable behavior
---------------------------- ---------------------------------------------
defaultConstruct Construct each element in the target range
by value-initialization, or 'std::memset' if
type has a trivial default constructor.
Note that this function *does* *not* perform
default-initialization, the colloquial
terminology "default construct" is maintained
for backwards compatibility.
uninitializedFillN Copy construct from value for each element in
the target range, or 'std::memset' if value
is all 0s or 1s bits, and type is bit-wise
copyable
copyConstruct Copy construct from each element in the
original range to the corresponding element
in the target range, or 'std::memcpy' if
value is null and type is bit-wise copyable
destructiveMove Copy from each element in the original range
to the corresponding element in the target
and destroy objects in the original range, or
'std::memcpy' if type is bit-wise moveable
destructiveMoveAndInsert 'destructiveMove' from the original range to
target range, leaving a hole in the middle,
followed by 'defaultConstruct',
'uninitializedFillN' or 'copyConstruct' to
fill hole with the appropriate values
destructiveMoveAndMoveInsert 'destructiveMove' from the original range to
the target range, leaving a hole in the
middle, followed by 'destructiveMove'
from second range to fill hole
insert 'std::memmove' or 'copyConstruct' by some
positive offset to create a hole, followed by
'uninitializedFillN', 'copyConstruct', or
copy assignment to fill hole with the
appropriate values
emplace 'std::memmove' or 'copyConstruct' by some
positive offset to create a hole, followed by
in-place construction, 'copyConstruct', or
copy assignment to fill hole with the
appropriate values
moveInsert 'destructiveMove' by some positive offset to
create a hole, followed by 'destructiveMove'
to fill hole with the appropriate values
erase 'ADP::destroy' elements in target range until
specified position, followed by
'destructiveMove' by some negative offset
from the end of the range to fill hole with
the remaining values
rotate 'destructiveMove' to move elements into a
shifting hole along parallel cyclic
permutations, or 'std::memmove' for small
rotations if type is bit-wise moveable
The traits under consideration by this component are:
Trait English description
-------------------------------------------- -----------------------------
constructor trait", or
"TYPE has a trivial default
constructor"
copyable trait", or
"TYPE is bit-wise copyable"
moveable trait", or
"TYPE is bit-wise moveable"
Definition bslmf_istriviallydefaultconstructible.h:293
Definition bslmf_isbitwisecopyable.h:298
Definition bslmf_isbitwisemoveable.h:718
Aliasing
There are some aliasing concerns in this component, due to the presence of the reference const TARGET_TYPE& value
argument, which may belong to a range that will be modified during the course of the operation. All such aliasing concerns are taken care of properly. Other aliasing concerns due to the copying or a range [first, last)
are not taken care of, since their intended use is for range assignments and insertions in standard containers, for which the standard explicitly says that first
and last
shall not be iterators into the container.
Usage
In this section we show intended use of this component.
Example 1: Defining a Vector-Like Type
Suppose we want to define a STL-vector-like type. One requirement is that an object of this vector should forward its allocator to its contained elements when appropriate. Another requirement is that the vector should take advantage of the optimizations available for certain traits of the contained element type. For example, if the contained element type has the bslmf::IsBitwiseMoveable
trait, moving an element in a vector can be done using memcpy
instead of copy construction.
We can utilize the class methods provided by bslalg::ArrayPrimitives
to satisfy the above requirements. Unlike bslma::ConstructionUtil
, which operates on a single element, bslalg::ArrayPrimitives
operates on arrays, which will further help simplify our implementation.
First, we create an elided definition of the class template MyVector
:
template <class TYPE, class ALLOC>
class MyVector {
TYPE *d_array_p;
int d_capacity;
int d_size;
ALLOC d_allocator;
public:
MyVector,
BloombergLP::bslmf::IsBitwiseMoveable);
: d_array_p(0)
, d_capacity(0)
, d_size(0)
, d_allocator_p(
bslma::Default::allocator(basicAllocator))
{
}
MyVector(const MyVector& original,
void reserve(int minCapacity);
void insert(int dstIndex, int numElements, const TYPE& value);
const TYPE& operator[](int position) const
{
return d_array_p[position];
}
{
return d_size;
}
};
#define BSLMF_NESTED_TRAIT_DECLARATION(t_TYPE, t_TRAIT)
Definition bslmf_nestedtraitdeclaration.h:231
Definition bslma_allocator.h:457
bsl::size_t size(const TYPE &array)
Return the number of elements in the specified array.
Definition balxml_encoderoptions.h:68
Then, we implement the copy constructor of MyVector
:
template <class TYPE>
MyVector<TYPE>::MyVector(const MyVector<TYPE>& original,
: d_array_p(0)
, d_capacity(0)
, d_size(0)
, d_allocator_p(
bslma::Default::allocator(basicAllocator))
{
reserve(original.d_size);
Here, we call the bslalg::ArrayPrimitives::copyConstruct
class method to copy each element from original.d_array_p
to d_array_p
(When appropriate, this class method passes this vector's allocator to the copy constructor of TYPE
or uses bit-wise copy.):
d_array_p,
original.d_array_p,
original.d_array_p + original.d_size,
d_allocator_p);
d_size = original.d_size;
}
static void copyConstruct(typename bsl::allocator_traits< ALLOCATOR >::pointer toBegin, FWD_ITER fromBegin, FWD_ITER fromEnd, ALLOCATOR allocator)
Definition bslalg_arrayprimitives.h:1959
Now, we implement the reserve
method of MyVector
:
template <class TYPE>
void MyVector<TYPE>::reserve(int minCapacity)
{
if (d_capacity >= minCapacity) return;
TYPE *newArrayPtr = static_cast<TYPE*>(d_allocator_p->allocate(
BloombergLP::bslma::Allocator::size_type(minCapacity * sizeof(TYPE))));
if (d_array_p) {
Here, we call the bslalg::ArrayPrimitives::destructiveMove
class method to copy each original element from d_array_p
to newArrayPtr
and then destroy all the original elements (When appropriate, this class method passes this vector's allocator to the copy constructor of TYPE
or uses bit-wise copy.):
d_array_p,
d_array_p + d_size,
d_allocator_p);
d_allocator_p->deallocate(d_array_p);
}
d_array_p = newArrayPtr;
d_capacity = minCapacity;
}
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
Finally, we implement the insert
method of MyVector
:
template <class TYPE>
void
MyVector<TYPE>::insert(int dstIndex, int numElements, const TYPE& value)
{
int newSize = d_size + numElements;
if (newSize > d_capacity) {
int newCapacity = d_capacity == 0 ? 2 : d_capacity * 2;
reserve(newCapacity);
}
Here, we call the bslalg::ArrayPrimitives::insert
class method to first move each element after dstIndex
by numElements
and then copy construct numElements
of value
at dstIndex
. (When appropriate, this class method passes this vector's allocator to the copy constructor of TYPE
or uses bit-wise copy.):
d_array_p + d_size,
value,
numElements,
d_allocator_p);
d_size = newSize;
}
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
◆ bslalg_ArrayPrimitives