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
A core constant expression is any expression whose evaluation would not evaluate any one of the following:
constexpr
function or a constexpr
constructor that is being evaluated as part of the expression constexpr int n = std::numeric_limits<int>::max(); // OK: max() is constexpr constexpr int m = std::time(nullptr); // Error: std::time() is not constexpr
constexpr
function which is declared, but not defined constexpr
function/constructor template instantiation where the instantiation fails to satisfy constexpr function/constructor requirements. 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 int x, y, z[30]; constexpr auto e1 = &y - &x; // Error: undefined constexpr auto e2 = &z[20] - &z[3]; // OK constexpr std::bitset<2> a; constexpr bool b = a[2]; // UB, but unspecified if detected
int main() { const std::size_t tabsize = 50; int tab[tabsize]; // OK: tabsize is a constant expression std::size_t n = 50; const std::size_t sz = n; int tab2[sz]; // error: sz is not a constant expression // because sz is not initialized with a constant expression }
constexpr
or a template parameter object (since C++20) or to its non-mutable subobject false
void*
to any pointer-to-object type (since C++14) modification of an object, unless the object has non-volatile literal type and its lifetime began within the evaluation of the expression.
constexpr int incr(int& n) { return ++n; } constexpr int g(int k) { constexpr int x = incr(k); // error: incr(k) is not a core constant // expression because lifetime of k // began outside the expression incr(k) return x; } constexpr int h(int k) { int x = incr(k); // OK: x is not required to be initialized with a core // constant expression return x; } constexpr int y = h(1); // OK: initializes y with the value 2 // h(1) is a core constant expression because // the lifetime of k begins inside the expression h(1)
this
or to a variable defined outside that lambda, if that reference would be an odr-use void g() { const int n=0; constexpr int j=*&n; // OK: outside of a lambda-expression [=]{ constexpr int i=n; // OK: 'n' is not odr-used and not captured here. constexpr int j=*&n;// Ill-formed: '&n' would be an odr-use of 'n'. }; }
note that if the ODR-use takes place in a function call to a closure, it does not refer to // OK: 'v' & 'm' are odr-used but do not occur in a constant-expression // within the nested lambda auto monad = [](auto v){return [=]{return v;};}; auto bind = [](auto m){return [=](auto fvm){return fvm(m());};}; // OK to have captures to automatic objects created during constant expression evaluation. static_assert(bind(monad(2))(monad)() == monad(2)()); | (since C++17) |
Note: Just being a core constant expression does not have any direct semantic meaning: an expression has to be one of the following subsets to be used in certain contexts:
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.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:
| (since C++17) |
A contextually converted constant expression of type bool
is an expression, contextually converted to bool
, where the converted expression is a constant expression and the conversion sequence contains only the conversions above. Such expressions can be used in noexcept
specifications and static assert declarations.
A constant expression is either.
| (since C++14) |
A constant expression is a literal constant expression, a reference constant expression, or an address 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. Reference constant expression is an lvalue core constant expression that designates an object with static storage duration or a function. Address constant expression is a prvalue core constant expression (after conversions required by context) of type | (until C++14) |
void test() { static const int a = std::random_device{}(); constexpr const int& ra = a; // OK: a is a glvalue constant expression constexpr int ia = a; // Error: a is not a prvalue constant expression const int b = 42; constexpr const int& rb = b; // Error: b is not a glvalue constant expression constexpr int ib = b; // OK: b is a prvalue constant expression }
Implementations are not permitted to declare library functions as constexpr unless the standard says the function is constexpr copy elision is mandatory in constant expressions. | (since C++14) |
The following behavior-changing defect reports were applied retroactively to previously published C++ standards.
DR | Applied to | Behavior as published | Correct behavior |
---|---|---|---|
CWG 2167 | C++14 | non-member references local to an evaluation were making the evaluation non-constexpr | non-member references allowed |
CWG 1313 | C++11 | undefined behavior was permitted, and all pointer subtraction was prohibited | same-array pointer subtraction ok, UB prohibited |
CWG 1952 | C++11 | standard library undefined behavior was required to be diagnosed | unspecified whether library UB is diagnosed |
© cppreference.com
Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0.
http://en.cppreference.com/w/cpp/language/constant_expression