BDE 4.39.x Production Release
Loading...
Searching...
No Matches
bsls_util.h
Go to the documentation of this file.
1/// @file bsls_util.h
2///
3/// The content of this file has been pre-processed for Doxygen.
4///
5
6
7// bsls_util.h -*-C++-*-
8#ifndef INCLUDED_BSLS_UTIL
9#define INCLUDED_BSLS_UTIL
10
11#include <bsls_ident.h>
12BSLS_IDENT("$Id: $")
13
14/// @defgroup bsls_util bsls_util
15/// @brief Provide essential, low-level support for portable generic code.
16/// @addtogroup bsl
17/// @{
18/// @addtogroup bsls
19/// @{
20/// @addtogroup bsls_util
21/// @{
22///
23/// <h1> Outline </h1>
24/// * <a href="#bsls_util-purpose"> Purpose</a>
25/// * <a href="#bsls_util-classes"> Classes </a>
26/// * <a href="#bsls_util-macros"> Macros </a>
27/// * <a href="#bsls_util-description"> Description </a>
28/// * <a href="#bsls_util-usage"> Usage </a>
29/// * <a href="#bsls_util-example-1-obtain-the-address-of-a-class-that-defines-operator"> Example 1: Obtain the Address of a class That Defines operator&. </a>
30///
31/// # Purpose {#bsls_util-purpose}
32/// Provide essential, low-level support for portable generic code.
33///
34/// # Classes {#bsls_util-classes}
35///
36/// - bsls::Util: utility class supplying essential, low-level functionality
37///
38/// # Macros {#bsls_util-macros}
39///
40/// - BSLS_UTIL_ADDRESSOF(OBJ): address of `OBJ`, even if `operator&` overloaded
41///
42/// # Description {#bsls_util-description}
43/// This component defines a utility `struct`, `bsls::Util`, that
44/// serves as a namespace for a suite of pure functions that supply essential
45/// low-level support for implementing portable generic facilities such as might
46/// be found in the C++ standard library.
47///
48/// ## Usage {#bsls_util-usage}
49///
50///
51/// This section illustrates intended use of this component.
52///
53/// ### Example 1: Obtain the Address of a class That Defines operator&. {#bsls_util-example-1-obtain-the-address-of-a-class-that-defines-operator}
54///
55///
56/// There are times, especially within low-level library functions, where it is
57/// necessary to obtain the address of an object even if that object's class
58/// overloads `operator&` to return something other than the object's address.
59///
60/// First, we create a special reference-like type that can refer to a single
61/// bit within a byte (inline implementations are provided in class scope for
62/// ease of exposition):
63/// @code
64/// class BitReference {
65///
66/// // DATA
67/// char *d_byte_p;
68/// int d_bitpos;
69///
70/// public:
71/// // CREATORS
72/// BitReference(char *byteptr = 0, int bitpos = 0) // IMPLICIT
73/// : d_byte_p(byteptr)
74/// , d_bitpos(bitpos)
75/// {
76/// }
77///
78/// // ACCESSORS
79/// operator bool() const { return (*d_byte_p >> d_bitpos) & 1; }
80///
81/// char *byteptr() const { return d_byte_p; }
82/// int bitpos() const { return d_bitpos; }
83/// };
84/// @endcode
85/// Then, we create a pointer-like type that can point to a single bit:
86/// @code
87/// class BitPointer {
88///
89/// // DATA
90/// char *d_byte_p;
91/// int d_bitpos;
92///
93/// public:
94/// // CREATORS
95/// BitPointer(char *byteptr = 0, int bitpos = 0) // IMPLICIT
96/// : d_byte_p(byteptr)
97/// , d_bitpos(bitpos)
98/// {
99/// }
100///
101/// // ACCESSORS
102/// BitReference operator*() const
103/// {
104/// return BitReference(d_byte_p, d_bitpos);
105/// }
106///
107/// // etc.
108/// };
109/// @endcode
110/// Next, we overload `operator&` for `BitReference` to return a `BitPointer`
111/// instead of a raw pointer, completing the setup:
112/// @code
113/// inline BitPointer operator&(const BitReference& ref)
114/// {
115/// return BitPointer(ref.byteptr(), ref.bitpos());
116/// }
117/// @endcode
118/// Then, we note that there are times when it might be desirable to get the
119/// true address of a `BitReference`. Since the above overload prevents the
120/// obvious syntax from working, we use `bsls::Util::addressOf` to accomplish
121/// this task.
122///
123/// Next, we create a `BitReference` object:
124/// @code
125/// char c[4];
126/// BitReference br(c, 3);
127/// @endcode
128/// Now, we invoke `bsls::Util::addressOf` to obtain and save the address of
129/// `br`:
130/// @code
131/// BitReference *p = bsls::Util::addressOf(br); // OK
132/// // BitReference *p = &br; // Won't compile
133/// @endcode
134/// Notice that the commented line illustrates canonical use of `operator&` that
135/// would not compile in this example.
136///
137/// Finally, we verify that address obtained is the correct one, running some
138/// sanity checks:
139/// @code
140/// assert(0 != p);
141/// assert(c == p->byteptr());
142/// assert(3 == p->bitpos());
143/// @endcode
144/// @}
145/** @} */
146/** @} */
147
148/** @addtogroup bsl
149 * @{
150 */
151/** @addtogroup bsls
152 * @{
153 */
154/** @addtogroup bsls_util
155 * @{
156 */
157
158#include <bsls_compilerfeatures.h>
159#include <bsls_keyword.h>
160#include <bsls_platform.h>
161
162
163
164namespace bsls {
165
166/// This class template provides an easy way to alias a function pointer
167/// type when used as the return type of a function. The syntax for a
168/// function returning a function pointer is otherwise quite obscure, and
169/// difficult to read. As we want to return function pointers taking
170/// parameters and returning a result specified by template parameters
171/// below, it is not possible to define a simple typedef to the function
172/// type outside the function template itself.
173///
174/// See @ref bsls_util
175template <class TYPE>
177
178 typedef TYPE type; // alias of the template parameter 'TYPE'.
179};
180
181#ifdef BSLS_COMPILERFEATURES_SUPPORT_RVALUE_REFERENCES
182template <class TYPE>
183struct Util_RemoveReference {
184 typedef TYPE type;
185};
186
187template <class TYPE>
188struct Util_RemoveReference<TYPE&> {
189 typedef TYPE type;
190};
191
192template <class TYPE>
193struct Util_RemoveReference<TYPE&&> {
194 typedef TYPE type;
195};
196
197template <class TYPE>
198struct Util_AssertNotLvalue {
199 typedef int type;
200};
201
202template <class TYPE>
203struct Util_AssertNotLvalue<TYPE&> {
204 static_assert(sizeof(typename Util_Identity<TYPE>::type) == 0,
205 "Cannot forward an rvalue as an lvalue.");
206 typedef int type;
207};
208#endif // BSLS_COMPILERFEATURES_SUPPORT_RVALUE_REFERENCES
209
210 // ===========
211 // struct Util
212 // ===========
213
214/// This `struct` provides a namespace for essential low-level functions for
215/// implementing portable generic facilities such as the C++ standard
216/// library.
217///
218/// See @ref bsls_util
219struct Util {
220
221 // CLASS METHODS
222
223 /// Return the address of the specified `obj`, even if `operator&` is
224 /// overloaded for objects of type `BSLS_TYPE`. Behavior is undefined unless `BSLS_TYPE` is an object type.
225 ///
226 /// \note Note that this function
227 /// conforms to the C++11 definition for `addressof` as specified in the
228 /// section [specialized.addressof] (20.6.12.1) of the C++11 standard,
229 /// except that function types, which are not object types, are
230 /// supported by `std::addressof` in C++11.
231 template <class TYPE>
232 static TYPE *addressOf(TYPE& obj);
233
234 /// Return the address of the specified function `fn`.
235 /// \note Note that this
236 /// implementation supports functions of only a limited number of
237 /// parameters, determined by the current needs of the BDE software. A
238 /// more general form that will support an arbitrary number of function
239 /// parameters will be available with C++11.
240 template <class RESULT>
241 static
242 typename Util_Identity<RESULT()>::type *addressOf(RESULT (&fn)());
243 template <class RESULT, class ARG>
244 static
245 typename Util_Identity<RESULT(ARG)>::type *addressOf(RESULT (&fn)(ARG));
246 template <class RESULT, class ARG1, class ARG2>
247 static
248 typename Util_Identity<RESULT(ARG1, ARG2)>::type *addressOf(
249 RESULT (&fn)(ARG1, ARG2));
250
251#ifdef BSLS_COMPILERFEATURES_SUPPORT_RVALUE_REFERENCES
252 template <class TYPE>
253 static
255 TYPE&& forward(typename Util_RemoveReference<TYPE>::type& t)
257
258 /// Return a reference to the specified `t` of non-deduced `TYPE`. If
259 /// `TYPE` is an lvalue-reference type, then the result will be an lvalue-reference, and an rvalue-refernce otherwise.
260 ///
261 /// \note Note that as
262 /// `TYPE` is not deduced, it must be explicitly specified by the caller
263 /// of this function. Also note that while this function may return an
264 /// rvalue-reference, it cannot extend the lifetime of temporaries
265 /// beyond the expression that calls this function; storing an rvalue
266 /// reference to the result will lead to undefined behavior.
267 template <class TYPE>
268 static
270 TYPE&& forward(typename Util_RemoveReference<TYPE>::type&& t)
272#endif // BSLS_COMPILERFEATURES_SUPPORT_RVALUE_REFERENCES
273};
274
275} // close package namespace
276
277 // ======
278 // MACROS
279 // ======
280
281// The following macros are private to the BDE implementation and not intended
282// for widespread use. They support the BDE STL decision for the standard
283// containers to support types that overload 'operator&' only on the Microsoft
284// platform. This support is provided on Microsoft to enable containers
285// holding the 'CComPtr' type from the Microsoft Foundation Class library
286// (which overloads 'operator&'), but is not provided on UNIX platforms to
287// avoid additional template bloat in the 'big' only to support a class design
288// that is almost certainly an error.
289#ifdef BSLS_PLATFORM_CMP_MSVC
290# define BSLS_UTIL_ADDRESSOF(OBJ) ::BloombergLP::bsls::Util::addressOf(OBJ)
291
292# if !defined(BDE_USE_ADDRESSOF)
293# define BDE_USE_ADDRESSOF
294# endif
295#else
296# define BSLS_UTIL_ADDRESSOF(OBJ) (&(OBJ))
297#endif
298
299namespace bsls {
300
301// This macro takes the address of an object by calling 'Util::addressOf' on
302// Windows, and simply taking the address with the '&' operator on all other
303// platforms.
304
305// ============================================================================
306// INLINE FUNCTION DEFINITIONS
307// ============================================================================
308
309// CLASS METHODS
310template <class TYPE>
311inline
312TYPE *Util::addressOf(TYPE& obj)
313{
314 return static_cast<TYPE *>(
315 static_cast<void *>(
316 const_cast<char *>(&reinterpret_cast<const volatile char&>(obj))));
317}
318
319template <class RESULT>
320inline
321typename Util_Identity<RESULT()>::type *
322Util::addressOf(RESULT (&fn)())
323{
324 return fn;
325}
326
327template <class RESULT, class ARG>
328inline
329typename Util_Identity<RESULT(ARG)>::type *
330Util::addressOf(RESULT (&fn)(ARG))
331{
332 return fn;
333}
334
335template <class RESULT, class ARG1, class ARG2>
336inline
337typename Util_Identity<RESULT(ARG1, ARG2)>::type *
338Util::addressOf(RESULT (&fn)(ARG1, ARG2))
339{
340 return fn;
341}
342
343#ifdef BSLS_COMPILERFEATURES_SUPPORT_RVALUE_REFERENCES
344template <class TYPE>
346TYPE&& Util::forward(typename Util_RemoveReference<TYPE>::type& t)
348{
349 return static_cast<TYPE&&>(t);
350}
351
352template <class TYPE>
354TYPE&& Util::forward(typename Util_RemoveReference<TYPE>::type&& t)
356{
357 static_assert(sizeof(typename Util_AssertNotLvalue<TYPE>::type) > 0,
358 "Just to trigger instantiation of the checker template.");
359 return static_cast<TYPE&&>(t);
360}
361#endif // BSLS_COMPILERFEATURES_SUPPORT_RVALUE_REFERENCES
362
363} // close package namespace
364
365
366#endif
367
368// ----------------------------------------------------------------------------
369// Copyright 2013 Bloomberg Finance L.P.
370//
371// Licensed under the Apache License, Version 2.0 (the "License");
372// you may not use this file except in compliance with the License.
373// You may obtain a copy of the License at
374//
375// http://www.apache.org/licenses/LICENSE-2.0
376//
377// Unless required by applicable law or agreed to in writing, software
378// distributed under the License is distributed on an "AS IS" BASIS,
379// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
380// See the License for the specific language governing permissions and
381// limitations under the License.
382// ----------------------------- END-OF-FILE ----------------------------------
383
384/** @} */
385/** @} */
386/** @} */
#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 bdlt_iso8601util.h:707
Definition bsls_util.h:176
TYPE type
Definition bsls_util.h:178
Definition bsls_util.h:219
static TYPE * addressOf(TYPE &obj)
Definition bsls_util.h:312