BDE 4.39.x Production Release
Loading...
Searching...
No Matches
bsls_consteval.h
Go to the documentation of this file.
1
/// @file bsls_consteval.h
2
///
3
/// The content of this file has been pre-processed for Doxygen.
4
///
5
6
7
// bsls_consteval.h -*-C++-*-
8
#ifndef INCLUDED_BSLS_CONSTEVAL
9
#define INCLUDED_BSLS_CONSTEVAL
10
11
#include <
bsls_ident.h
>
12
BSLS_IDENT
(
"$Id: $"
)
13
14
/// @defgroup bsls_consteval bsls_consteval
15
/// @brief Provide macros related to compile-time evaluation.
16
/// @addtogroup bsl
17
/// @{
18
/// @addtogroup bsls
19
/// @{
20
/// @addtogroup bsls_consteval
21
/// @{
22
///
23
/// <h1> Outline </h1>
24
/// * <a href="#bsls_consteval-purpose"> Purpose</a>
25
/// * <a href="#bsls_consteval-macros"> Macros </a>
26
/// * <a href="#bsls_consteval-description"> Description </a>
27
/// * <a href="#bsls_consteval-macro-reference"> Macro Reference </a>
28
/// * <a href="#bsls_consteval-usage"> Usage </a>
29
/// * <a href="#bsls_consteval-example-1-bsls_consteval_constexpr-compute-with-output"> Example 1: BSLS_CONSTEVAL_CONSTEXPR compute with output </a>
30
/// * <a href="#bsls_consteval-example-2-evolving-a-constexpr-function"> Example 2: Evolving a constexpr function </a>
31
///
32
/// # Purpose {#bsls_consteval-purpose}
33
/// Provide macros related to compile-time evaluation.
34
///
35
/// # Macros {#bsls_consteval-macros}
36
///
37
/// - BSLS_CONSTEVAL_CONSTEXPR: `constexpr` if `IS_ACTIVE` defined
38
/// - BSLS_CONSTEVAL_CONSTEXPR_MEMBER: `constexpr` if `IS_ACTIVE`, else `const`
39
/// - BSLS_CONSTEVAL_IS_CONSTANT_EVALUATED: `true` during constant evaluation
40
/// - BSLS_CONSTEVAL_IS_CONSTANT_EVALUATED_IS_ACTIVE: undefined if inactive
41
///
42
/// @see bsls_keyword
43
///
44
/// # Description {#bsls_consteval-description}
45
/// This component provides preprocessor macros that, when
46
/// possible, will identify whether a function is being evaluated at compile
47
/// time. This enables branching to avoid the use of constructs that would not
48
/// be valid to evaluate at compile time. When available, the
49
/// `std::is_constant_evaluated()` function will be used. On some platforms
50
/// where that is unavailable, a compiler intrinsic will be used instead.
51
/// Finally, when no option for this functionality is available, the
52
/// `BSLS_CONSTEVAL_IS_CONSTANT_EVALUATED` macro will expand to `false` and
53
/// `BSLS_CONSTEVAL_IS_CONSTANT_EVALUATED_IS_ACTIVE` will not be defined. To
54
/// ease writing declarations of functions where there is conditionally
55
/// available compile-time behavior, `BSLS_CONSTEVAL_CONSTEXPR` is defined to be
56
/// equivalent to `constexpr` if
57
/// `BSLS_CONSTEVAL_IS_CONSTANT_EVALUATED_IS_ACTIVE` is defined. Note that the
58
/// `BSLS_CONSTEVAL_CONSTEXPR` macro is distinct from the
59
/// `BSLS_KEYWORD_CONSTEXPR*` family in @ref bsls_keyword : the former is defined
60
/// according to whether the Standard Library function (or a suitable intrinsic
61
/// replacement) is available, whereas the latter are defined according to
62
/// which version of the C++ language is enabled.
63
///
64
/// ## Macro Reference {#bsls_consteval-macro-reference}
65
///
66
///
67
/// This section documents the preprocessor macros defined in this component.
68
///
69
/// `BSLS_CONSTEVAL_IS_CONSTANT_EVALUATED`
70
/// This macro expands to `std::is_constant_evaluated()` when it is
71
/// available, or to a compiler intrinsic with equivalent functionality if
72
/// available; otherwise it expands to `false`.
73
///
74
/// `BSLS_CONSTEVAL_IS_CONSTANT_EVALUATED_IS_ACTIVE`
75
/// This macro is defined to `1` if `BSLS_CONSTEVAL_IS_CONSTANT_EVALUATED`
76
/// can be used to identify compile-time evaluation, and is undefined
77
/// otherwise.
78
///
79
/// `BSLS_CONSTEVAL_CONSTEXPR`
80
/// This macro is defined to be `constexpr` if
81
/// `BSLS_CONSTEVAL_IS_CONSTANT_EVALUATED_IS_ACTIVE` is defined; otherwise
82
/// it is defined as empty.
83
///
84
/// `BSLS_CONSTEVAL_CONSTEXPR_MEMBER`
85
/// This macro is defined to be `constexpr` if
86
/// `BSLS_CONSTEVAL_IS_CONSTANT_EVALUATED_IS_ACTIVE` is defined;
87
/// otherwise it is `const`. This should be applied to variables and
88
/// member variables that should be initialized by a function that is
89
/// `BSLS_CONSTEVAL_CONSTEXPR`.
90
///
91
/// ## Usage {#bsls_consteval-usage}
92
///
93
///
94
/// This section illustrates intended use of this component.
95
///
96
/// ## Example 1: BSLS_CONSTEVAL_CONSTEXPR compute with output {#bsls_consteval-example-1-bsls_consteval_constexpr-compute-with-output}
97
///
98
///
99
/// In this simple example, the macros are used to determine when it is
100
/// permissible to log a message to `stdout`.
101
/// @code
102
/// /// Return `23` if the invocation is evaluated at compile time and that
103
/// /// is detectable, otherwise print a diagnostic message to `stdout` and
104
/// /// return `17`.
105
/// BSLS_CONSTEVAL_CONSTEXPR int compute()
106
/// {
107
/// #ifdef BSLS_CONSTEVAL_IS_CONSTANT_EVALUATED_IS_ACTIVE
108
/// if (BSLS_CONSTEVAL_IS_CONSTANT_EVALUATED) {
109
/// return 23; // RETURN
110
/// }
111
/// #endif
112
/// puts("Computing value");
113
/// return 17; // RETURN
114
/// }
115
/// @endcode
116
/// Now we define a `test1` function to invoke `compute` in different contexts.
117
/// This function can be evaluated both at runtime and at compile time without
118
/// errors. Below, this function is evaluated in both cases, and the difference
119
/// in behavior is observed.
120
/// @code
121
/// /// Invoke `compute` in both a const and non-const initialization,
122
/// /// verifying the expected results.
123
/// void test1()
124
/// {
125
/// int i = compute();
126
/// BSLS_CONSTEVAL_CONSTEXPR_MEMBER int j = compute();
127
/// #ifdef BSLS_CONSTEVAL_IS_CONSTANT_EVALUATED_IS_ACTIVE
128
/// ASSERT(17 == i);
129
/// ASSERT(23 == j);
130
/// #else
131
/// ASSERT(17 == i);
132
/// ASSERT(17 == j);
133
/// #endif
134
/// }
135
/// @endcode
136
/// When `17 == i` or `17 == j`, `compute` will write "Computing value\n" to
137
/// `stdout`, so this message will be written once or twice depending on
138
/// whether `BSLS_CONSTEVAL_IS_CONSTANT_EVALUATED_IS_ACTIVE` is defined. The
139
/// variable `j` will always be `const`, and on platforms where the `compute`
140
/// function supports being `constexpr`, i.e. those where it can use
141
/// `BSLS_CONSTEVAL_IS_CONSTANT_EVALUATED` to suppress its use of standard
142
/// output, `j` will also be `constexpr` and its value will be computed at
143
/// compile time.
144
///
145
/// ## Example 2: Evolving a constexpr function {#bsls_consteval-example-2-evolving-a-constexpr-function}
146
///
147
///
148
/// Consider the situation where there are two viable implementations of the
149
/// same algorithm, one of which satisfies the (stringent and pessimizing)
150
/// requirements needed to be a `constexpr` function, the other of which takes
151
/// advantage of runtime optimizations (such as hardware acceleration,
152
/// exceptions, or non-`constexpr` third-party libraries) that are not available
153
/// at compile time on any platform:
154
/// @code
155
/// int runtimeCompute(int input);
156
///
157
/// /// Return a complicated computed value based on the specified `input`.
158
/// BSLS_KEYWORD_CONSTEXPR int compiletimeCompute(int input);
159
/// @endcode
160
/// Assuming these functions were introduced long ago, it is likely they are
161
/// heavily used wherever valid throughout a codebase. The `compiletimeCompute`
162
/// function is likely used to initialize many `const` and `constexpr`
163
/// variables, but also potentially used in many runtime-only expressions, or as
164
/// part of other `constexpr` functions that are themselves sometimes used at
165
/// runtime. The `runtimeCompute` function, similarly, is likely used in many
166
/// contexts that could become `constexpr` or be evaluated at compile time, but
167
/// is hindered due to itself not being `constexpr`.
168
///
169
/// We can begin to transform `compiletimeCompute` and `runtimeCompute` to both
170
/// have improved performance wherever they might be used by moving their
171
/// implementations to separate functions:
172
/// @code
173
/// /// Return a complicated computed value based on the specified `input`.
174
/// int runtimeComputeImpl(int input);
175
///
176
/// /// Return a complicated computed value based on the specified `input`.
177
/// BSLS_KEYWORD_CONSTEXPR int compiletimeComputeImpl(int input);
178
/// @endcode
179
/// Then, for `compiletimeCompute` we can provide a new implementation that will
180
/// use the better runtime algorithm when possible, while remaining `constexpr`
181
/// on all of the platforms where it previously was `constexpr` (i.e., without
182
/// changing its declaration):
183
/// @code
184
/// /// Return a complicated computed value based on the specified `input`.
185
/// BSLS_KEYWORD_CONSTEXPR int compiletimeCompute(int input)
186
/// {
187
/// #ifdef BSLS_CONSTEVAL_IS_CONSTANT_EVALUATED_IS_ACTIVE
188
/// if (!BSLS_CONSTEVAL_IS_CONSTANT_EVALUATED) {
189
/// return runtimeComputeImpl(input); // RETURN
190
/// }
191
/// #endif // BSLS_CONSTEVAL_IS_CONSTANT_EVALUATED_IS_ACTIVE
192
/// return compiletimeComputeImpl(input);
193
/// }
194
/// @endcode
195
/// Now clients using `compiletimeCompute` at runtime, both within and outside
196
/// of other `constexpr` functions, will get the benefits of an improved
197
/// algorithm without any need for change.
198
///
199
/// Similarly, `runtimeCompute` can become opportunistically `constexpr` by
200
/// declaring the function with `BSLS_CONSTEVAL_CONSTEXPR`, which might
201
/// promote some existing evaluations from runtime to compile time on
202
/// platforms that can support it:
203
/// @code
204
/// /// Return a complicated computed value based on the specified `input`.
205
/// BSLS_CONSTEVAL_CONSTEXPR int runtimeCompute(int input)
206
/// {
207
/// #ifdef BSLS_CONSTEVAL_IS_CONSTANT_EVALUATED_IS_ACTIVE
208
/// if (BSLS_CONSTEVAL_IS_CONSTANT_EVALUATED) {
209
/// return compiletimeComputeImpl(input); // RETURN
210
/// }
211
/// #endif // BSLS_CONSTEVAL_IS_CONSTANT_EVALUATED_IS_ACTIVE
212
/// return runtimeComputeImpl(input);
213
/// }
214
/// @endcode
215
/// Clients of `runtimeCompute` can continue to use it at runtime with no
216
/// changes, occasionally getting the benefits of the compile-time algorithm.
217
/// When using `runtimeCompute` to initialize a variable, the compile-time
218
/// behavior can be forced by annotating the variable with
219
/// `BSLS_CONSTEVAL_CONSTEXPR_MEMBER`.
220
///
221
/// With these changes, clients on older platforms can continue to take
222
/// advantage of having optimal algorithms available at both compile time and
223
/// runtime while getting the best available implementation on newer platforms
224
/// that enable the detection of compile-time evaluation.
225
/// @}
226
/** @} */
227
/** @} */
228
229
/** @addtogroup bsl
230
* @{
231
*/
232
/** @addtogroup bsls
233
* @{
234
*/
235
/** @addtogroup bsls_consteval
236
* @{
237
*/
238
239
#include <bsls_compilerfeatures.h>
240
241
#ifdef BSLS_COMPILERFEATURES_SUPPORT_TRAITS_HEADER
242
#include <type_traits>
243
#endif
244
245
#if defined(BSLS_COMPILERFEATURES_SUPPORT_CONSTEXPR_CPP14)
246
#if defined(BSLS_COMPILERFEATURES_SUPPORT_IS_CONSTANT_EVALUATED)
247
#define BSLS_CONSTEVAL_IS_CONSTANT_EVALUATED \
248
std::is_constant_evaluated()
249
#define BSLS_CONSTEVAL_IS_CONSTANT_EVALUATED_IS_ACTIVE 1
250
#elif defined(__has_builtin)
251
#if __has_builtin(__builtin_is_constant_evaluated)
252
#define BSLS_CONSTEVAL_IS_CONSTANT_EVALUATED \
253
__builtin_is_constant_evaluated()
254
#define BSLS_CONSTEVAL_IS_CONSTANT_EVALUATED_IS_ACTIVE 1
255
#endif
// __has_builtin(__builtin_is_constant_evaluated)
256
#endif
// defined(BSLS_COMPILERFEATURES_SUPPORT_IS_CONSTANT_EVALUATED)
257
#endif
// defined BSLS_COMPILERFEATURES_SUPPORT_CONSTEXPR_CPP14
258
259
#if !defined(BSLS_CONSTEVAL_IS_CONSTANT_EVALUATED)
260
#define BSLS_CONSTEVAL_IS_CONSTANT_EVALUATED false
261
#endif
// !defined(BSLS_CONSTEVAL_IS_CONSTANT_EVALUATED)
262
263
#ifdef BSLS_CONSTEVAL_IS_CONSTANT_EVALUATED_IS_ACTIVE
264
#define BSLS_CONSTEVAL_CONSTEXPR constexpr
265
#define BSLS_CONSTEVAL_CONSTEXPR_MEMBER constexpr
266
#else
267
#define BSLS_CONSTEVAL_CONSTEXPR
268
#define BSLS_CONSTEVAL_CONSTEXPR_MEMBER const
269
#endif
270
271
#endif
272
// ----------------------------------------------------------------------------
273
// Copyright 2022 Bloomberg Finance L.P.
274
//
275
// Licensed under the Apache License, Version 2.0 (the "License");
276
// you may not use this file except in compliance with the License.
277
// You may obtain a copy of the License at
278
//
279
// http://www.apache.org/licenses/LICENSE-2.0
280
//
281
// Unless required by applicable law or agreed to in writing, software
282
// distributed under the License is distributed on an "AS IS" BASIS,
283
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
284
// See the License for the specific language governing permissions and
285
// limitations under the License.
286
// ----------------------------- END-OF-FILE ----------------------------------
287
288
/** @} */
289
/** @} */
290
/** @} */
bsls_ident.h
BSLS_IDENT
#define BSLS_IDENT(str)
BSLS_IDENT() - insert string into .comment binary segment (if supported)
Definition
bsls_ident.h:238
doxygen_input
bde
groups
bsl
bsls
bsls_consteval.h
Generated by
1.9.8