BDE 4.14.0 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.
206struct ArrayUtil {
207
208 private:
209 // PRIVATE TYPES
210
211 /// This private class provides a function-object type that adapts a
212 /// (categorized) accessor functor to an uncategorized accessor functor.
213 /// For the definition of an accessor functor, see
214 /// {@ref bdlat_typecategory |`ACCESSOR` Functors}. An uncategorized
215 /// accessor functor is one that does not take a second, `category`,
216 /// argument, such as a functor that may be passed to
217 /// `bdlat_ArrayFunctions::accessElement`, for example.
218 template <class ACCESSOR>
219 class AccessByCategoryAdapter;
220
221 /// This private class provides a function-object type that adapts a
222 /// (categorized) manipulator functor to an uncategorized manipulator
223 /// functor. For the definition of a manipulator functor, see
224 /// {@ref bdlat_typecategory |`MANIPULATOR` Functors}. An uncategorized
225 /// manipulator functor is one that does not take a second, `category`,
226 /// argument, such as a functor that may be passed to
227 /// `bdlat_ArrayFunctions::manipulateElement`, for example.
228 template <class MANIPULATOR>
229 class ManipulateByCategoryAdapter;
230
231 public:
232 // CLASS METHODS
233
234 /// Invoke the specified `accessor` on the non-modifiable element at the
235 /// specified `index` of the specified `array` and on a prvalue of the
236 /// category tag type for the dynamic category of the element. See
237 /// {@ref bdlat_typecategory |Category Tags and Enumerators} for
238 /// documentation about category tags. Return the value from the
239 /// invocation of `accessor`. The accessor must be an accessor functor.
240 /// See {@ref bdlat_typecategory |`ACCESSOR` Functors} for the requirements
241 /// on `accessor`. The behavior is undefined unless
242 /// `0 <= index < bdlat_ArrayFunctions::size(array)`.
243 template <class TYPE, class ACCESSOR>
244 static int accessElementByCategory(const TYPE& array,
245 ACCESSOR& accessor,
246 int index);
247
248 /// Invoke the specified `manipulator` on the address of the element at
249 /// the specified `index` of the specified `array` and on a prvalue of
250 /// the category tag type for the dynamic category of the element. See
251 /// {@ref bdlat_typecategory |Category Tags and Enumerators} for
252 /// documentation about category tags. Return the value from the
253 /// invocation of `manipulator`. The `manipulator` must be a
254 /// manipulator functor. See
255 /// {@ref bdlat_typecategory |`MANIPULATOR` Functors} for the requirements
256 /// on `manipulator`. The behavior is undefined unless
257 /// `0 <= index < bdlat_ArrayFunctions::size(array)`.
258 template <class TYPE, class MANIPULATOR>
259 static int manipulateElementByCategory(TYPE *array,
260 MANIPULATOR& manipulator,
261 int index);
262};
263
264 // ========================================
265 // class ArrayUtil::AccessByCategoryAdapter
266 // ========================================
267
268/// See the class-level documentation of `ArrayUtil` for the description of
269/// this component-private class template.
270template <class ACCESSOR>
271class ArrayUtil::AccessByCategoryAdapter {
272
273 // DATA
274
275 // The `accessor` attribute of this object
276 ACCESSOR *d_accessor_p;
277
278 public:
279 // CREATORS
280
281 /// Create an `AccessByCategoryAdapter` object having the specified
282 /// `accessor` attribute value.
283 explicit AccessByCategoryAdapter(ACCESSOR *accessor);
284
285 // ACCESSORS
286
287 /// Invoke the `accessor` of this object with the specified `value` and
288 /// a prvalue of the category tag type for its dynamic category. Return
289 /// the value from the invocation of the `accessor`.
290 template <class VALUE_TYPE>
291 int operator()(const VALUE_TYPE& value) const;
292};
293
294 // ============================================
295 // class ArrayUtil::ManipulateByCategoryAdapter
296 // ============================================
297
298/// See the class-level documentation of `ArrayUtil` for the description of
299/// this component-private class template.
300template <class MANIPULATOR>
301class ArrayUtil::ManipulateByCategoryAdapter {
302
303 // DATA
304
305 // The `manipulator` attribute of this object.
306 MANIPULATOR *d_manipulator_p;
307
308 public:
309 // CREATORS
310
311 /// Create a `ManipulateByCategory` object having the specified
312 /// `manipulator` attribute value.
313 explicit ManipulateByCategoryAdapter(MANIPULATOR *manipulator);
314
315 // ACCESSORS
316
317 /// Invoke the `manipulator` of this object with the specified `value`
318 /// and a prvalue of the category tag type for its dynamic category.
319 /// Return the value from the invocation of the `manipulator`.
320 template <class VALUE_TYPE>
321 int operator()(VALUE_TYPE *value) const;
322};
323
324// ============================================================================
325// INLINE DEFINITIONS
326// ============================================================================
327
328 // ----------------
329 // struct ArrayUtil
330 // ----------------
331
332// CLASS METHODS
333template <class TYPE, class ACCESSOR>
334inline
336 ACCESSOR& accessor,
337 int index)
338{
339#if !defined(BSLS_PLATFORM_CMP_SUN)
341#endif
344 BSLS_ASSERT(0 <= index);
345 BSLS_ASSERT(static_cast<bsl::size_t>(index) <
347
348 const AccessByCategoryAdapter<ACCESSOR> adapter(&accessor);
349 return bdlat_ArrayFunctions::accessElement(array, adapter, index);
350}
351
352template <class TYPE, class MANIPULATOR>
353inline
355 MANIPULATOR& manipulator,
356 int index)
357{
358#if !defined(BSLS_PLATFORM_CMP_SUN)
360#endif
361 BSLS_ASSERT(array);
364 BSLS_ASSERT(0 <= index);
365 BSLS_ASSERT(static_cast<bsl::size_t>(index) <
367
368 const ManipulateByCategoryAdapter<MANIPULATOR> adapter(&manipulator);
369 return bdlat_ArrayFunctions::manipulateElement(array, adapter, index);
370}
371
372 // ----------------------------------------
373 // class ArrayUtil::AccessByCategoryAdapter
374 // ----------------------------------------
375
376// CREATORS
377template <class ACCESSOR>
378inline
379ArrayUtil::AccessByCategoryAdapter<ACCESSOR>::AccessByCategoryAdapter(
380 ACCESSOR *accessor)
381: d_accessor_p(accessor)
382{
383}
384
385// ACCESSORS
386template <class ACCESSOR>
387template <class VALUE_TYPE>
388inline
389int ArrayUtil::AccessByCategoryAdapter<ACCESSOR>::operator()(
390 const VALUE_TYPE& value) const
391{
392 return bdlat_TypeCategoryUtil::accessByCategory(value, *d_accessor_p);
393}
394
395 // --------------------------------------------
396 // class ArrayUtil::ManipulateByCategoryAdapter
397 // --------------------------------------------
398
399// CREATORS
400template <class MANIPULATOR>
401inline
402ArrayUtil::ManipulateByCategoryAdapter<
403 MANIPULATOR>::ManipulateByCategoryAdapter(MANIPULATOR *manipulator)
404: d_manipulator_p(manipulator)
405{
406}
407
408template <class MANIPULATOR>
409template <class VALUE_TYPE>
410inline
411int ArrayUtil::ManipulateByCategoryAdapter<MANIPULATOR>::operator()(
412 VALUE_TYPE *value) const
413{
415 *d_manipulator_p);
416}
417
418} // close package namespace
419
420
421#endif // INCLUDED_BDLAT_ARRAYUTIL
422
423// ----------------------------------------------------------------------------
424// Copyright 2022 Bloomberg Finance L.P.
425//
426// Licensed under the Apache License, Version 2.0 (the "License");
427// you may not use this file except in compliance with the License.
428// You may obtain a copy of the License at
429//
430// http://www.apache.org/licenses/LICENSE-2.0
431//
432// Unless required by applicable law or agreed to in writing, software
433// distributed under the License is distributed on an "AS IS" BASIS,
434// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
435// See the License for the specific language governing permissions and
436// limitations under the License.
437// ----------------------------- END-OF-FILE ----------------------------------
438
439/** @} */
440/** @} */
441/** @} */
static int manipulateByCategory(TYPE *object, MANIPULATOR &manipulator)
Definition bdlat_typecategory.h:1404
static int accessByCategory(const TYPE &object, ACCESSOR &accessor)
Definition bdlat_typecategory.h:1444
#define BSLMF_ASSERT(expr)
Definition bslmf_assert.h:229
#define BSLS_ASSERT(X)
Definition bsls_assert.h:1804
#define BSLS_IDENT(str)
Definition bsls_ident.h:195
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:206
static int manipulateElementByCategory(TYPE *array, MANIPULATOR &manipulator, int index)
Definition bdlat_arrayutil.h:354
static int accessElementByCategory(const TYPE &array, ACCESSOR &accessor, int index)
Definition bdlat_arrayutil.h:335
Definition bdlat_arrayfunctions.h:718
@ e_ARRAY_CATEGORY
Definition bdlat_typecategory.h:1046