Consteval blocks (since C++26)
Executes statements at compile time.
Syntax
consteval compound-statement
|
|||||||||
| compound-statement | - | a compound statement |
Explanation
A consteval block can appear anywhere a declaration can appear. When a consteval block is compiled (formally, when it's analyzed and translated), or when the enclosing template is instantiated, the compound statement is executed as if it were the body of an immediately-invoked, static, consteval lambda with no captures and a return type of void, except that:
- The execution of the compound statement may have side effects, such as producing injected declarations by calling std::meta::define_aggregate.
- The variable __func__ is not declared in this lambda.
- The scope of this lambda function is transparent to reflection functions such as std::meta::current_function and std::meta::parent_of.
#include <meta>
void outer_func()
{
consteval
{
constexpr auto fn = std::meta::current_function();
static_assert(fn == ^^outer_func);
}
}
The compound statement may contain return statements to exit the consteval block early.
Let C be a consteval block, and E be an entity declared by an injected declaration produced by the evaluation of C. The program is ill-formed if:
- C is enclosed by the scope of E or
- letting P be a point whose immediate scope is that to which E belongs, there is a function parameter scope or class scope that encloses exactly one of C or P.
Injected declarations
A declaration may be injected as a side effect of evaluating a constant expression.
The side effect takes place after the entire constant expression has been evaluated. If the consteval block is a member declaration, the side effect takes place before the semantic analysis of the complete-class context.
struct A;
consteval
{
std::meta::define_aggregate(^^A, {});
A a; // error, A is incomplete
}
A a; // OK
struct B
{
struct Mem;
void f() { Mem m; } // OK, function body is a complete-class context
consteval { std::meta::define_aggregate(^^Mem, {}); }
}
Each injected declaration is associated with a synthesized point, from which only the injected declaration is reachable. The synthesized point is part of the evaluation context. That is, after a function call that produces an injected declaration, that declaration is visible to reflection functions during the evaluation of the current constant expression. However, the synthesized point is not part of the evaluation context of a nested constant expression.
struct A;
consteval
{
std::meta::define_aggregate(^^A, {}); // #1
bool x = std::meta::is_complete_type(^^A);
// x is true: the injected declaration #1 is reachable
constexpr bool y = std::meta::is_complete_type(^^A);
// y is false: #1 is not reachable in its initialization
}
Each injected declaration has an associated characteristic sequence, which is the data member descriptions in the std::meta::define_aggregate call. If an entity is defined by an injected declaration, its definitions in different translation units must be injected declarations with the same characteristic sequence.
Notes
| Feature-test macro | Value | Std | Feature |
|---|---|---|---|
__cpp_impl_reflection |
202506L |
(C++26) | Reflection |
Keywords
See also
(C++26) |
defines an aggregate type from a sequence of data member descriptions (function template) |