Namespaces
Variants

Consteval blocks (since C++26)

From cppreference.com
 
 
C++ language
General topics
Flow control
Conditional execution statements
if
Iteration statements (loops)
for
range-for (C++11)
Jump statements
Functions
Function declaration
Lambda function expression
inline specifier
Dynamic exception specifications (until C++17*)
noexcept specifier (C++11)
Exceptions
Namespaces
Types
Specifiers
const/volatile
decltype (C++11)
auto (C++11)
constexpr (C++11)
consteval (C++20)
constinit (C++20)
Storage duration specifiers
Initialization
Expressions
Alternative representations
Literals
Boolean - Integer - Floating-point
Character - String - nullptr (C++11)
User-defined (C++11)
Utilities
Attributes (C++11)
Types
typedef declaration
Type alias declaration (C++11)
Casts
Memory allocation
Classes
Class-specific function properties
explicit (C++11)
static

Special member functions
Templates
Miscellaneous
 

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:

#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

consteval

See also

defines an aggregate type from a sequence of data member descriptions
(function template) [edit]