BDE 4.39.x Production Release
Loading...
Searching...
No Matches
bslma_pointerutil.h
Go to the documentation of this file.
1/// @file bslma_pointerutil.h
2///
3/// The content of this file has been pre-processed for Doxygen.
4///
5
6
7// bslma_pointerutil.h -*-C++-*-
8#ifndef INCLUDED_BSLMA_POINTERUTIL
9#define INCLUDED_BSLMA_POINTERUTIL
10
11#include <bsls_ident.h>
12BSLS_IDENT("$Id: $")
13
14/// @defgroup bslma_pointerutil bslma_pointerutil
15/// @brief Provide utilities for pointer manipulation.
16/// @addtogroup bsl
17/// @{
18/// @addtogroup bslma
19/// @{
20/// @addtogroup bslma_pointerutil
21/// @{
22///
23/// <h1> Outline </h1>
24/// * <a href="#bslma_pointerutil-purpose"> Purpose</a>
25/// * <a href="#bslma_pointerutil-classes"> Classes </a>
26/// * <a href="#bslma_pointerutil-description"> Description </a>
27/// * <a href="#bslma_pointerutil-function-pointers-and-void"> Function Pointers and void </a>
28/// * <a href="#bslma_pointerutil-usage"> Usage </a>
29/// * <a href="#bslma_pointerutil-example-1-using-voidify-for-placement-new"> Example 1: Using voidify for Placement New </a>
30/// * <a href="#bslma_pointerutil-example-2-using-unqualify-for-generic-forwarding"> Example 2: Using unqualify for Generic Forwarding </a>
31///
32/// # Purpose {#bslma_pointerutil-purpose}
33/// Provide utilities for pointer manipulation.
34///
35/// # Classes {#bslma_pointerutil-classes}
36///
37/// - bslma::PointerUtil: namespace for pointer utility functions
38///
39/// # Description {#bslma_pointerutil-description}
40/// This component provides a utility `struct`,
41/// `bslma::PointerUtil`, that serves as a namespace for `static` functions that
42/// perform low-level pointer manipulations useful for implementing portable
43/// generic facilities. `voidify` returns a `void *` from a pointer to a
44/// potentially cv-qualified type, or from a function pointer on platforms that
45/// support the conversion. `unqualify` returns a pointer to the cv-unqualified
46/// version of the pointed-to type, or returns a function pointer unchanged.
47///
48/// ### Function Pointers and void {#bslma_pointerutil-function-pointers-and-void}
49///
50///
51/// Conversion from a pointer-to-function to `void *` requires a
52/// @ref reinterpret_cast and is conditionally-supported behavior in C++17; prior
53/// to C++17 it is undefined behavior. In practice, this conversion is
54/// well-defined on all platforms that BDE is known to support, and is formally
55/// a part of the POSIX Standard.
56///
57/// ## Usage {#bslma_pointerutil-usage}
58///
59///
60/// This section illustrates intended use of this component.
61///
62/// ### Example 1: Using voidify for Placement New {#bslma_pointerutil-example-1-using-voidify-for-placement-new}
63///
64///
65/// Suppose we are implementing a simplified `optional`-like container that
66/// holds a value of (template parameter) `TYPE` in a raw buffer. `TYPE` may
67/// be const-qualified (e.g., `MyOptional<const int>`).
68///
69/// First, we define the class template with an aligned buffer and a flag:
70/// @code
71/// template <class TYPE>
72/// class MyOptional {
73/// // DATA
74/// union {
75/// bsls::AlignmentUtil::MaxAlignedType d_align;
76/// char d_buf[sizeof(TYPE)];
77/// };
78/// bool d_hasValue;
79///
80/// public:
81/// // CREATORS
82/// MyOptional() : d_hasValue(false) {}
83///
84/// // MANIPULATORS
85///
86/// /// Construct a `TYPE` object in this object's buffer having its
87/// /// default value, and return a reference to the newly created
88/// /// object.
89/// TYPE& emplace();
90///
91/// // ACCESSORS
92/// bool hasValue() const { return d_hasValue; }
93/// const TYPE& value() const
94/// {
95/// return *reinterpret_cast<const TYPE *>(d_buf);
96/// }
97/// };
98/// @endcode
99/// Then we implement `emplace`. We declare a pointer of the correct type to
100/// the return value so that we can efficiently return a reference to the object
101/// we are about to create.
102/// @code
103/// template <class TYPE>
104/// TYPE& MyOptional<TYPE>::emplace()
105/// {
106/// BSLS_ASSERT(!d_hasValue);
107///
108/// TYPE *addr = reinterpret_cast<TYPE *>(d_buf);
109/// @endcode
110/// Now, we use `voidify` to provide the address at which to construct the new
111/// object. A placement-new expression requires a `void *` operand, but `TYPE`
112/// may be cv-qualified and @ref static_cast alone cannot produce `void *` from a
113/// pointer to a cv-qualified type.
114/// @code
115/// addr = ::new (bslma::PointerUtil::voidify(addr)) TYPE();
116/// d_hasValue = true;
117/// return *addr;
118/// }
119/// @endcode
120/// Finally, we can use `MyOptional` with a const-qualified type. Without
121/// `voidify`, the placement new inside `emplace` would not compile:
122/// @code
123/// MyOptional<const int> opt;
124/// const int& ref = opt.emplace();
125/// assert(opt.hasValue());
126/// assert(0 == ref);
127/// @endcode
128///
129/// ### Example 2: Using unqualify for Generic Forwarding {#bslma_pointerutil-example-2-using-unqualify-for-generic-forwarding}
130///
131///
132/// Suppose we are given a construction facility that constructs an object of
133/// (template parameter) `TYPE` at a specified address having its default
134/// value, and returns a pointer to the newly created object:
135/// @code
136/// /// Construct an object of the specified (template parameter) `TYPE` at
137/// /// the specified `address` having its default value, and return
138/// /// `address`.
139/// template <class TYPE>
140/// TYPE *constructInPlace(TYPE *address);
141/// @endcode
142/// When forwarding to such a facility from our own generic code, we can strip
143/// any cv-qualification with `unqualify` so that the downstream facility is
144/// always invoked with the unqualified type, avoiding a redundant template
145/// instantiation for each cv-variant of the same underlying type across the
146/// entire program. Casting away `const` is well-defined when the underlying
147/// storage was not originally declared `const` -- as is typical for raw buffers
148/// managed by containers and allocators. Observe that the `int *` returned by
149/// `constructInPlace` implicitly converts to `const int *` or `volatile int *`
150/// when assigned back, correctly preserving the original cv-qualification:
151/// @code
152/// union {
153/// bsls::AlignmentUtil::MaxAlignedType d_align;
154/// char d_buf[sizeof(int)];
155/// } u = {};
156/// int *ip = reinterpret_cast<int *>(u.d_buf);
157/// const int *cp = reinterpret_cast<const int *>(u.d_buf);
158/// volatile int *vp = reinterpret_cast<volatile int *>(u.d_buf);
159///
160/// ip = constructInPlace(bslma::PointerUtil::unqualify(ip));
161/// assert(0 == *ip);
162///
163/// cp = constructInPlace(bslma::PointerUtil::unqualify(cp));
164/// assert(0 == *cp);
165///
166/// vp = constructInPlace(bslma::PointerUtil::unqualify(vp));
167/// assert(0 == *vp);
168/// @endcode
169/// @}
170/** @} */
171/** @} */
172
173/** @addtogroup bsl
174 * @{
175 */
176/** @addtogroup bslma
177 * @{
178 */
179/** @addtogroup bslma_pointerutil
180 * @{
181 */
182
183#include <bslscm_version.h>
184
186#include <bslmf_isfunction.h>
187
189#include <bsls_keyword.h>
190#include <bsls_platform.h>
191
192
193namespace bslma {
194
195 // ==================
196 // struct PointerUtil
197 // ==================
198
199/// This `struct` provides a namespace for utility functions that perform
200/// low-level pointer manipulations.
201///
202/// See @ref bslma_pointerutil
204 // CLASS METHODS
205
206 /// Return the specified `address` cast to a pointer to the
207 /// cv-unqualified form of the (template parameter) `TYPE`; if `TYPE` is a
208 /// function type, `address` is returned unchanged.
209#ifdef BSLS_PLATFORM_CMP_SUN
210 template <class TYPE>
211 static TYPE *unqualify(const volatile TYPE *address);
212#else
213 template <class TYPE>
215 TYPE *address) BSLS_KEYWORD_NOEXCEPT;
216 template <class TYPE>
218 const TYPE *address) BSLS_KEYWORD_NOEXCEPT;
219 template <class TYPE>
221 volatile TYPE *address) BSLS_KEYWORD_NOEXCEPT;
222 template <class TYPE>
224 const volatile TYPE *address) BSLS_KEYWORD_NOEXCEPT;
225#endif
226
227 /// Return the specified `address` cast to `void *`, stripping any cv-qualification from the (template parameter) `TYPE`.
228 ///
229 /// \note Note that if
230 /// `TYPE` is a function type, the conversion relies on conditionally-
231 /// supported behavior (see {Function Pointers and `void *`}).
232 template <class TYPE>
233 static BSLS_KEYWORD_CONSTEXPR void *voidify(TYPE *address)
235
236 private:
237 // PRIVATE CLASS METHODS
238
239#ifdef BSLS_PLATFORM_CMP_SUN
240 /// Return the specified `address` cast to a pointer to the
241 /// cv-unqualified form of `TYPE`. The `bsl::false_type` tag indicates
242 /// that `TYPE` is not a function type.
243 template <class TYPE>
244 static TYPE *unqualify(const volatile TYPE *address, bsl::false_type);
245
246 /// Return the specified `address` unchanged. The `bsl::true_type` tag
247 /// indicates that `TYPE` is a function type.
248 template <class TYPE>
249 static TYPE *unqualify(const volatile TYPE *address, bsl::true_type);
250#endif
251
252#ifndef BSLS_COMPILERFEATURES_SUPPORT_CONSTEXPR_CPP17
253 /// Return the specified `address` cast to `void *`, stripping any cv-
254 /// qualification from `TYPE`. The `bsl::false_type` tag indicates that
255 /// `TYPE` is not a function type.
256 template <class TYPE>
257 static BSLS_KEYWORD_CONSTEXPR void *voidify(TYPE *address, bsl::false_type)
259
260 /// Return the specified `address` cast to `void *`. The `bsl::true_type`
261 /// tag indicates that `TYPE` is a function type; see {Function Pointers
262 /// and `void *`}.
263 template <class TYPE>
264 static void *voidify(TYPE *address, bsl::true_type) BSLS_KEYWORD_NOEXCEPT;
265#endif
266};
267
268// ============================================================================
269// INLINE DEFINITIONS
270// ============================================================================
271
272 // ------------------
273 // struct PointerUtil
274 // ------------------
275
276// CLASS METHODS
277#ifdef BSLS_PLATFORM_CMP_SUN
278template <class TYPE>
279inline
280TYPE *PointerUtil::unqualify(const volatile TYPE *address)
281{
282 return unqualify(address, bsl::is_function<TYPE>());
283}
284
285template <class TYPE>
286inline
287TYPE *PointerUtil::unqualify(const volatile TYPE *address, bsl::false_type)
288{
289 return const_cast<TYPE *>(address);
290}
291
292template <class TYPE>
293inline
294TYPE *PointerUtil::unqualify(const volatile TYPE *address, bsl::true_type)
295{
296 return address;
297}
298#else
299template <class TYPE>
300inline
303{
304 return address;
305}
306
307template <class TYPE>
308inline
311{
312 return const_cast<TYPE *>(address);
313}
314
315template <class TYPE>
316inline
319{
320 return const_cast<TYPE *>(address);
321}
322
323template <class TYPE>
324inline
326 const volatile TYPE *address)
328{
329 return const_cast<TYPE *>(address);
330}
331#endif
332
333#ifdef BSLS_COMPILERFEATURES_SUPPORT_CONSTEXPR_CPP17
334template <class TYPE>
335inline
336constexpr void *PointerUtil::voidify(TYPE *address) noexcept
337{
338 if constexpr (bsl::is_function_v<TYPE>) {
339 // See {Function Pointers and 'void *'}.
340
341 return reinterpret_cast<void *>(address); // RETURN
342 }
343 else {
344 return unqualify(address); // RETURN
345 }
346}
347#else
348template <class TYPE>
349inline
352{
353 return voidify(address, bsl::is_function<TYPE>());
354}
355
356// PRIVATE CLASS METHODS
357template <class TYPE>
358inline
362{
363 return unqualify(address);
364}
365
366template <class TYPE>
367inline
369{
370 // See {Function Pointers and 'void *'}.
371
372 return reinterpret_cast<void *>(address);
373}
374#endif
375
376} // close package namespace
377
378
379#endif
380
381// ----------------------------------------------------------------------------
382// Copyright 2026 Bloomberg Finance L.P.
383//
384// Licensed under the Apache License, Version 2.0 (the "License");
385// you may not use this file except in compliance with the License.
386// You may obtain a copy of the License at
387//
388// http://www.apache.org/licenses/LICENSE-2.0
389//
390// Unless required by applicable law or agreed to in writing, software
391// distributed under the License is distributed on an "AS IS" BASIS,
392// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
393// See the License for the specific language governing permissions and
394// limitations under the License.
395// ----------------------------- END-OF-FILE ----------------------------------
396
397/** @} */
398/** @} */
399/** @} */
#define BSLS_IDENT(str)
BSLS_IDENT() - insert string into .comment binary segment (if supported)
Definition bsls_ident.h:238
#define BSLS_KEYWORD_CONSTEXPR
Definition bsls_keyword.h:624
#define BSLS_KEYWORD_NOEXCEPT
Definition bsls_keyword.h:674
Definition baljsn_encoder_testtypes.h:76
Definition bslmf_integralconstant.h:261
Definition bslmf_isfunction.h:232
Definition bslma_pointerutil.h:203
static BSLS_KEYWORD_CONSTEXPR void * voidify(TYPE *address) BSLS_KEYWORD_NOEXCEPT
Definition bslma_pointerutil.h:350
static BSLS_KEYWORD_CONSTEXPR TYPE * unqualify(TYPE *address) BSLS_KEYWORD_NOEXCEPT
Definition bslma_pointerutil.h:301