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