BDE 4.14.0 Production release
Loading...
Searching...
No Matches
bdlb_arrayutil.h
Go to the documentation of this file.
1/// @file bdlb_arrayutil.h
2///
3/// The content of this file has been pre-processed for Doxygen.
4///
5
6
7// bdlb_arrayutil.h -*-C++-*-
8#ifndef INCLUDED_BDLB_ARRAYUTIL
9#define INCLUDED_BDLB_ARRAYUTIL
10# include <bsls_ident.h>
11BSLS_IDENT("$Id: $")
12
13/// @defgroup bdlb_arrayutil bdlb_arrayutil
14/// @brief Provide utilities to determine properties of fixed-sized arrays.
15/// @addtogroup bdl
16/// @{
17/// @addtogroup bdlb
18/// @{
19/// @addtogroup bdlb_arrayutil
20/// @{
21///
22/// <h1> Outline </h1>
23/// * <a href="#bdlb_arrayutil-purpose"> Purpose</a>
24/// * <a href="#bdlb_arrayutil-classes"> Classes </a>
25/// * <a href="#bdlb_arrayutil-macros"> Macros </a>
26/// * <a href="#bdlb_arrayutil-description"> Description </a>
27/// * <a href="#bdlb_arrayutil-usage"> Usage </a>
28/// * <a href="#bdlb_arrayutil-example-1-basic-syntax"> Example 1: Basic Syntax </a>
29/// * <a href="#bdlb_arrayutil-example-2-use-with-database-interfaces"> Example 2: Use with Database Interfaces </a>
30///
31/// # Purpose {#bdlb_arrayutil-purpose}
32/// Provide utilities to determine properties of fixed-sized arrays.
33///
34/// # Classes {#bdlb_arrayutil-classes}
35///
36/// - bdlb::ArrayUtil: namespace for array access function templates
37///
38/// # Macros {#bdlb_arrayutil-macros}
39///
40/// - BDLB_ARRAYUTIL_SIZE: get a constant expression with an array's length.
41/// - BDLB_ARRAYUTIL_LENGTH: get a constant expression with an array's length.
42///
43/// # Description {#bdlb_arrayutil-description}
44/// This component provides a utility `struct`, `bdlb::ArrayUtil`,
45/// that serves as a namespace for a collection of function templates providing
46/// access to the length and iterators of statically sized built-in arrays.
47///
48/// The basic idea is that the compiler knows the length of statically sized
49/// arrays and the corresponding information can be exposed using simple
50/// function templates. The use of these function templates is easier and safer
51/// than the alternatives like use of `sizeof` (turning the array into a pointer
52/// doesn't cause the use of `sizeof` to fail at compile-time but it yields a
53/// wrong result) or manually specifying the length of an array.
54///
55/// ## Usage {#bdlb_arrayutil-usage}
56///
57///
58/// This section illustrates intended use of this component.
59///
60/// ### Example 1: Basic Syntax {#bdlb_arrayutil-example-1-basic-syntax}
61///
62///
63/// When creating a sequence of values it is often easy to write the sequence as
64/// an initialized array and use this array to initialize a container. Since
65/// the array's length may be changed as the program is maintained, the code
66/// using the array should automatically determine the array's length or
67/// automatically determine iterators to the beginning and the end of the array.
68///
69/// For example, to initialize a `bsl::vector<int>` with the first few prime
70/// numbers stored in an array the following code uses the `begin` and `end`
71/// methods of `bdlb::ArrayUtil`:
72/// @code
73/// void usePrimes(bool verbose)
74/// {
75/// if (verbose) cout << "\n" << "'usePrimes'" << "\n"
76/// << "===========" << "\n";
77///
78/// const int primes[] = { 2, 3, 5, 7, 11, 13, 17 };
79/// bsl::vector<int> values(bdlb::ArrayUtil::begin(primes),
80/// bdlb::ArrayUtil::end(primes));
81///
82/// assert(values.size() == bdlb::ArrayUtil::size(primes));
83/// @endcode
84/// Notice that, after constructing `values` with the content of the array
85/// `primes` the assertion verifies that the correct number of values is stored
86/// in `values`.
87///
88/// When the length is needed as a constant expression, e.g., to use it for the
89/// length of another array, the macro `BDLB_ARRAYUTIL_LENGTH(array)` can be
90/// used:
91/// @code
92/// int reversePrimes[BDLB_ARRAYUTIL_SIZE(primes)];
93///
94/// bsl::copy(values.rbegin(),
95/// values.rend(),
96/// bdlb::ArrayUtil::begin(reversePrimes));
97///
98/// assert(bsl::mismatch(bdlb::ArrayUtil::rbegin(primes),
99/// bdlb::ArrayUtil::rend(primes),
100/// bdlb::ArrayUtil::begin(reversePrimes)).second
101/// == bdlb::ArrayUtil::end(reversePrimes));
102/// }
103/// @endcode
104/// After defining the array `reversePrimes` with the same length as `primes`
105/// the elements of `values` are copied in reverse order into this array. The
106/// assertion verifies that `reversePrimes` contains the values from `primes`
107/// but in reverse order: `bsl::mismatch` is used with a reverse sequence of
108/// `primes` by using the `rbegin` and `rend` methods for `primes` and normal
109/// sequence using the `begin` and `end` methods for `reversePrimes`.
110///
111/// ### Example 2: Use with Database Interfaces {#bdlb_arrayutil-example-2-use-with-database-interfaces}
112///
113///
114/// The functions `begin`, `end`, and `size` provided by this component are
115/// similar to functions provided by containers. The main difference is that
116/// they reside in a utility component rather than being member functions.
117///
118/// A typical use case for the `size` function is a function expecting a pointer
119/// to a sequence of keys (e.g., columns in a database) and the number of the
120/// keys in the sequence:
121/// @code
122/// void query(bsl::string *result,
123/// const bsl::string *columns,
124/// size_t numberOfColumns)
125/// {
126///
127/// // Query the database....
128///
129/// }
130///
131/// void loadData(bsl::vector<bsl::string> *data)
132/// {
133/// const bsl::string columns[] = { "column1", "column2", "column3" };
134/// bsl::string result[BDLB_ARRAYUTIL_SIZE(columns)];
135///
136/// query(result, columns, bdlb::ArrayUtil::size(columns));
137/// data->assign(bdlb::ArrayUtil::begin(result),
138/// bdlb::ArrayUtil::end(result));
139/// }
140/// @endcode
141/// The `loadData` function shows how to use the different function templates.
142/// The array `columns` doesn't have a length specified. It is determined from
143/// the number of elements it is initialized with. In this case it is easy to
144/// see that there are three elements but in real situations the number of
145/// elements can be non-trivial to get right. Also, changing the number of
146/// elements would make it necessary to apply the corresponding change in
147/// multiple places. Thus, the length is determined using `bdlb::ArrayUtil`:
148///
149/// * The length of `result` should match the length of `columns`. When
150/// specifying the length of an array a constant expression is necessary. In
151/// C++ 2011 the function `bdlb::ArrayUtil::size` could return a constant
152/// expression but compilers not, yet, implementing the standard a trick must
153/// be used (using `sizeof` with a reference to suitably sized array of
154/// `char`). This trick is packaged into the macro `BDLB_ARRAYUTIL_SIZE()`.
155/// * When the length is needed in a context where a `const` expression is not
156/// required, e.g., when calling `query`, the `bdlb::ArrayUtil::size'
157/// function can be used with the array.
158/// * The `bdlb::ArrayUtil::begin` and `bdlb::ArrayUtil::end` functions are
159/// used to obtain `begin` and `end` iterators used with the vector's
160/// `assign` function to put the `result` obtained from the call to `query`
161/// into the `vector` pointed to by `data`.
162///
163/// Similar needs for an array of a sequence of values frequently arise when
164/// using one of the database interfaces.
165///
166/// Another common use case are test cases where the content of a computed
167/// sequence must be compared with an expected result:
168/// @code
169/// void checkData(const bsl::vector<bsl::string>& data)
170/// {
171/// const bsl::string expect[] = {
172/// // ...
173/// };
174/// assert(data.size() == bdlb::ArrayUtil::size(expect));
175/// assert(bdlb::ArrayUtil::end(expect)
176/// == bsl::mismatch(bdlb::ArrayUtil::begin(expect),
177/// bdlb::ArrayUtil::end(expect),
178/// data.begin()).first);
179/// }
180/// @endcode
181/// In the code below the actual result in `data` is compared to the values in
182/// the array `expect`:
183///
184/// 1. We make sure that the lengths of `data` and `expect` are identical using
185/// `bdlb::ArrayUtil::size`.
186/// 2. The sequences are compared using the `mismatch` algorithm: To get the
187/// begin and of the `expect` array `bdlb::ArrayUtil::begin` and
188/// `bdlb::ArrayUtil::end`, respectively, are used.
189/// @code
190/// void getAndCheckData(bool verbose)
191/// {
192/// if (verbose) cout << "\n" << "'getAndCheckData'" << "\n"
193/// << "=================" << "\n";
194/// bsl::vector<bsl::string> data;
195/// loadData(&data);
196/// checkData(data);
197/// }
198/// @endcode
199/// @}
200/** @} */
201/** @} */
202
203/** @addtogroup bdl
204 * @{
205 */
206/** @addtogroup bdlb
207 * @{
208 */
209/** @addtogroup bdlb_arrayutil
210 * @{
211 */
212
213#include <bdlscm_version.h>
214
215#include <bsl_iterator.h>
216#include <bsl_cstddef.h>
217
218/// Return the number of elements in the passed array `a` as a constant
219/// expression.
220#define BDLB_ARRAYUTIL_SIZE(a) sizeof(BloombergLP::bdlb::ArrayUtil::sizer(a))
221
222/// Return the number of elements in the passed array `a` as a constant
223/// expression.
224#define BDLB_ARRAYUTIL_LENGTH(a) sizeof(BloombergLP::bdlb::ArrayUtil::sizer(a))
225
226
227namespace bdlb {
228 // ====================
229 // struct bdeuArrayUtil
230 // ====================
231
232/// This `struct` provides a namespace for a collection of function
233/// templates providing access to the length and iterators of statically
234/// sized built-in arrays
235struct ArrayUtil {
236
237 // CLASS METHODS
238
239 // ** iterators **
240
241 /// Return an iterator pointing to the first element of the specified
242 /// `array` of template parameter `LENGTH` elements of template
243 /// parameter `TYPE`.
244 template <class TYPE, bsl::size_t LENGTH>
245 static TYPE *begin(TYPE (&array)[LENGTH]);
246
247 /// Return the past-the-end iterator for the specified `array` of
248 /// template parameter `LENGTH` elements of template parameter `TYPE`.
249 template <class TYPE, bsl::size_t LENGTH>
250 static TYPE *end(TYPE (&array)[LENGTH]);
251
252 /// Return a reverse iterator pointing to the last element of the
253 /// specified `array` of template parameter `LENGTH` elements of
254 /// template parameter `TYPE`.
255 template <class TYPE, bsl::size_t LENGTH>
256 static bsl::reverse_iterator<TYPE *> rbegin(TYPE (&array)[LENGTH]);
257
258 /// Return the past-the-end reverse iterator for the specified `array`
259 /// of template parameter `LENGTH` elements of template parameter
260 /// `TYPE`.
261 template <class TYPE, bsl::size_t LENGTH>
262 static bsl::reverse_iterator<TYPE *> rend(TYPE (&array)[LENGTH]);
263
264 // ** size and length **
265
266 /// Return the number of elements in the specified `array` of template
267 /// parameter `LENGTH` elements of template parameter `TYPE`. This
268 /// method is synonymous with the `size` method.
269 template <class TYPE, bsl::size_t LENGTH>
270 static bsl::size_t length(TYPE (&array)[LENGTH]);
271
272 /// Return the number of elements in the specified `array` of template
273 /// parameter `LENGTH` elements of template parameter `TYPE`. This
274 /// method is synonymous with the `length` method.
275 template <class TYPE, bsl::size_t LENGTH>
276 static bsl::size_t size(TYPE (&array)[LENGTH]);
277
278 /// Return a reference to an array of `char`s with the same number of
279 /// elements as the specified `array` of template parameter `LENGTH`
280 /// elements of template parameter `TYPE`. This function is *not*
281 /// implemented and can only be used in a non-evaluated context. The
282 /// function is used together with `sizeof` to obtain a constant
283 /// expression with the `LENGTH` of the `array`. See
284 /// `BDLB_ARRAYUTIL_SIZE` and `BDLB_ARRAYUTIL_LENGTH`.
285 template <class TYPE, bsl::size_t LENGTH>
286 static char (&sizer(TYPE (&array)[LENGTH]))[LENGTH];
287};
288
289// ============================================================================
290// INLINE AND TEMPLATE FUNCTION DEFINITIONS
291// ============================================================================
292
293 // --------------------
294 // struct bdeuArrayUtil
295 // --------------------
296
297// CLASS METHODS
298
299 // ** iterators **
300
301template <class TYPE, bsl::size_t LENGTH>
302inline
303TYPE *ArrayUtil::begin(TYPE (&array)[LENGTH])
304{
305 return array;
306}
307
308template <class TYPE, bsl::size_t LENGTH>
309inline
310TYPE *ArrayUtil::end(TYPE (&array)[LENGTH])
311{
312 return array + LENGTH;
313}
314
315template <class TYPE, bsl::size_t LENGTH>
316inline
317bsl::reverse_iterator<TYPE *> ArrayUtil::rbegin(TYPE (&array)[LENGTH])
318{
319 return bsl::reverse_iterator<TYPE *>(end(array));
320}
321
322template <class TYPE, bsl::size_t LENGTH>
323inline
324bsl::reverse_iterator<TYPE *> ArrayUtil::rend(TYPE (&array)[LENGTH])
325{
326 return bsl::reverse_iterator<TYPE *>(begin(array));
327}
328
329 // ** size and length **
330
331template <class TYPE, bsl::size_t LENGTH>
332inline
333bsl::size_t ArrayUtil::length(TYPE (&)[LENGTH])
334{
335 return LENGTH;
336}
337
338template <class TYPE, bsl::size_t LENGTH>
339inline
340bsl::size_t ArrayUtil::size(TYPE (&)[LENGTH])
341{
342 return LENGTH;
343}
344
345} // close package namespace
346
347
348#endif
349
350// ----------------------------------------------------------------------------
351// Copyright 2015 Bloomberg Finance L.P.
352//
353// Licensed under the Apache License, Version 2.0 (the "License");
354// you may not use this file except in compliance with the License.
355// You may obtain a copy of the License at
356//
357// http://www.apache.org/licenses/LICENSE-2.0
358//
359// Unless required by applicable law or agreed to in writing, software
360// distributed under the License is distributed on an "AS IS" BASIS,
361// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
362// See the License for the specific language governing permissions and
363// limitations under the License.
364// ----------------------------- END-OF-FILE ----------------------------------
365
366/** @} */
367/** @} */
368/** @} */
#define BSLS_IDENT(str)
Definition bsls_ident.h:195
Definition bdlb_algorithmworkaroundutil.h:74
Definition bdlb_arrayutil.h:235
static TYPE * end(TYPE(&array)[LENGTH])
Definition bdlb_arrayutil.h:310
static bsl::reverse_iterator< TYPE * > rend(TYPE(&array)[LENGTH])
Definition bdlb_arrayutil.h:324
static bsl::size_t length(TYPE(&array)[LENGTH])
Definition bdlb_arrayutil.h:333
static bsl::reverse_iterator< TYPE * > rbegin(TYPE(&array)[LENGTH])
Definition bdlb_arrayutil.h:317
static TYPE * begin(TYPE(&array)[LENGTH])
Definition bdlb_arrayutil.h:303
static char(& sizer(TYPE(&array)[LENGTH]))[LENGTH]
static bsl::size_t size(TYPE(&array)[LENGTH])
Definition bdlb_arrayutil.h:340