BDE 4.39.x Production Release
Loading...
Searching...
No Matches
bdlat_arrayfunctions.h
Go to the documentation of this file.
1/// @file bdlat_arrayfunctions.h
2///
3/// The content of this file has been pre-processed for Doxygen.
4///
5
6
7// bdlat_arrayfunctions.h -*-C++-*-
8#ifndef INCLUDED_BDLAT_ARRAYFUNCTIONS
9#define INCLUDED_BDLAT_ARRAYFUNCTIONS
10
11#include <bsls_ident.h>
12BSLS_IDENT("$Id: $")
13
14/// @defgroup bdlat_arrayfunctions bdlat_arrayfunctions
15/// @brief Provide a namespace defining "array" functions.
16/// @addtogroup bdl
17/// @{
18/// @addtogroup bdlat
19/// @{
20/// @addtogroup bdlat_arrayfunctions
21/// @{
22///
23/// <h1> Outline </h1>
24/// * <a href="#bdlat_arrayfunctions-purpose"> Purpose</a>
25/// * <a href="#bdlat_arrayfunctions-classes"> Classes </a>
26/// * <a href="#bdlat_arrayfunctions-description"> Description </a>
27/// * <a href="#bdlat_arrayfunctions-usage"> Usage </a>
28/// * <a href="#bdlat_arrayfunctions-example-1-defining-an-array-type"> Example 1: Defining an "Array" Type </a>
29/// * <a href="#bdlat_arrayfunctions-example-2-using-the-infrastructure-via-general-methods"> Example 2: Using the Infrastructure Via General Methods </a>
30/// * <a href="#bdlat_arrayfunctions-example-3-defining-utility-functions"> Example 3: Defining Utility Functions </a>
31/// * <a href="#bdlat_arrayfunctions-example-4-achieving-type-independence"> Example 4: Achieving Type Independence </a>
32///
33/// # Purpose {#bdlat_arrayfunctions-purpose}
34/// Provide a namespace defining "array" functions.
35///
36/// # Classes {#bdlat_arrayfunctions-classes}
37///
38/// - bdlat_ArrayFunctions: namespace for calling "array" functions
39///
40/// # Description {#bdlat_arrayfunctions-description}
41/// The `bdlat_ArrayFunctions` `namespace` provided in this
42/// component defines parameterized functions that expose "array" behavior for
43/// "array" types. See the `bdlat` package-level documentation for a brief
44/// description of "array" types.
45///
46/// The functions in this namespace allow users to:
47/// * obtain the number of elements in an array (`size`).
48/// * set the number of elements in an array (`resize`).
49/// * manipulate an element in an array using a parameterized manipulator
50/// (`manipulateElement`).
51/// * access an element in an array using a parameterized accessor
52/// (`accessElement`).
53///
54/// Also, if supported by the array type, reserve capacity for a number of
55/// elements in an array (`reserve`) and whether reserve capacity is supported
56/// (`supportsReserve`). If not supported, the default implementations return
57/// non-zero (failure) for `reserve` and `false` for `supportsReserve`.
58///
59/// A type becomes part of the `bdlat` "array" framework by creating, in the
60/// namespace where the type is defined, overloads of the following two (free)
61/// functions and two (free) function templates. Note that the placeholder
62/// `YOUR_TYPE` is not a template argument and should be replaced with the name
63/// of the type being plugged into the framework.
64/// @code
65/// // MANIPULATORS
66///
67/// /// Invoke the specified `manipulator` on the address of the element at
68/// /// the specified `index` of the specified `array`. The supplied
69/// /// `manipulator` must be a callable type that can be called as if it had
70/// /// the following signature:
71/// /// ```
72/// /// int manipulator(ELEMENT_TYPE *element);
73/// /// ```
74/// /// Return the value from the invocation of `manipulator`. The behavior is
75/// /// undefined unless `0 <= index` and `index < bdlat_arraySize(*array)`.
76/// template <class MANIPULATOR>
77/// int bdlat_arrayManipulateElement(YOUR_TYPE *array,
78/// MANIPULATOR& manipulator,
79/// int index);
80///
81/// /// Set the size of the specified modifiable `array` to the specified
82/// /// `newSize`. If `newSize > bdlat_arraySize(*array)`, then
83/// /// `newSize - bdlat_arraySize(*array)` elements with default values
84/// /// (i.e., `ElementType()`) are appended to `array`. If
85/// /// `newSize < bdlat_arraySize(*array)`, then the
86/// /// `bdlat_arraySize(*array) - newSize` elements at the end of `array`
87/// /// are destroyed. The behavior is undefined unless `0 <= newSize`.
88/// void bdlat_arrayResize(YOUR_TYPE *array, int newSize);
89///
90/// // ACCESSORS
91///
92/// /// Invoke the specified `accessor` on a `const`-reference to the element at
93/// /// the specified `index` of the specified `array`. The supplied `accessor`
94/// /// must be a callable type that can be called as if it had the following
95/// /// signature:
96/// /// ```
97/// /// int accessor(const ELEMENT_TYPE& element);
98/// /// ```
99/// /// Return the value from the invocation of `accessor`. The behavior is
100/// /// undefined unless `0 <= index` and `index < bdlat_arraySize(array)`.
101/// template <class ACCESSOR>
102/// int bdlat_arrayAccessElement(const YOUR_TYPE& array,
103/// ACCESSOR& accessor,
104/// int index);
105///
106/// /// Return the number of elements in the specified `array`.
107/// bsl::size_t bdlat_arraySize(const YOUR_TYPE& array);
108/// @endcode
109///
110/// The "array" type must also define two meta-functions in the
111/// `bdlat_ArrayFunctions` namespace:
112///
113/// * the meta-function `IsArray` contains a compile-time constant `value` that
114/// is non-zero if the parameterized `TYPE` exposes "array" behavior.
115/// * the `ElementType` meta-function contains a `typedef` `Type` that
116/// specifies the type of the element stored in the parameterized "array"
117/// type.
118///
119/// The two optional methods for reserving capacity:
120/// @code
121/// /// If successful, make the capacity of the specified modifiable `array` at
122/// /// least the specified `numElements` and return zero. If unsuccessful or
123/// /// unsupported, return a non-zero value. This method has no effect, and
124/// /// returns zero, if the current capacity meets or exceeds the required
125/// /// capacity. The behavior is undefined unless `0 <= numElements`.
126/// int bdlat_arrayReserve(YOUR_TYPE *array, int numElements);
127///
128/// /// Return `true` if `bdlat_arrayReserve` will attempt to reserve capacity
129/// /// in the specified `array`, and `false` otherwise.
130/// bool bdlat_arraySupportsReserve(const YOUR_TYPE& array);
131/// @endcode
132///
133/// Note that `bsl::vector<TYPE>` is already part of the `bdlat`
134/// infrastructure for "array" types because this component also provides
135/// overloads of the required functions and meta-function specializations.
136///
137/// ## Usage {#bdlat_arrayfunctions-usage}
138///
139///
140/// This section illustrates intended use of this component.
141///
142/// ### Example 1: Defining an "Array" Type {#bdlat_arrayfunctions-example-1-defining-an-array-type}
143///
144///
145/// Suppose you had a type, `mine::MyIntArray`, that provides the essential
146/// features of an "array" type.
147/// @code
148/// namespace BloombergLP {
149/// namespace mine {
150///
151/// class MyIntArray {
152///
153/// int *d_data_p;
154/// bsl::size_t d_size;
155///
156/// public:
157/// // CREATORS
158/// MyIntArray()
159/// : d_data_p(0)
160/// , d_size(0)
161/// {
162/// }
163///
164/// ~MyIntArray()
165/// {
166/// bsl::free(d_data_p);
167/// }
168///
169/// // MANIPULATORS
170/// void resize(bsl::size_t newSize);
171///
172/// int& value(bsl::size_t index)
173/// {
174/// assert(index < d_size);
175///
176/// return d_data_p[index];
177/// }
178///
179/// // ACCESSORS
180/// const int& value(bsl::size_t index) const
181/// {
182/// assert(index < d_size);
183///
184/// return d_data_p[index];
185/// }
186///
187/// bsl::size_t size() const
188/// {
189/// return d_size;
190/// }
191/// };
192///
193/// void MyIntArray::resize(bsl::size_t newSize)
194/// {
195/// // Always match buffer to size exactly.
196///
197/// if (d_size == newSize) {
198/// return; // RETURN
199/// }
200///
201/// int *newData = static_cast<int *>(bsl::malloc(sizeof(int)
202/// * newSize));
203/// if (d_size < newSize) {
204/// if (d_data_p) {
205/// bsl::memcpy(newData, d_data_p, d_size * sizeof(int));
206/// }
207/// std::memset(newData + d_size,
208/// 0,
209/// (newSize - d_size) * sizeof(int));
210///
211/// } else {
212/// bsl::memcpy(newData, d_data_p, newSize);
213/// }
214///
215/// bsl::free(d_data_p);
216/// d_data_p = newData;
217/// d_size = newSize;
218/// }
219///
220/// } // close namespace mine
221/// } // close enterprise namespace
222/// @endcode
223///
224/// We can now make `mine::MyIntArray` expose "array" behavior by implementing
225/// the necessary `bdlat_ArrayFunctions` for `MyIntArray` inside the `mine`
226/// namespace and defining the required meta-functions withing the
227/// `bdlat_ArrayFunctions` namespace.
228///
229/// First, we should forward declare all the functions that we will implement
230/// inside the `mine` namespace:
231/// @code
232/// namespace BloombergLP {
233/// namespace mine {
234///
235/// // MANIPULATORS
236///
237/// /// Invoke the specified `manipulator` on the address of the element at
238/// /// the specified `index` of the specified `array`. Return the value
239/// /// from the invocation of `manipulator`. The behavior is undefined
240/// /// unless `0 <= index` and `index < bdlat_arraySize(*array)`.
241/// template <class MANIPULATOR>
242/// int bdlat_arrayManipulateElement(MyIntArray *array,
243/// MANIPULATOR& manipulator,
244/// int index);
245///
246/// /// Set the size of the specified modifiable `array` to the specified
247/// /// `newSize`. If `newSize > bdlat_arraySize(*array)`, then
248/// /// `newSize - bdlat_arraySize(*array)` elements with default values
249/// /// (i.e., `ElementType()`) are appended to `array`. If
250/// /// `newSize < bdlat_arraySize(*array)`, then the
251/// /// `bdlat_arraySize(*array) - newSize` elements at the end of `array`
252/// /// are destroyed. The behavior is undefined unless `0 <= newSize`.
253/// void bdlat_arrayResize(MyIntArray *array, int newSize);
254///
255/// // ACCESSORS
256///
257/// /// Invoke the specified `accessor` on a `const`-reference to the
258/// /// element at the specified `index` of the specified `array`. Return
259/// /// the value from the invocation of `accessor`. The behavior is
260/// /// undefined unless `0 <= index` and `index < bdlat_arraySize(array)`.
261/// template <class ACCESSOR>
262/// int bdlat_arrayAccessElement(const MyIntArray& array,
263/// ACCESSOR& accessor,
264/// int index);
265///
266/// /// Return the number of elements in the specified `array`.
267/// bsl::size_t bdlat_arraySize(const MyIntArray& array);
268///
269/// } // close namespace mine
270/// } // close enterprise namespace
271/// @endcode
272///
273/// Then, we will implement these functions. Recall that the two (non-template)
274/// functions should be defined in some `.cpp` file, unless you choose to make
275/// them `inline` functions.
276/// @code
277/// namespace BloombergLP {
278/// namespace mine {
279///
280/// // MANIPULATORS
281/// template <class MANIPULATOR>
282/// int bdlat_arrayManipulateElement(MyIntArray *array,
283/// MANIPULATOR& manipulator,
284/// int index)
285/// {
286/// assert(array);
287/// assert(0 <= index);
288/// assert(static_cast<bsl::size_t>(index) < array->size());
289///
290/// return manipulator(&array->value(index));
291/// }
292///
293/// void bdlat_arrayResize(MyIntArray *array, int newSize)
294/// {
295/// assert(array);
296/// assert(0 <= newSize);
297///
298/// array->resize(newSize);
299/// }
300///
301/// // ACCESSORS
302/// template <class ACCESSOR>
303/// int bdlat_arrayAccessElement(const MyIntArray& array,
304/// ACCESSOR& accessor,
305/// int index)
306/// {
307/// assert(0 <= index);
308/// assert(static_cast<bsl::size_t>(index) < array.size());
309///
310/// return accessor(array.value(index));
311/// }
312///
313/// bsl::size_t bdlat_arraySize(const MyIntArray& array)
314/// {
315/// return array.size();
316/// }
317///
318/// } // close namespace mine
319/// } // close enterprise namespace
320/// @endcode
321/// Finally, we specialize the `IsArray` and `ElementType` meta-functions
322/// in the `bdlat_ArrayFunctions` namespace for the
323/// `mine::MyIntArray` type:
324/// @code
325/// namespace BloombergLP {
326/// namespace bdlat_ArrayFunctions {
327///
328/// // TRAITS
329/// template <>
330/// struct IsArray<mine::MyIntArray> : bsl::true_type {
331/// };
332///
333/// template <>
334/// struct ElementType<mine::MyIntArray> {
335/// typedef int Type;
336/// };
337///
338/// } // close namespace bdlat_ArrayFunctions
339/// } // close enterprise namespace
340/// @endcode
341///
342/// This completes the `bdlat` infrastructure for `mine::MyIntArray` and
343/// allows the generic software to recognize the type as an array abstraction.
344///
345/// ### Example 2: Using the Infrastructure Via General Methods {#bdlat_arrayfunctions-example-2-using-the-infrastructure-via-general-methods}
346///
347///
348/// The `bdlat` "array" framework provides a set of fundamental operations
349/// common to any "array" type. We can build upon these operations to make our
350/// own utilities, or use them on our own types that are plugged into the
351/// framework, like `mine::MyIntArray`, which we created in {Example 1}. For
352/// example, we can use the (fundamental) operations in the
353/// `bdlat_ArrayFunctions` namespace to operate on `mine::MyIntArray`, even
354/// though they have no knowledge of that type in particular:
355/// @code
356/// void usageMakeArray()
357/// {
358/// BSLMF_ASSERT(bdlat_ArrayFunctions::IsArray<mine::MyIntArray>::value);
359///
360/// mine::MyIntArray array;
361/// assert(0 == bdlat_ArrayFunctions::size(array));
362///
363/// bdlat_ArrayFunctions::resize(&array, 8);
364/// assert(8 == bdlat_ArrayFunctions::size(array));
365///
366/// bdlat_ArrayFunctions::resize(&array, 4);
367/// assert(4 == bdlat_ArrayFunctions::size(array));
368/// }
369/// @endcode
370/// To perform operations on the elements of an array requires use of the
371/// functions that employ accessor and manipulator functors. For example:
372/// @code
373/// template <class ELEMENT_TYPE>
374/// class GetElementAccessor {
375///
376/// // DATA
377/// ELEMENT_TYPE *d_element_p;
378///
379/// public:
380/// // CREATORS
381/// explicit GetElementAccessor(ELEMENT_TYPE *value)
382/// : d_element_p(value)
383/// {
384/// }
385///
386/// // MANIPULATORS
387/// int operator()(const ELEMENT_TYPE& elementValue)
388/// {
389/// *d_element_p = elementValue;
390/// return 0;
391/// }
392/// };
393///
394/// template<class ELEMENT_TYPE>
395/// class SetElementManipulator {
396///
397/// // DATA
398/// ELEMENT_TYPE d_value;
399///
400/// public:
401/// // CREATORS
402/// SetElementManipulator(const ELEMENT_TYPE& value)
403/// : d_value(value)
404/// {
405/// }
406///
407/// // ACCESSOR
408/// int operator()(ELEMENT_TYPE *element) const
409/// {
410/// *element = d_value;
411/// return 0;
412/// }
413/// };
414/// @endcode
415/// Notice that these functors make few assumptions of `ELEMENT_TYPE`, merely
416/// that it is copy constructable and copy assignable.
417///
418/// With these definitions we can now use the generic functions to set and
419/// get values from an `mine::MyIntArray` object:
420/// @code
421/// void usageArrayElements()
422/// {
423/// mine::MyIntArray array;
424/// bdlat_ArrayFunctions::resize(&array, 4);
425///
426/// // Confirm initial array elements from resize.
427///
428/// int value;
429/// GetElementAccessor<int> accessor(&value);
430///
431/// for (int index = 0; index < 4; ++index) {
432/// int rc = bdlat_ArrayFunctions::accessElement(array,
433/// accessor,
434/// index);
435/// assert(0 == rc);
436/// assert(0 == value)
437/// }
438///
439/// // Set element `index * 10` as its value.
440///
441/// for (int index = 0; index < 4; ++index) {
442/// SetElementManipulator<int> manipulator(index * 10);
443///
444/// int rc = bdlat_ArrayFunctions::manipulateElement(&array,
445/// manipulator,
446/// index);
447/// assert(0 == rc);
448/// }
449///
450/// // Confirm new value of each element.
451///
452/// for (int index = 0; index < 4; ++index) {
453/// int rc = bdlat_ArrayFunctions::accessElement(array,
454/// accessor,
455/// index);
456/// assert(0 == rc);
457/// assert(index * 10 == value);
458/// }
459/// }
460/// @endcode
461///
462/// ### Example 3: Defining Utility Functions {#bdlat_arrayfunctions-example-3-defining-utility-functions}
463///
464///
465/// Creating functor objects for each operation can be tedious and error prone;
466/// consequently, those types are often executed via utility functions.
467///
468/// Suppose we want to create utilities for getting and setting the elements of
469/// an arbitrary "array" type. We might define a utility `struct`, `ArrayUtil`,
470/// a namespace for those functions:
471/// @code
472/// struct ArrayUtil {
473///
474/// // CLASS METHODS
475///
476/// /// Load to the specified `value` the element at the specified
477/// /// `index` of the specified `object` array. Return 0 if the
478/// /// element is successfully loaded to `value`, and a non-zero value
479/// /// otherwise. This function template requires that the specified
480/// /// `ARRAY_TYPE` is a `bdlat` "array" type. The behavior is
481/// /// undefined unless `0 <= index` and
482/// /// `index < bdlat_ArrayFunctions::size(object)`.
483/// template <class ARRAY_TYPE>
484/// static int getElement(typename bdlat_ArrayFunctions
485/// ::ElementType<ARRAY_TYPE>::Type *value,
486/// const ARRAY_TYPE& object,
487/// int index)
488/// {
489/// BSLMF_ASSERT(bdlat_ArrayFunctions::IsArray<ARRAY_TYPE>::value);
490///
491/// typedef typename bdlat_ArrayFunctions
492/// ::ElementType<ARRAY_TYPE>::Type ElementType;
493///
494/// GetElementAccessor<ElementType> elementAccessor(value);
495///
496/// return bdlat_ArrayFunctions::accessElement(object,
497/// elementAccessor,
498/// index);
499/// }
500///
501/// /// Assign the specified `value` to the element of the specified
502/// /// `object` array at the specified `index`. Return 0 if the
503/// /// element is successfully assigned to `value`, and a non-zero
504/// /// value otherwise. This function template requires that the
505/// /// specified `ARRAY_TYPE` is a `bdlat` "array" type. The behavior
506/// /// is undefined unless `0 <= index` and
507/// /// `index < bdlat_ArrayFunctions::size(*object)`.
508/// template <class ARRAY_TYPE>
509/// static int setElement(
510/// ARRAY_TYPE *object,
511/// int index,
512/// const typename bdlat_ArrayFunctions::ElementType<ARRAY_TYPE>
513/// ::Type& value)
514/// {
515/// BSLMF_ASSERT(bdlat_ArrayFunctions::IsArray<ARRAY_TYPE>::value);
516///
517/// typedef typename bdlat_ArrayFunctions::ElementType<ARRAY_TYPE>
518/// ::Type ElementType;
519///
520/// SetElementManipulator<ElementType> manipulator(value);
521///
522/// return bdlat_ArrayFunctions::manipulateElement(object,
523/// manipulator,
524/// index);
525/// }
526/// };
527/// @endcode
528/// Now, we can use these functors to write generic utility functions for
529/// getting and setting the value types of arbitrary "array" classes.
530/// @code
531/// void myUsageScenario()
532/// {
533/// mine::MyIntArray array;
534/// bdlat_ArrayFunctions::resize(&array, 4);
535///
536/// // Confirm initial values.
537///
538/// for (int index = 0; index < 4; ++index) {
539/// int value;
540/// int rc = ArrayUtil::getElement(&value, array, index);
541/// assert(0 == rc);
542/// assert(0 == value);
543/// }
544///
545/// // Set element `index * 10` as its value.
546///
547/// for (int index = 0; index < 4; ++index) {
548/// int value = index * 10;
549/// int rc = ArrayUtil::setElement(&array, index, value);
550/// assert(0 == rc);
551/// }
552///
553/// // Confirm value of each element.
554///
555/// for (int index = 0; index < 4; ++index) {
556/// int value;
557/// int rc = ArrayUtil::getElement(&value, array, index);
558/// assert(0 == rc);
559/// assert(index * 10 == value);
560/// }
561/// }
562/// @endcode
563///
564/// ### Example 4: Achieving Type Independence {#bdlat_arrayfunctions-example-4-achieving-type-independence}
565///
566///
567/// Suppose we have another type such as `your::YourFloatArray`, shown below:
568/// @code
569/// namespace BloombergLP {
570/// namespace your {
571///
572/// class YourFloatArray {
573///
574/// float *d_data_p;
575/// bsl::size_t d_size;
576/// bsl::size_t d_capacity;
577///
578/// public:
579/// // CREATORS
580/// YourFloatArray()
581/// : d_data_p(0)
582/// , d_size(0)
583/// {
584/// }
585///
586/// ~YourFloatArray()
587/// {
588/// delete[] d_data_p;
589/// }
590///
591/// // MANIPULATORS
592/// void setSize(bsl::size_t newSize); // Too large for inline.
593///
594/// float& element(bsl::size_t index)
595/// {
596/// assert(index < d_size);
597///
598/// return d_data_p[index];
599/// }
600///
601/// // ACCESSORS
602/// const float& element(bsl::size_t index) const
603/// {
604/// assert(index < d_size);
605///
606/// return d_data_p[index];
607/// }
608///
609/// bsl::size_t numElements() const
610/// {
611/// return d_size;
612/// }
613///
614/// bsl::size_t capacity() const
615/// {
616/// return d_capacity;
617/// }
618/// };
619///
620/// } // close namespace your
621/// } // close enterprise namespace
622/// @endcode
623/// Notice that while there are many similarities to `mine::MyIntArray`, there
624/// are also significant differences:
625/// * The element type is `float`, not `int`.
626/// * Many of the accessors are named differently (e.g., `numElements` instead
627/// of `size`, `setSize` instead of `resize`).
628/// * There is an additional attribute, `capacity`, because this class has a
629/// `setSize` method (not shown) that reduces calls to the heap by over
630/// allocating when the size is increased beyond the current capacity.
631///
632/// Nevertheless, since `your::YourFloatArray` also provides the functions
633/// and types expected by the `bdlat` infrastructure (not shown) we can
634/// successfully use `your::FloatArray` value instead of `mine::MyIntArray`
635/// in the previous usage scenario, with no other changes:
636/// @code
637/// void yourUsageScenario()
638/// {
639/// your::YourFloatArray array;
640/// bdlat_ArrayFunctions::resize(&array, 4);
641///
642/// // Confirm initial values.
643///
644/// for (int index = 0; index < 4; ++index) {
645/// float value;
646/// int rc = ArrayUtil::getElement(&value, array, index);
647/// assert(0 == rc);
648/// assert(0.0 == value);
649/// }
650///
651/// // Set element `index * 10` as its value.
652///
653/// for (int index = 0; index < 4; ++index) {
654/// float value = static_cast<float>(index * 10);
655/// int rc = ArrayUtil::setElement(&array, index, value);
656/// assert(0 == rc);
657/// }
658///
659/// // Confirm value of each element.
660///
661/// for (int index = 0; index < 4; ++index) {
662/// float value;
663/// int rc = ArrayUtil::getElement(&value, array, index);
664/// assert(0 == rc);
665/// assert(static_cast<float>(index * 10) == value);
666/// }
667/// }
668/// @endcode
669///
670/// Notice that syntax and order of `bdlat_ArrayFunctions` function
671/// calls have not been changed. The only difference is that the element
672/// type has changed from `int` to `float`.
673///
674/// Finally, instead of defining a new "array" type, we could substitute the
675/// existing type template `bsl::vector`. Note that this component
676/// provides specializations of the `bdlat_ArrayFunctions` for that
677/// type. Since the accessor and manipulator functions we created earlier are
678/// type neutral, we can simply drop `bsl::vector<bsl::string>` into our
679/// familiar scenario:
680/// @code
681/// void anotherUsageScenario()
682/// {
683/// bsl::vector<bsl::string> array; // STANDARD ARRAY TYPE
684/// bdlat_ArrayFunctions::resize(&array, 4);
685///
686/// // Confirm initial values.
687///
688/// for (int index = 0; index < 4; ++index) {
689/// bsl::string value;
690/// int rc = ArrayUtil::getElement(&value, array, index);
691/// assert(0 == rc);
692/// assert("" == value);
693/// }
694///
695/// // Set element `index * 10` as its value.
696///
697/// for (int index = 0; index < 4; ++index) {
698/// bsl::ostringstream oss; oss << (index * 10);
699/// int rc = ArrayUtil::setElement(&array, index, oss.str());
700/// assert(0 == rc);
701/// }
702///
703/// // Confirm value of each element.
704///
705/// for (int index = 0; index < 4; ++index) {
706/// bsl::string value;
707/// int rc = ArrayUtil::getElement(&value, array, index);
708///
709/// bsl::ostringstream oss; oss << (index * 10);
710///
711/// assert(0 == rc);
712/// assert(oss.str() == value);
713/// }
714/// }
715/// @endcode
716/// @}
717/** @} */
718/** @} */
719
720/** @addtogroup bdl
721 * @{
722 */
723/** @addtogroup bdlat
724 * @{
725 */
726/** @addtogroup bdlat_arrayfunctions
727 * @{
728 */
729
730#include <bdlscm_version.h>
731
732#include <bdlat_bdeatoverrides.h>
733
735
736#include <bsl_cstddef.h>
737#include <bsl_cstdlib.h>
738#include <bsl_vector.h>
739
740
741
742 // ==============================
743 // namespace bdlat_ArrayFunctions
744 // ==============================
745
746/// This `namespace` provides functions that expose "array" behavior for
747/// "array" types. Specializations are provided for `bsl::vector<TYPE>`.
748/// See the component-level documentation for more information.
749namespace bdlat_ArrayFunctions {
750
751 // META-FUNCTIONS
752
753 /// This meta-function should contain a typedef `Type` that specifies
754 /// the type of element stored in an array of the parameterized `TYPE`.
755 template <class TYPE>
757
758 /// This `struct` should be specialized for third-party types that are
759 /// need to expose "array" behavior. See the component-level
760 /// documentation for further information.
761 template <class TYPE>
763 };
764
765 // MANIPULATORS
766
767 /// Invoke the specified `manipulator` on the address of the element at the
768 /// specified `index` of the specified `array`. The supplied `manipulator`
769 /// must be a callable type that can be called as if it had the following
770 /// signature:
771 /// @code
772 // int manipulator(ELEMENT_TYPE *element);
773 /// @endcode
774 /// Return the value from the invocation of `manipulator`.
775 ///
776 /// \pre The behavior is undefined unless `0 <= index` and `index < size(*array)`.
777 template <class TYPE, class MANIPULATOR>
778 int manipulateElement(TYPE *array,
779 MANIPULATOR& manipulator,
780 int index);
781
782 /// If successful, make the capacity of the specified modifiable `array` at
783 /// least the specified `numElements` and return zero. If unsuccessful or
784 /// unsupported, return a non-zero value. This method has no effect, and
785 /// returns zero, if the current capacity meets or exceeds the required capacity.
786 ///
787 /// \pre The behavior is undefined unless `0 <= numElements`.
788 template <class TYPE>
789 int reserve(TYPE *array, int numElements);
790
791 /// Set the size of the specified modifiable `array` to the specified
792 /// `newSize`. If `newSize > size(array)`, then `newSize - size(array)`
793 /// elements with default values are appended to `array`. If
794 /// `newSize < size(array)`, then the `size(array) - newSize` elements
795 /// at the end of `array` are destroyed.
796 ///
797 /// \pre The behavior is undefined unless `0 <= newSize`.
798 template <class TYPE>
799 void resize(TYPE *array, int newSize);
800
801 // ACCESSORS
802
803 /// Invoke the specified `accessor` on the non-modifiable element at the
804 /// specified `index` of the specified `array`. The supplied `accessor`
805 /// must be a callable type that can be called as if it had the following
806 /// signature:
807 /// @code
808 /// int accessor(const ELEMENT_TYPE& element);
809 /// @endcode
810 /// Return the value from the invocation of `accessor`.
811 ///
812 /// \pre The behavior is undefined unless `0 <= index` and `index < size(array)`.
813 template <class TYPE, class ACCESSOR>
814 int accessElement(const TYPE& array,
815 ACCESSOR& accessor,
816 int index);
817
818 /// Return the number of elements in the specified `array`.
819 template <class TYPE>
820 bsl::size_t size(const TYPE& array);
821
822 /// Return `true` if `reserve` will attempt to reserve capacity in the
823 /// specified `array`, and `false` otherwise.
824 template <class TYPE>
825 bool supportsReserve(const TYPE& array);
826
827} // close namespace bdlat_ArrayFunctions
828
829 // =====================================
830 // default reserve capacity declarations
831 // =====================================
832
833/// This namespace declaration adds the default implementations for reserve
834/// capacity methods.
835namespace bdlat_ArrayFunctions {
836
837 // MANIPULATORS
838 template <class TYPE>
839 int bdlat_arrayReserve(TYPE *array, int numElements);
840
841 // ACCESSORS
842 template <class TYPE>
843 bool bdlat_arraySupportsReserve(const TYPE& array);
844
845} // close namespace bdlat_ArrayFunctions
846
847 // ========================
848 // bsl::vector declarations
849 // ========================
850
851/// This namespace declaration adds the implementation of the "array" traits for `bsl::vector` to `bdlat_ArrayFunctions`.
852///
853/// \note Note that `bsl::vector` is
854/// the canonical "array" type.
855namespace bdlat_ArrayFunctions {
856
857 // META-FUNCTIONS
858 template <class TYPE, class ALLOC>
859 struct IsArray<bsl::vector<TYPE, ALLOC> > : bsl::true_type {
860 };
861
862 template <class TYPE, class ALLOC>
863 struct ElementType<bsl::vector<TYPE, ALLOC> > {
864 typedef TYPE Type;
865 };
866
867 // MANIPULATORS
868 template <class TYPE, class ALLOC, class MANIPULATOR>
870 MANIPULATOR& manipulator,
871 int index);
872
873 template <class TYPE, class ALLOC>
874 int bdlat_arrayReserve(bsl::vector<TYPE, ALLOC> *array, int numElements);
875
876 template <class TYPE, class ALLOC>
878
879 // ACCESSORS
880 template <class TYPE, class ALLOC, class ACCESSOR>
882 ACCESSOR& accessor,
883 int index);
884
885 template <class TYPE, class ALLOC>
886 bsl::size_t bdlat_arraySize(const bsl::vector<TYPE, ALLOC>& array);
887
888 template <class TYPE, class ALLOC>
890
891} // close namespace bdlat_ArrayFunctions
892
893// ============================================================================
894// INLINE DEFINITIONS
895// ============================================================================
896
897 // -------------------------
898 // namespace-level functions
899 // -------------------------
900
901// MANIPULATORS
902template <class TYPE, class MANIPULATOR>
903inline
905 MANIPULATOR& manipulator,
906 int index)
907{
908 return bdlat_arrayManipulateElement(array, manipulator, index);
909}
910
911template <class TYPE>
912inline
913int bdlat_ArrayFunctions::reserve(TYPE *array, int numElements)
914{
915 return bdlat_arrayReserve(array, numElements);
916}
917
918template <class TYPE>
919inline
920void bdlat_ArrayFunctions::resize(TYPE *array, int newSize)
921{
922 bdlat_arrayResize(array, newSize);
923}
924
925// ACCESSORS
926template <class TYPE, class ACCESSOR>
927inline
928int bdlat_ArrayFunctions::accessElement(const TYPE& array,
929 ACCESSOR& accessor,
930 int index)
931{
932 return bdlat_arrayAccessElement(array, accessor, index);
933}
934
935template <class TYPE>
936inline
937bsl::size_t bdlat_ArrayFunctions::size(const TYPE& array)
938{
939 return bdlat_arraySize(array);
940}
941
942template <class TYPE>
943inline
944bool bdlat_ArrayFunctions::supportsReserve(const TYPE& array)
945{
946 return bdlat_arraySupportsReserve(array);
947}
948
949 // ------------------------------------
950 // default reserve capacity definitions
951 // ------------------------------------
952
953// MANIPULATORS
954template <class TYPE>
955inline
957{
958 return -1;
959}
960
961// ACCESSORS
962template <class TYPE>
963inline
965{
966 return false;
967}
968
969 // -----------------------
970 // bsl::vector definitions
971 // -----------------------
972
973// MANIPULATORS
974template <class TYPE, class ALLOC, class MANIPULATOR>
975inline
978 MANIPULATOR& manipulator,
979 int index)
980{
981 TYPE& element = (*array)[index];
982 return manipulator(&element);
983}
984
985template <class TYPE, class ALLOC>
986inline
989 int numElements)
990{
991 array->reserve(numElements);
992 return 0;
993}
994
995template <class TYPE, class ALLOC>
996inline
998 int newSize)
999{
1000 array->resize(newSize);
1001}
1002
1003// ACCESSORS
1004template <class TYPE, class ALLOC, class ACCESSOR>
1005inline
1007 const bsl::vector<TYPE, ALLOC>& array,
1008 ACCESSOR& accessor,
1009 int index)
1010{
1011 return accessor(array[index]);
1012}
1013
1014template <class TYPE, class ALLOC>
1015inline
1017 const bsl::vector<TYPE, ALLOC>& array)
1018{
1019 return array.size();
1020}
1021
1022template <class TYPE, class ALLOC>
1023inline
1026{
1027 return true;
1028}
1029
1030
1031
1032#endif
1033
1034// ----------------------------------------------------------------------------
1035// Copyright 2015 Bloomberg Finance L.P.
1036//
1037// Licensed under the Apache License, Version 2.0 (the "License");
1038// you may not use this file except in compliance with the License.
1039// You may obtain a copy of the License at
1040//
1041// http://www.apache.org/licenses/LICENSE-2.0
1042//
1043// Unless required by applicable law or agreed to in writing, software
1044// distributed under the License is distributed on an "AS IS" BASIS,
1045// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1046// See the License for the specific language governing permissions and
1047// limitations under the License.
1048// ----------------------------- END-OF-FILE ----------------------------------
1049
1050/** @} */
1051/** @} */
1052/** @} */
size_type size() const BSLS_KEYWORD_NOEXCEPT
Return the number of elements in this vector.
Definition bslstl_vector.h:3019
Definition bslstl_vector.h:1120
void reserve(size_type newCapacity)
Definition bslstl_vector.h:4263
void resize(size_type newSize)
Definition bslstl_vector.h:4189
#define BSLS_IDENT(str)
BSLS_IDENT() - insert string into .comment binary segment (if supported)
Definition bsls_ident.h:238
void bdlat_arrayResize(ArrayRef *array, int newSize)
Definition bdlar_arrayref.h:300
int bdlat_arrayAccessElement(const ArrayRef &array, t_ACCESSOR &accessor, int index)
Definition bdlar_arrayref.h:307
bsl::size_t bdlat_arraySize(const ArrayRef &array)
Definition bdlar_arrayref.h:315
Definition bdlar_arrayref.h:422
int bdlat_arrayReserve(TYPE *array, int numElements)
bool bdlat_arraySupportsReserve(const TYPE &array)
int manipulateElement(TYPE *array, MANIPULATOR &manipulator, int index)
void resize(TYPE *array, int newSize)
void bdlat_arrayResize(bsl::vector< TYPE, ALLOC > *array, int newSize)
bool supportsReserve(const TYPE &array)
bsl::size_t size(const TYPE &array)
Return the number of elements in the specified array.
int reserve(TYPE *array, int numElements)
int accessElement(const TYPE &array, ACCESSOR &accessor, int index)
int bdlat_arrayAccessElement(const bsl::vector< TYPE, ALLOC > &array, ACCESSOR &accessor, int index)
bsl::size_t bdlat_arraySize(const bsl::vector< TYPE, ALLOC > &array)
int bdlat_arrayManipulateElement(bsl::vector< TYPE, ALLOC > *array, MANIPULATOR &manipulator, int index)
Definition bdlat_valuetypefunctions.h:939
TYPE Type
Definition bdlat_arrayfunctions.h:864
Definition bdlat_arrayfunctions.h:756
Definition bdlat_arrayfunctions.h:762
Definition bslmf_integralconstant.h:261