[dcl.constexpr] (original) (raw)
9 Declarations [dcl]
9.2 Specifiers [dcl.spec]
9.2.6 The constexpr and consteval specifiers [dcl.constexpr]
The constexpr specifier shall be applied only to the definition of a variable or variable template, a structured binding declaration, or the declaration of a function or function template.
The consteval specifier shall be applied only to the declaration of a function or function template.
A function or static data member declared with the constexpr or consteval specifier on its first declaration is implicitly an inline function or variable ([dcl.inline]).
If any declaration of a function or function template has a constexpr or consteval specifier, then all its declarations shall contain the same specifier.
[Note 1:
An explicit specialization can differ from the template declaration with respect to the constexpr or consteval specifier.
— _end note_]
[Note 2:
Function parameters cannot be declared constexpr.
— _end note_]
[Example 1: constexpr void square(int &x); constexpr int bufsz = 1024; constexpr struct pixel { int x;int y;constexpr pixel(int); };constexpr pixel::pixel(int a) : x(a), y(x) { square(x); } constexpr pixel small(2); constexpr void square(int &x) { x *= x;} constexpr pixel large(4); int next(constexpr int x) { return x + 1;} extern constexpr int memsz; — _end example_]
A constexpr or consteval specifier used in the declaration of a function declares that function to be a constexpr function.
[Note 3:
A function declared with the consteval specifier is an immediate function ([expr.const]).
— _end note_]
A destructor, an allocation function, or a deallocation function shall not be declared with the consteval specifier.
Except for instantiated constexpr functions, non-templated constexpr functions shall be constexpr-suitable.
[Example 2: constexpr int square(int x) { return x * x; } constexpr long long_max() { return 2147483647; } constexpr int abs(int x) { if (x < 0) x = -x;return x; } constexpr int constant_non_42(int n) { if (n == 42) { static int value = n;return value;} return n;} constexpr int uninit() { struct { int a; } s;return s.a; } constexpr int prev(int x) { return --x; } constexpr int g(int x, int n) { int r = 1;while (--n > 0) r *= x;return r;} — _end example_]
An invocation of a constexpr function in a given context produces the same result as an invocation of an equivalent non-constexpr function in the same context in all respects except that
- an invocation of a constexpr function can appear in a constant expression ([expr.const]) and
- copy elision is not performed in a constant expression ([class.copy.elision]).
[Note 4:
Declaring a function constexpr can change whether an expression is a constant expression.
This can indirectly cause calls to std::is_constant_evaluatedwithin an invocation of the function to produce a different value.
— _end note_]
[Note 5:
It is possible to write a constexpr function for which no invocation satisfies the requirements of a core constant expression.
— _end note_]
The constexpr and consteval specifiers have no effect on the type of a constexpr function.
[Example 3: constexpr int bar(int x, int y) { return x + y + x*y; } int bar(int x, int y) { return x * 2 + 3 * y; } — _end example_]
A constexpr specifier used in an object declaration declares the object as const.
Such an object shall have literal type and shall be initialized.
A constexpr variable shall be constant-initializable ([expr.const]).
A constexpr variable that is an object, as well as any temporary to which a constexpr reference is bound, shall have constant destruction.
[Example 4: struct pixel { int x, y;};constexpr pixel ur = { 1294, 1024 }; constexpr pixel origin; namespace N { void f() { int x;constexpr int& ar = x; static constexpr int& sr = x; } } — _end example_]