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>
12BSLS_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/** @} */
#define BSLS_IDENT(str)
Definition bsls_ident.h:195