Constant expressions

From cppreference.com
< cpp‎ | language

Defines an expression 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.

int n = 1;
std::array<int, n> a1; // error, n is not a constant expression
const int cn = 2;
std::array<int, cn> a2; // OK, cn is a constant expression

Contents

[edit] Core constant expressions

A core constant expression is any expression that does not have any one of the following in any subexpression (ignoring the unevaluated arguments of &&, ||, and ?:)

1) A function call expression that calls a function (or a constructor) that is not declared constexpr
constexpr int n = std::numeric_limits<int>::max(); // OK, max() is constexpr
constexpr int m = std::time(NULL); // Error: std::time() is not constexpr
2) A function call to a constexpr function which is declared, but not defined, if the function call itself is not made inside the body of a constexpr function.
3) A function call to a constexpr function with arguments that do not produce a constant expression when substituted
constexpr const int* addr(const int& ir) { return &ir; }
static const int x = 5;
constexpr const int* xp = addr(x); // OK
constexpr const int* tp = addr(5); // error: &5 is not a constant expression
4) A function call to a constexpr function with arguments that do not produce constant expressions in member-initializer lists that are called from this function
int x;
struct A {
    constexpr A(bool b) : m(b?42:x) { }
    int m;
};
constexpr int v = A(true).m; // OK
constexpr int w = A(false).m; // error: non-const x
5) A function call to a recursive constexpr function that would exceed compile-time recursion depth limit (implementation-defined)
6) The this pointer except if used for class member access inside a non-static member function.
7) An expression whose result is not mathematically defined or is out of range for its type.
constexpr double d1 = 2.0/1.0; // OK
constexpr double d2 = 2.0/0.0; // Error: not defined
constexpr int n = std::numeric_limits<int>::max() + 1; // Error: overflow
(until C++14)
7) An expression whose evaluation leads to any form of core language (since C++17) undefined behavior (including signed integer overflow, division by zero, pointer arithmetic outside array bounds, etc). Whether standard library undefined behavior is detected is unspecified. (since C++17)
(since C++14)
9) An lvalue-to-rvalue implicit conversion applied to a non-active member of a union or its subobject
10) Any other lvalue-to-rvalue implicit conversion, unless the lvalue...
a) has integral or enumeration type and refers to a complete non-volatile const object, which is initialized with a constant expression
b) is a non-volatile glvalue that refers to an element of a string literal
c) has literal type and refers to a non-volatile object defined with constexpr or to its non-mutable subobject
d) has literal type and refers to a non-volatile temporary, initialized with a constant expression
11) a reference to a variable unless it was initialized with a constant expression or is a non-static data member of a temporary object whose lifetime begain within this expression
12) conversion from cv void* to any pointer-to-object type
(since C++14)
15) pseudo-destructor call
16) an increment or a decrement operator
17) a typeid expression applied to a glvalue of polymorphic type
18) a new-expression or a delete-expression
19) a subtraction operator between two pointers
20) an equality or relational operator when the result is unspecified
21) an assignment or a compount assignment operator
22) a throw expression

[edit] 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 contextually implicitly converted to an integral or unscoped enumeration type.

only integral constant expressions can be used as array bounds, the dimensions in new-expressions other than the first (until C++14), bit-field lengths, enumeration initializers when the underlying type is not fixed, null-pointer constants (until C++14), and alignments.

[edit] Converted constant expression

Converted constant expression is an expression implicitly converted to prvalue of type T, where the converted expression is a core 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
  • array-to-pointer conversions
  • function-to-pointer conversions
  • function pointer conversions (pointer to noexcept function to pointer to function)
  • qualification conversions
  • null pointer conversions from std::nullptr_t
  • null member pointer conversions from std::nullptr_t
(since C++17)
  • And if any reference binding takes place, it is direct binding (not one that constructs a temporary object)
Only converted constant expressions can be used as case expressions, enumerator initializers when the underlying type is fixed, array bounds, the dimensions in new-expressions other than the first (since C++14), and as integral and enumeration (until C++17)non-type template arguments.

[edit] Literal constant expression

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.

[edit] Reference constant expression

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

[edit] Address constant expression

Address constant expression is a prvalue core constant expression (after conversions required by context) of type std::nullptr_t 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.

[edit] Notes

Implementations are not permitted to declare library functions as constexpr unless the standard says the function is constexpr (since C++14)

[edit] See also