cpp/language/constant expression

Defines an that can be evaluated at compile time.

Such expressions can be used as non-type template arguments, array sizes, and in other contexts that require constant expressions, e.g.

Core constant expressions
A core constant expression is any expression whose evaluation would not evaluate any one of the following:   the pointer, except in a  that is being evaluated as part of the expression  a control flow that passes through a declaration of a variable with static or thread-local, and unusable in constant expressions  a function call expression that calls a function (or a constructor) that is not declared

 a function call to a constexpr function which is declared, but not defined  a function call to a constexpr function/constructor template instantiation where the instantiation fails to satisfy  requirements.  a function call to a constexpr virtual function, invoked on an object not usable in constant expressions and whose lifetime began outside this expression.  an expression that would exceed the implementation-defined limits  an expression whose evaluation leads to any form of core language undefined behavior (including signed integer overflow, division by zero, pointer arithmetic outside array bounds, etc). Whether standard library undefined behavior is detected is unspecified.

 a  an lvalue-to-rvalue  unless applied to a non-volatile literal-type glvalue that ...  designates an object that is usable in constant expressions,

 refers to a non-volatile object whose lifetime began within the evaluation of this expression   an lvalue-to-rvalue or modification applied to a non-active member of a  or its subobject (even if it shares a common initial sequence with the active member)  an lvalue-to-rvalue implicit conversion on an object <li> an invocation of implicit copy/move constructor/assignment for a union whose active member is mutable (if any), with lifetime beginning outside the evaluation of this expression <li> an assignment expression that would change the active member of a union <li> an referring to a variable or a data member of reference type, unless the reference is usable in constant expressions or its lifetime began within the evaluation of this expression <li> conversion from pointer to to any pointer-to-object type <li> <li> <li> pseudo-destructor call <li> an increment or a decrement operator <li> modification of an object, unless the object has non-volatile literal type and its lifetime began within the evaluation of the expression

<li> a destructor call or pseudo destructor call for an object whose lifetime did not begin within the evaluation of this expression <li> a  expression applied to a glvalue of polymorphic type <li> a <li> a <li> Coroutines: an  or a <li>  a  when the result is unspecified <li> an equality or relational operator whose result is unspecified <li> an assignment or a compound assignment operator <li> a throw expression <li> an <li> an invocation of the va_arg macro, whether an invocation of the va_start macro can be evaluated is unspecified <li> a statement <li> a or  expression that would throw an exception <li> inside a lambda-expression, a reference to or to a variable defined outside that lambda, if that reference would be an odr-use

</ol>

Note: Just being a core constant expression does not have any direct semantic meaning: an expression has to be one of the subsets of constant expressions (see below) to be used in certain contexts.

Constant expression
A constant expression is either
 * core constant expression that refers to
 * an object with static storage duration that is not a temporary, or


 * a function


 * a prvalue core constant expression whose value satisfies the following constraints:
 * if the value is an object of class type, each non-static data member of reference type refers to an entity that satisfies the constraints for above
 * if the value is of pointer type, it holds
 * address of an object with static storage duration
 * address past the end of an object with static storage duration
 * address of a function
 * a null pointer value


 * if the value is an object of class or array type, each subobject satisfies these constraints for values

Integral constant expression
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. If an expression of class type is used where an integral constant expression is expected, the expression is to an integral or unscoped enumeration type.

The following contexts require an integral constant expression:


 * enumeration initializers when the underlying type is not fixed
 * enumeration initializers when the underlying type is not fixed

Converted constant expression
A converted constant expression of type is an expression  to type T, where the converted expression is a constant expression, and the implicit conversion sequence contains only:
 * constexpr user-defined conversions (so a class can be used where integral type is expected)
 * lvalue-to-rvalue conversions
 * integral promotions
 * non-narrowing integral conversions


 * And if any takes place, it is direct binding (not one that constructs a temporary object)

The following contexts require a converted constant expression:
 * when the underlying type is fixed
 * when the underlying type is fixed


 * non-type.

A contextually converted constant expression of type  is an expression,, where the converted expression is a constant expression and the conversion sequence contains only the conversions above.

The following contexts require a contextually converted constant expression of type :



Historical categories
Categories of constant expressions listed below are no longer used in the standard since C++14:


 * A literal constant expression is a prvalue core constant expression of non-pointer literal type (after conversions as required by context). A literal constant expression of array or class type requires that each subobject is initialized with a constant expression.


 * A reference constant expression is an lvalue core constant expression that designates an object with static storage duration or a function.


 * An address constant expression is a prvalue core constant expression (after conversions required by context) of type std or of a pointer type, which points to an object with static storage duration, one past the end of an array with static storage duration, to a function, or is a null pointer.

{{rrev|since=c++17|

Constant subexpression
A constant subexpression is an expression whose evaluation as of an expression  would not prevent  from being a core constant expression, where  is not any of the following expressions:

}}

Usable in constant expressions
In the list above, a variable is usable in constant expressions at a point if


 * the variable is
 * a constexpr variable, or
 * it is a variable
 * of reference type or
 * of const-qualified integral or enumeration type


 * and the definition of the variable is reachable from

An object or reference is usable in constant expressions if it is
 * a variable that is usable in constant expressions, or


 * a string literal object, or
 * a non-mutable subobject or reference member of any of the above, or
 * a temporary object of non-volatile const-qualified literal type whose lifetime is to that of a variable that is usable in constant expressions.

Manifestly constant-evaluated expressions
The following expressions (including conversions to the destination type) are manifestly constant-evaluated:


 * Where a constant expression is grammatically required, including:
 * the dimensions in other than the first
 * non-type
 * expressions in
 * expressions in
 * initializers of
 * non-type
 * expressions in
 * expressions in
 * initializers of
 * initializers of


 * Where a non-constant expression is also accepted, including:
 * initializers of variables with reference type or const-qualified integral or enumeration type, when the initializers are constant expressions
 * initializers of static and thread local variables, when all subexpressions of the initializers (including constructor calls and implicit conversions) are constant expressions (that is, when the initializers are )

Functions and variables needed for constant evaluation
Following expressions or conversions are potentially constant evaluated:
 * manifestly constant-evaluated expressions
 * potentially-evaluated expressions
 * immediate subexpressions of a braced-init-list (constant evaluation may be necessary to determine whether )
 * address-of (unary ) expressions that occur within a (constant evaluation may be necessary to determine whether such an expression is )
 * subexpressions of one of the above that are not a subexpression of a nested

A function is needed for constant evaluation if it is a constexpr function and an expression that is potentially constant evaluated.

A variable is needed for constant evaluation if it is either a constexpr variable or is of non-volatile const-qualified integral type or of reference type and the that denotes it is potentially constant evaluated.

Definition of a defaulted function and instantiation of a specialization  are triggered if the function  is needed for constant evaluation.