7 Expressions [expr]

7.7 Constant evaluation [expr.const]

7.7.3 Constant expressions [expr.const.const]

A consteval-only value is either
  • a reflection value ([basic.fundamental]) that is not the null reflection value or
  • a pointer or pointer-to-member that points to an immediate function or to or past the end of an immediate object.
An object is an immediate object if its complete object has
  • a constituent value that is consteval-only or
  • a constituent reference that refers to an immediate object or immediate function.
Every immediate object shall be
  • the object associated with a constexpr variable or a subobject thereof,
  • a template parameter object ([temp.param]) or a subject thereof, or
  • an object whose lifetime begins and ends during the evaluation of a core constant expression.
[Example 1: consteval int plus1(int x) { return x + 1; } template <auto V> struct C {}; auto a = plus1; // error: immediate object not associated with constexpr variable constexpr auto b = plus1; // OK auto c = C<plus1>(); // OK auto d = ^^int; // error: immediate object not associated with constexpr variable auto e = C<^^char>(); // OK — end example]
Each expression E that odr-uses a variable that declares or refers to an immediate object shall be in an immediate function context; a diagnostic is required only if either
  • the innermost declaration that contains E or
  • the defining declaration of the variable
is reachable from the other.
A core constant expression is a constant expression unless it is a prvalue whose result object ([basic.lval]) has a constituent value that is an invalid pointer value ([basic.compound]) or is indeterminate or erroneous ([basic.indet]).
A constant expression is an immediate constant expression if it is either
  • a glvalue that refers to an immediate object or an immediate function, or
  • a prvalue whose result object (if any) is an immediate object.
[Note 1: 
A glvalue core constant expression that either refers to or points to an unspecified object is not a constant expression.
— end note]
[Example 2: consteval int f() { return 42; } consteval auto g() { return f; } consteval int h(int (*p)() = g()) { return p(); } constexpr int r = h(); // OK constexpr auto e = g(); // error: a pointer to an immediate function is // not a permitted result of a constant expression struct S { int x; constexpr S() {} }; int i() { constexpr S s; // error: s.x has erroneous value } — end example]
An integral constant expression is an expression of integral or unscoped enumeration type, implicitly converted to a prvalue, where the converted expression is a core constant expression.
[Note 2: 
Such expressions can be used as bit-field lengths ([class.bit]), as enumerator initializers if the underlying type is not fixed ([dcl.enum]), and as alignments.
— end note]
If an expression of literal class type is used in a context where an integral constant expression is required, then that expression is contextually implicitly converted ([conv]) to an integral or unscoped enumeration type and the selected conversion function shall be constexpr.
[Example 3: struct A { constexpr A(int i) : val(i) { } constexpr operator int() const { return val; } constexpr operator long() const { return 42; } private: int val; }; constexpr A a = alignof(int); alignas(a) int n; // error: ambiguous conversion struct B { int n : a; }; // error: ambiguous conversion — end example]
A converted constant expression of type T is an expression, implicitly converted to type T, where the converted expression is a constant expression and the implicit conversion sequence contains only and where the reference binding (if any) binds directly.
[Note 3: 
Such expressions can be used in new expressions ([expr.new]), as case expressions ([stmt.switch]), as enumerator initializers if the underlying type is fixed ([dcl.enum]), as array bounds ([dcl.array]), as constant template arguments ([temp.arg]), and as the constant expression of a splice-specifier ([basic.splice]).
— end note]
A contextually converted constant expression of type bool is an expression, contextually converted to bool ([conv]), where the converted expression is a constant expression and the conversion sequence contains only the conversions above.