User:Runge
C++ user and leaner.
Contents |
Explanation of immediate-*
An immediate function F is either:
- a function declared with consteval specifier, or
- is escalated from a immediate-escalating function (see below) which contains (at least) an immediate-escalating expression (see below) immediately . To be precise, there's an immediate-escalating expression
EinsideF's function body such thatE's innermost enclosing non-block scope isF's function parameter scope.
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
|
(since C++23) |
An immediate-escalating function is a function that possibly be escalated to become an immediate function. It's either:
- the call operator of a lambda that is not declared with the consteval specifier, or
- a defaulted special member function that is not declared with the consteval specifier, or
- a function that results from the instantiation of a templated entity defined with the constexpr specifier.
Roughly speaking, an immediate-escalating expression is a expression E which 1) needs to be evaluated in an immediate function context but initially not in, and 2) which is contained by a immediate-escalating function F. Hence, this makes F an immediate function (according to the second bullet of immediate function) and makes E in an immediate function context (according to the first bullet of immediate function context). Through this argument, consteval could propagate up, or in other word, such expression colors its enclosing (immediate-escalating) function consteval.
To be precise, a expression is an immediate-escalating expression if it is not initially in an immediate function context and it is either:
- a potentially-evaluated id-expression that denotes an immediate function that is not a subexpression of an immediate invocation (see below), or
- an immediate invocation (see below) that is not a constant expression and is not a subexpression of an immediate invocation.
Notably, if an invocation of an immediate function already has already formed a constant expression or inside an immediate invocation expression, then the id-expression of a immediate function in such invocation will not make it an immediate-escalating expression.
And an immediate-escalating expression shall appear only in an immediate-escalating function. Or in other word, it needs to be invoked inside an immediate function context, if it is unable to color its enclosing function with consteval through immediate-escalating mechanism, then such invocation results in a compile-time error.
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, or
- an aggregate initialization that evaluates a default member initializer with a subexpression that is an immediate-escalating expression.
consteval int id(int i) { return i; } // immediate function constexpr char id(char c) { return c; } // non immediate template<class T> constexpr int f(T t) { // its instantiation forms an immediate-escalating function return t + id(t); } auto a = &f<char>; // OK, since char id(char) is not an immediate function, // there's no immediate invocation inside f's function body. // f<char> will not be escalated. // auto b = &f<int>; // error: f<int> is an immediate function since `id(t)` is now a // immediate invocation due to now id references to an immediate function // int id(int), then f<int> is escalated to be an immediate function. static_assert(f(3) == 6); // OK, invocation of an immediate function inside // a manifestly constant evaluated context template<class T> constexpr int g(T t) { // its instantiation forms an immediate-escalating function, return t + id(42); // but g<int> is not an immediate function because } // id(42) is already a constant expression template<class T, class F> constexpr bool is_not(T t, F f) { // its instantiation forms an immediate-escalating function return not f(t); } consteval bool is_even(int i) { return i % 2 == 0; } // immediate function static_assert(is_not(5, is_even)); // OK, is_even denote an immediate function and // is_not<int, bool(*)(int)> is escalated to be an immediate function int x = 0; template<class T> constexpr T h(T t = id(x)) { // h<int> is not an immediate function // id(x) is not evaluated when parsing the default argument ([dcl.fct.default], [temp.inst]) return t; } template<class T> constexpr T hh() { // hh<int> is an immediate function because of the invocation return h<T>(); // of the immediate function id in the default argument of h<int> } int i = hh<int>(); // error: hh<int>() is an immediate-escalating expression // outside of an immediate-escalating function struct A { int x; int y = id(x); }; template<class T> constexpr int k(int) { // k<int> is not an immediate function because A(42) is a return A(42).y; // constant expression and thus not immediate-escalating }
Immediate invocation
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, or
- an aggregate initialization that evaluates a default member initializer with a subexpression that is an immediate-escalating expression.
Immediate function
An immediate function is a function that is:
- declared with the consteval specifier,or
- an immediate-escalating function
Fwhose function body contains an immediate-escalating expressionEsuch thatE's innermost enclosing non-block isF's function parameter scope.
Immediate function context
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
|
(since C++23) |
Immediate-escalating function
An immediate-escalating function is:
- the call operator of a lambda that is not declared with the consteval specifier, or
- a defaulted special member function that is not declared with the consteval specifier, or
- a function that results from the instantiation of a templated entity defined with the constexpr specifier.
Immediate-escalating expression
An expression or conversion is immediate-escalating if it is not initially in an immediate function context and it is either:
- a potentially-evaluated id-expression that denotes an immediate function that is not a subexpression of an immediate invocation, or
- an immediate invocation that is not a constant expression and is not a subexpression of an immediate invocation.
An immediate-escalating expression shall appear only in an immediate-escalating function.
Examples: TBD.