Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.syntblaze.com/llms.txt

Use this file to discover all available pages before exploring further.

A consteval function, introduced in C++20, is an immediate function that is strictly guaranteed to be evaluated at compile-time. Unlike constexpr, which acts as a dual-purpose function capable of both compile-time and runtime evaluation, a consteval function mandates that every invocation produces a valid constant expression, unless the invocation occurs within an immediate function context. If the compiler cannot evaluate the function at compile-time outside of such a context, the program is ill-formed and will result in a compilation error.

Syntax

The consteval specifier is placed in the function declaration, preceding the return type.
consteval return_type function_name(parameters) {
    // function body
}

Core Mechanics and Constraints

To qualify as an immediate function, a consteval function must adhere to strict structural and contextual rules:
  • Constant Expression Requirement & Immediate Function Context: Outside of an immediate function context, every call to a consteval function must yield a compile-time constant, meaning all arguments passed to it must be constant expressions. However, within an immediate function context (such as the body of another consteval function or an immediate-escalating function), this restriction is lifted. In this context, a consteval function can freely call other consteval functions using its own runtime parameters. This exemption is critical for composing immediate functions without requiring intermediate variables to be strictly constexpr.
  • Type Requirements: While C++20 strictly mandated that both the return type and all parameter types be literal types, C++23 (via P2448R2) relaxed this rule. Parameter and return types are no longer required to be literal types at the declaration level, though the function must still be capable of producing a constant expression during actual evaluation.
  • Implicit Inline: A consteval function is implicitly inline.
  • Address Restrictions: You cannot take the address of a consteval function, nor can you form a pointer or reference to it, unless the context in which you are doing so is an immediate function context.
  • Prohibited Contexts: A consteval function cannot be a destructor, a coroutine, or an allocation/deallocation function. Note that while C++20 introduced constexpr destructors, the standard explicitly forbids destructors from being declared consteval.
  • Body Restrictions: The function body is subject to the same restrictions as a constexpr function. Uninitialized variables are permitted provided they are not read before being initialized. As of C++23, the body may also contain goto statements, labels, and definitions of variables of non-literal types, strictly provided that the specific code paths containing these constructs are not executed during constant evaluation.

consteval vs. constexpr

The distinction between constexpr and consteval lies in the strictness of the evaluation context:
  • constexpr: Indicates that a function can be evaluated at compile-time if provided with constant expressions. If provided with runtime variables, it degrades to a standard runtime function.
  • consteval: Indicates that a function must be evaluated at compile-time. It has no runtime equivalent and will never generate runtime machine code for the function call itself.

Evaluation Behavior and Composition

The following code block demonstrates the strict evaluation rules and the mechanics of the immediate function context:
consteval int compute_multiplier(int a, int b) {
    return a * b;
}

consteval int compose_computation(int x, int y) {
    // Valid: This is an immediate function context.
    // 'x' and 'y' are not constant expressions themselves, but passing 
    // them to another consteval function is perfectly legal here.
    return compute_multiplier(x, y) + 10;
}

int main() {
    // Valid: Both arguments are literal constants. Evaluated at compile-time.
    constexpr int result1 = compose_computation(5, 10); 
    
    // Valid: The result can be assigned to a non-constexpr variable, 
    // but the function execution still occurs entirely at compile-time.
    int result2 = compose_computation(4, 8); 

    int runtime_val = 5;
    
    // Ill-formed: 'runtime_val' is not a constant expression, and this call 
    // is not inside an immediate function context.
    // int result3 = compute_multiplier(runtime_val, 10); // Compilation Error
    
    return 0;
}

Immediate Escalation (C++23 Context)

Introduced in C++23, immediate escalation is a mechanism where specific functions automatically promote to consteval (immediate functions) if they invoke an immediate function in a way that cannot be evaluated at compile-time (e.g., using non-constant arguments). Crucially, not all functions escalate. Escalation is strictly limited to immediate-escalating functions, which are defined as:
  1. Functions resulting from the instantiation of a parameterized entity (such as a function template or a member of a class template) defined with the constexpr specifier. A standard, non-constexpr parameterized entity will not escalate and will produce a hard compilation error if it invokes a consteval function with non-constant arguments.
  2. Lambdas (specifically, the closure type’s operator(), provided it is not explicitly declared consteval).
  3. Defaulted special member functions that are not explicitly declared with the constexpr specifier. If a defaulted special member function is explicitly declared constexpr, it behaves like a standard constexpr function and does not escalate.
If one of these eligible functions invokes a consteval function with non-constant arguments, it escalates to consteval itself, propagating the strict compile-time evaluation requirement up the call stack. A standard, non-templated constexpr function is never an immediate-escalating function. This strict boundary exists to prevent silent ABI and API breaks that would occur if a standard function signature implicitly changed its linkage and runtime availability.
Master C++ with Deep Grasping Methodology!Learn More