[expr.const.imm]
7 Expressions [expr]
7.7 Constant evaluation [expr.const]
7.7.5 Immediate functions [expr.const.imm]
An expression or conversion is in an immediate function context if it is potentially evaluated and either:
- its innermost enclosing non-block scope is a function parameter scope of an immediate function,
- it is a subexpression of a manifestly constant-evaluated expression or conversion, or
- its enclosing statement is enclosed ([stmt.pre]) by the compound-statement of a consteval if statement ([stmt.if]).
An invocation is an immediate invocation if it is a potentially evaluated explicit or implicit invocation of an immediate function and is not in an immediate function context.
An aggregate initialization is an immediate invocation if it evaluates a default member initializer that has a subexpression that is an immediate-escalating expression.
A potentially evaluated expression or conversion is immediate-escalating if it is neither initially in an immediate function context nor a subexpression of an immediate invocation, and
- it is an id-expression or splice-expression that designates an immediate function,
- it is an immediate invocation that is not a constant expression, or
- it is of consteval-only type ([basic.types.general]).
An immediate-escalating function is
- the call operator of a lambda that is not declared with the consteval specifier,
- a non-user-provided defaulted function that is not declared with the consteval specifier, or
- a function that is not a prospective destructor and that results from the instantiation of a templated entity defined with the constexpr specifier.
An immediate-escalating expression shall appear only in an immediate-escalating function.
An immediate function is a function that is
- declared with the consteval specifier,
- an immediate-escalating function whose type is consteval-only ([basic.types.general]), or
- an immediate-escalating function F
whose function body contains either
- an immediate-escalating expression or
- a definition of a non-constexpr variable with consteval-only type
[Example 1: consteval int id(int i) { return i; } constexpr char id(char c) { return c; } template<class T> constexpr int f(T t) { return t + id(t); } auto a = &f<char>; auto b = &f<int>; static_assert(f(3) == 6); template<class T> constexpr int g(T t) { return t + id(42); } template<class T, class F> constexpr bool is_not(T t, F f) { return not f(t); } consteval bool is_even(int i) { return i % 2 == 0; } static_assert(is_not(5, is_even)); int x = 0; template<class T> constexpr T h(T t = id(x)) { return t; } template<class T> constexpr T hh() { return h<T>(); } int i = hh<int>(); struct A { int x; int y = id(x); }; template<class T> constexpr int k(int) { return A(42).y; } constexpr int l(int c) pre(c >= 2) { return (c % 2 == 0) ? c / 0 : c; } const int i0 = l(0); const int i1 = l(1); const int i2 = l(2); const int i3 = l(3); — end example]