BDE 4.39.x Production Release
Loading...
Searching...
No Matches
bdlat_arrayutil.h
Go to the documentation of this file.
1/// @file bdlat_arrayutil.h
2///
3/// The content of this file has been pre-processed for Doxygen.
4///
5
6
7// bdlat_arrayutil.h -*-C++-*-
8#ifndef INCLUDED_BDLAT_ARRAYUTIL
9#define INCLUDED_BDLAT_ARRAYUTIL
10
11#include <bsls_ident.h>
12BSLS_IDENT("$Id: $")
13
14/// @defgroup bdlat_arrayutil bdlat_arrayutil
15/// @brief Provide utilities for operating on `bdlat` "array" types.
16/// @addtogroup bdl
17/// @{
18/// @addtogroup bdlat
19/// @{
20/// @addtogroup bdlat_arrayutil
21/// @{
22///
23/// <h1> Outline </h1>
24/// * <a href="#bdlat_arrayutil-purpose"> Purpose</a>
25/// * <a href="#bdlat_arrayutil-classes"> Classes </a>
26/// * <a href="#bdlat_arrayutil-description"> Description </a>
27/// * <a href="#bdlat_arrayutil-primitive-and-derived-functions-of-arrays"> Primitive and Derived Functions of Arrays </a>
28/// * <a href="#bdlat_arrayutil-usage"> Usage </a>
29/// * <a href="#bdlat_arrayutil-example-1-accessing-an-array-element-and-its-category"> Example 1: Accessing an Array Element And Its Category </a>
30///
31/// # Purpose {#bdlat_arrayutil-purpose}
32/// Provide utilities for operating on `bdlat` "array" types.
33///
34/// # Classes {#bdlat_arrayutil-classes}
35///
36/// - bdlat::ArrayUtil: namespace for utility functions on "array" types
37///
38/// @see bdlat_arrayfunctions, bdlat_typecategory
39///
40/// # Description {#bdlat_arrayutil-description}
41/// This component provides a utility `struct`, `bdlat::ArrayUtil`,
42/// which serves as a namespace for a collection of function templates providing
43/// derived operations for "array" types. See @ref bdlat_arrayfunctions
44/// for the set of requirements of "array" types in the `bdlat` framework. See
45/// @ref bdlat_typecategory for more general information about this framework.
46///
47/// ## Primitive and Derived Functions of Arrays {#bdlat_arrayutil-primitive-and-derived-functions-of-arrays}
48///
49///
50/// In order to be "plugged in" to the `bdlat` framework as an "array", a type
51/// must meet a set of requirements including providing certain function
52/// overloads (customization points) and specifying certain type traits, as
53/// specified by the @ref bdlat_arrayfunctions component. We call the required
54/// function overloads the "primitive" operations of "array" types. This
55/// component provides "derived" operations, which are operations that are
56/// exclusively defined in terms of primitive operations, and as such can be
57/// used with any "array" type.
58///
59/// ## Usage {#bdlat_arrayutil-usage}
60///
61///
62/// In this section we show intended usage of this component.
63///
64/// ### Example 1: Accessing an Array Element And Its Category {#bdlat_arrayutil-example-1-accessing-an-array-element-and-its-category}
65///
66///
67/// Suppose we would like to define a function that detects whether an element
68/// of an array is itself an array, in order to more generally detect nested
69/// arrays.
70///
71/// First, we need to define an accessor functor per
72/// {@ref bdlat_typecategory |`ACCESSOR` Functors} that will be used to detect
73/// whether an array element is itself an array:
74/// @code
75/// class MyArrayDetector {
76/// // DATA
77/// bool d_didVisitArray;
78///
79/// public:
80/// // CREATORS
81/// MyArrayDetector()
82/// : d_didVisitArray(false)
83/// {
84/// }
85///
86/// // MANIPULATORS
87/// template <class TYPE>
88/// int operator()(const TYPE& object, bdlat_TypeCategory::Array)
89/// {
90/// d_didVisitArray = true;
91/// return 0;
92/// }
93///
94/// template <class TYPE, class OTHER_CATEGORY>
95/// int operator()(const TYPE&, OTHER_CATEGORY)
96/// {
97/// d_didVisitArray = false;
98/// return 0;
99/// }
100///
101/// // ACCESSORS
102/// bool didVisitArray()
103/// {
104/// return d_didVisitArray;
105/// }
106/// };
107/// @endcode
108/// Then, we can define a utility `struct`, `MyArrayUtil`, that provides a
109/// function for detecting whether or not an array has an element that is itself
110/// an array:
111/// @code
112/// struct MyArrayUtil {
113///
114/// // CLASS METHODS
115/// template <class TYPE>
116/// static int isElementAnArray(bool *isArray,
117/// const TYPE& array,
118/// int index)
119/// // Load the value 'true' to the specified 'isArray' if the element
120/// // at the specified 'index' of the specified 'array' has the
121/// // "array" type category, and load the value 'false' otherwise.
122/// // Return 0 on success, and a non-zero value otherwise. If a
123/// // non-zero value is returned, the value loaded to 'isArray' is
124/// // unspecified. The behavior is undefined unless the specified
125/// // 'array' has the "array" type category, '0 <= index', and
126/// // 'index < bdlat_ArrayFunctions::size(array)'.
127/// {
128/// BSLS_ASSERT(bdlat_TypeCategoryFunctions::select(array) ==
129/// bdlat_TypeCategory::e_ARRAY_CATEGORY);
130/// BSLS_ASSERT(0 <= index);
131/// BSLS_ASSERT(static_cast<bsl::size_t>(index) <
132/// bdlat_ArrayFunctions::size(array));
133///
134/// MyArrayDetector detector;
135/// int rc = bdlat::ArrayUtil::accessElementByCategory(array,
136/// detector,
137/// index);
138/// if (0 != rc) {
139/// return -1; // RETURN
140/// }
141///
142/// *isArray = detector.didVisitArray();
143/// return 0;
144/// }
145/// };
146/// @endcode
147/// Finally, we can use this utility to detect whether elements of array types
148/// are themselves arrays:
149/// @code
150/// void example()
151/// {
152/// bsl::vector<int> vectorA;
153/// vectorA.push_back(42);
154///
155/// bool isArray = false;
156/// int rc = MyArrayUtil::isElementAnArray(&isArray, vectorA, 0);
157///
158/// assert(0 == rc);
159/// assert(! isArray);
160///
161/// bsl::vector<bsl::vector<int> > vectorB;
162/// vectorB.push_back(bsl::vector<int>());
163///
164/// rc = MyArrayUtil::isElementAnArray(&isArray, vectorB, 0);
165///
166/// assert(0 == rc);
167/// assert(isArray);
168/// }
169/// @endcode
170/// @}
171/** @} */
172/** @} */
173
174/** @addtogroup bdl
175 * @{
176 */
177/** @addtogroup bdlat
178 * @{
179 */
180/** @addtogroup bdlat_arrayutil
181 * @{
182 */
183
184#include <bdlscm_version.h>
185
186#include <bdlat_arrayfunctions.h>
187#include <bdlat_typecategory.h>
188
189#include <bslmf_assert.h>
191
192#include <bsls_assert.h>
193#include <bsls_platform.h>
194
195#include <bsl_cstddef.h>
196
197
198namespace bdlat {
199
200 // ================
201 // struct ArrayUtil
202 // ================
203
204/// This `struct` provides a namespace for suite of function templates
205/// providing non-primitive operations on "array" types.
206///
207/// See @ref bdlat_arrayutil
208struct ArrayUtil {
209
210 private:
211 // PRIVATE TYPES
212
213 /// This private class provides a function-object type that adapts a
214 /// (categorized) accessor functor to an uncategorized accessor functor.
215 /// For the definition of an accessor functor, see
216 /// {@ref bdlat_typecategory |`ACCESSOR` Functors}. An uncategorized
217 /// accessor functor is one that does not take a second, `category`,
218 /// argument, such as a functor that may be passed to
219 /// `bdlat_ArrayFunctions::accessElement`, for example.
220 template <class ACCESSOR>
221 class AccessByCategoryAdapter;
222
223 /// This private class provides a function-object type that adapts a
224 /// (categorized) manipulator functor to an uncategorized manipulator
225 /// functor. For the definition of a manipulator functor, see
226 /// {@ref bdlat_typecategory |`MANIPULATOR` Functors}. An uncategorized
227 /// manipulator functor is one that does not take a second, `category`,
228 /// argument, such as a functor that may be passed to
229 /// `bdlat_ArrayFunctions::manipulateElement`, for example.
230 template <class MANIPULATOR>
231 class ManipulateByCategoryAdapter;
232
233 public:
234 // CLASS METHODS
235
236 /// Invoke the specified `accessor` on the non-modifiable element at the
237 /// specified `index` of the specified `array` and on a prvalue of the
238 /// category tag type for the dynamic category of the element. See
239 /// {@ref bdlat_typecategory |Category Tags and Enumerators} for
240 /// documentation about category tags. Return the value from the
241 /// invocation of `accessor`. The accessor must be an accessor functor.
242 /// See {@ref bdlat_typecategory |`ACCESSOR` Functors} for the requirements on `accessor`.
243 ///
244 /// \pre The behavior is undefined unless
245 /// `0 <= index < bdlat_ArrayFunctions::size(array)`.
246 template <class TYPE, class ACCESSOR>
247 static int accessElementByCategory(const TYPE& array,
248 ACCESSOR& accessor,
249 int index);
250
251 /// Invoke the specified `manipulator` on the address of the element at
252 /// the specified `index` of the specified `array` and on a prvalue of
253 /// the category tag type for the dynamic category of the element. See
254 /// {@ref bdlat_typecategory |Category Tags and Enumerators} for
255 /// documentation about category tags. Return the value from the
256 /// invocation of `manipulator`. The `manipulator` must be a
257 /// manipulator functor. See
258 /// {@ref bdlat_typecategory |`MANIPULATOR` Functors} for the requirements on `manipulator`.
259 ///
260 /// \pre The behavior is undefined unless
261 /// `0 <= index < bdlat_ArrayFunctions::size(array)`.
262 template <class TYPE, class MANIPULATOR>
263 static int manipulateElementByCategory(TYPE *array,
264 MANIPULATOR& manipulator,
265 int index);
266};
267
268 // ========================================
269 // class ArrayUtil::AccessByCategoryAdapter
270 // ========================================
271
272/// See the class-level documentation of `ArrayUtil` for the description of
273/// this component-private class template.
274template <class ACCESSOR>
275class ArrayUtil::AccessByCategoryAdapter {
276
277 // DATA
278
279 // The `accessor` attribute of this object
280 ACCESSOR *d_accessor_p;
281
282 public:
283 // CREATORS
284
285 /// Create an `AccessByCategoryAdapter` object having the specified
286 /// `accessor` attribute value.
287 explicit AccessByCategoryAdapter(ACCESSOR *accessor);
288
289 // ACCESSORS
290
291 /// Invoke the `accessor` of this object with the specified `value` and
292 /// a prvalue of the category tag type for its dynamic category. Return
293 /// the value from the invocation of the `accessor`.
294 template <class VALUE_TYPE>
295 int operator()(const VALUE_TYPE& value) const;
296};
297
298 // ============================================
299 // class ArrayUtil::ManipulateByCategoryAdapter
300 // ============================================
301
302/// See the class-level documentation of `ArrayUtil` for the description of
303/// this component-private class template.
304template <class MANIPULATOR>
305class ArrayUtil::ManipulateByCategoryAdapter {
306
307 // DATA
308
309 // The `manipulator` attribute of this object.
310 MANIPULATOR *d_manipulator_p;
311
312 public:
313 // CREATORS
314
315 /// Create a `ManipulateByCategory` object having the specified
316 /// `manipulator` attribute value.
317 explicit ManipulateByCategoryAdapter(MANIPULATOR *manipulator);
318
319 // ACCESSORS
320
321 /// Invoke the `manipulator` of this object with the specified `value`
322 /// and a prvalue of the category tag type for its dynamic category.
323 /// Return the value from the invocation of the `manipulator`.
324 template <class VALUE_TYPE>
325 int operator()(VALUE_TYPE *value) const;
326};
327
328// ============================================================================
329// INLINE DEFINITIONS
330// ============================================================================
331
332 // ----------------
333 // struct ArrayUtil
334 // ----------------
335
336// CLASS METHODS
337template <class TYPE, class ACCESSOR>
338inline
340 ACCESSOR& accessor,
341 int index)
342{
343#if !defined(BSLS_PLATFORM_CMP_SUN)
345#endif
348 BSLS_ASSERT(0 <= index);
349 BSLS_ASSERT(static_cast<bsl::size_t>(index) <
351
352 const AccessByCategoryAdapter<ACCESSOR> adapter(&accessor);
353 return bdlat_ArrayFunctions::accessElement(array, adapter, index);
354}
355
356template <class TYPE, class MANIPULATOR>
357inline
359 MANIPULATOR& manipulator,
360 int index)
361{
362#if !defined(BSLS_PLATFORM_CMP_SUN)
364#endif
365 BSLS_ASSERT(array);
368 BSLS_ASSERT(0 <= index);
369 BSLS_ASSERT(static_cast<bsl::size_t>(index) <
371
372 const ManipulateByCategoryAdapter<MANIPULATOR> adapter(&manipulator);
373 return bdlat_ArrayFunctions::manipulateElement(array, adapter, index);
374}
375
376 // ----------------------------------------
377 // class ArrayUtil::AccessByCategoryAdapter
378 // ----------------------------------------
379
380// CREATORS
381template <class ACCESSOR>
382inline
383ArrayUtil::AccessByCategoryAdapter<ACCESSOR>::AccessByCategoryAdapter(
384 ACCESSOR *accessor)
385: d_accessor_p(accessor)
386{
387}
388
389// ACCESSORS
390template <class ACCESSOR>
391template <class VALUE_TYPE>
392inline
393int ArrayUtil::AccessByCategoryAdapter<ACCESSOR>::operator()(
394 const VALUE_TYPE& value) const
395{
396 return bdlat_TypeCategoryUtil::accessByCategory(value, *d_accessor_p);
397}
398
399 // --------------------------------------------
400 // class ArrayUtil::ManipulateByCategoryAdapter
401 // --------------------------------------------
402
403// CREATORS
404template <class MANIPULATOR>
405inline
406ArrayUtil::ManipulateByCategoryAdapter<
407 MANIPULATOR>::ManipulateByCategoryAdapter(MANIPULATOR *manipulator)
408: d_manipulator_p(manipulator)
409{
410}
411
412template <class MANIPULATOR>
413template <class VALUE_TYPE>
414inline
415int ArrayUtil::ManipulateByCategoryAdapter<MANIPULATOR>::operator()(
416 VALUE_TYPE *value) const
417{
419 *d_manipulator_p);
420}
421
422} // close package namespace
423
424
425#endif // INCLUDED_BDLAT_ARRAYUTIL
426
427// ----------------------------------------------------------------------------
428// Copyright 2022 Bloomberg Finance L.P.
429//
430// Licensed under the Apache License, Version 2.0 (the "License");
431// you may not use this file except in compliance with the License.
432// You may obtain a copy of the License at
433//
434// http://www.apache.org/licenses/LICENSE-2.0
435//
436// Unless required by applicable law or agreed to in writing, software
437// distributed under the License is distributed on an "AS IS" BASIS,
438// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
439// See the License for the specific language governing permissions and
440// limitations under the License.
441// ----------------------------- END-OF-FILE ----------------------------------
442
443/** @} */
444/** @} */
445/** @} */
static int manipulateByCategory(TYPE *object, MANIPULATOR &manipulator)
Definition bdlat_typecategory.h:1414
static int accessByCategory(const TYPE &object, ACCESSOR &accessor)
Definition bdlat_typecategory.h:1455
#define BSLMF_ASSERT(expr)
Definition bslmf_assert.h:231
#define BSLS_ASSERT(X)
Definition bsls_assert.h:1976
#define BSLS_IDENT(str)
BSLS_IDENT() - insert string into .comment binary segment (if supported)
Definition bsls_ident.h:238
int manipulateElement(TYPE *array, MANIPULATOR &manipulator, int index)
bsl::size_t size(const TYPE &array)
Return the number of elements in the specified array.
int accessElement(const TYPE &array, ACCESSOR &accessor, int index)
bdlat_TypeCategory::Value select(const TYPE &object)
Definition bdlat_arrayutil.h:198
Definition bdlat_arrayutil.h:208
static int manipulateElementByCategory(TYPE *array, MANIPULATOR &manipulator, int index)
Definition bdlat_arrayutil.h:358
static int accessElementByCategory(const TYPE &array, ACCESSOR &accessor, int index)
Definition bdlat_arrayutil.h:339
Definition bdlat_arrayfunctions.h:762
@ e_ARRAY_CATEGORY
Definition bdlat_typecategory.h:1048