Files
cppdraft_translate/cppdraft/dcl/constexpr.md
2025-10-25 03:02:53 +03:00

6.2 KiB
Raw Permalink Blame History

[dcl.constexpr]

9 Declarations [dcl]

9.2 Specifiers [dcl.spec]

9.2.6 The constexpr and consteval specifiers [dcl.constexpr]

1

#

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); // OK, declarationconstexpr int bufsz = 1024; // OK, definitionconstexpr struct pixel { // error: pixel is a typeint x; int y; constexpr pixel(int); // OK, declaration};constexpr pixel::pixel(int a): x(a), y(x) // OK, definition{ square(x); }constexpr pixel small(2); // error: square not defined, so small(2)// not constant ([expr.const]) so constexpr not satisfiedconstexpr void square(int &x) { // OK, definition x *= x;}constexpr pixel large(4); // OK, square definedint next(constexpr int x) { // error: not for parametersreturn x + 1;}extern constexpr int memsz; // error: not a definition — end example]

2

#

A constexpr or consteval specifier used in the declaration of a function declares that function to be a constexpr function.

[Note 3:

A function or constructor 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.

3

#

A function is constexpr-suitable if it is not a coroutine ([dcl.fct.def.coroutine]).

Except for instantiated constexpr functions, non-templated constexpr functions shall be constexpr-suitable.

[Example 2: constexpr int square(int x){ return x * x; } // OKconstexpr long long_max(){ return 2147483647; } // OKconstexpr int abs(int x) {if (x < 0) x = -x; return x; // OK}constexpr int constant_non_42(int n) { // OKif (n == 42) {static int value = n; return value; }return n;}constexpr int uninit() {struct { int a; } s; return s.a; // error: uninitialized read of s.a}constexpr int prev(int x){ return --x; } // OKconstexpr int g(int x, int n) { // OKint r = 1; while (--n > 0) r *= x; return r;} — end example]

4

#

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_evaluated within 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]

5

#

The constexpr and consteval specifiers have no effect on the type of a constexpr function.

[Example 3: constexpr int bar(int x, int y) // OK{ return x + y + x*y; }// ...int bar(int x, int y) // error: redefinition of bar{ return x * 2 + 3 * y; } — end example]

6

#

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 }; // OKconstexpr pixel origin; // error: initializer missingnamespace N {void f() {int x; constexpr int& ar = x; // OKstatic constexpr int& sr = x; // error: x is not constexpr-representable// at the point indicated below}// immediate scope here is that of N} — end example]