137 lines
6.2 KiB
Markdown
137 lines
6.2 KiB
Markdown
[dcl.constexpr]
|
||
|
||
# 9 Declarations [[dcl]](./#dcl)
|
||
|
||
## 9.2 Specifiers [[dcl.spec]](dcl.spec#dcl.constexpr)
|
||
|
||
### 9.2.6 The constexpr and consteval specifiers [dcl.constexpr]
|
||
|
||
[1](#1)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L887)
|
||
|
||
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[.](#1.sentence-1)
|
||
|
||
The consteval specifier shall be applied only to
|
||
the declaration of a function or function template[.](#1.sentence-2)
|
||
|
||
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]](dcl.inline "9.2.8 The inline specifier"))[.](#1.sentence-3)
|
||
|
||
If any declaration of a function or function template has
|
||
a constexpr or consteval specifier,
|
||
then all its declarations shall contain the same specifier[.](#1.sentence-4)
|
||
|
||
[*Note [1](#note-1)*:
|
||
|
||
An explicit specialization can differ from the template declaration
|
||
with respect to the constexpr or consteval specifier[.](#1.sentence-5)
|
||
|
||
â *end note*]
|
||
|
||
[*Note [2](#note-2)*:
|
||
|
||
Function parameters cannot be declared constexpr[.](#1.sentence-6)
|
||
|
||
â *end note*]
|
||
|
||
[*Example [1](#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]](expr.const "7.7 Constant expressions")) 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](#2)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L934)
|
||
|
||
A constexpr or consteval specifier
|
||
used in the declaration of a function
|
||
declares that function to be
|
||
a [*constexpr function*](#def:specifier,constexpr,function "9.2.6 The constexpr and consteval specifiers [dcl.constexpr]")[.](#2.sentence-1)
|
||
|
||
[*Note [3](#note-3)*:
|
||
|
||
A function or constructor declared with the consteval specifier
|
||
is an immediate function ([[expr.const]](expr.const "7.7 Constant expressions"))[.](#2.sentence-2)
|
||
|
||
â *end note*]
|
||
|
||
A destructor, an allocation function, or a deallocation function
|
||
shall not be declared with the consteval specifier[.](#2.sentence-3)
|
||
|
||
[3](#3)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L946)
|
||
|
||
A function is [*constexpr-suitable*](#def:constexpr-suitable "9.2.6 The constexpr and consteval specifiers [dcl.constexpr]") if
|
||
it is not a coroutine ([[dcl.fct.def.coroutine]](dcl.fct.def.coroutine "9.6.4 Coroutine definitions"))[.](#3.sentence-1)
|
||
|
||
Except for instantiated constexpr functions,
|
||
non-templated constexpr functions shall be constexpr-suitable[.](#3.sentence-2)
|
||
|
||
[*Example [2](#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](#4)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L987)
|
||
|
||
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
|
||
|
||
- [(4.1)](#4.1)
|
||
|
||
an invocation of a constexpr function
|
||
can appear in a constant expression ([[expr.const]](expr.const "7.7 Constant expressions")) and
|
||
|
||
- [(4.2)](#4.2)
|
||
|
||
copy elision is not performed in a constant expression ([[class.copy.elision]](class.copy.elision "11.9.6 Copy/move elision"))[.](#4.sentence-1)
|
||
|
||
[*Note [4](#note-4)*:
|
||
|
||
Declaring a function constexpr can change whether an expression
|
||
is a constant expression[.](#4.sentence-2)
|
||
|
||
This can indirectly cause calls to std::is_constant_evaluated within an invocation of the function to produce a different value[.](#4.sentence-3)
|
||
|
||
â *end note*]
|
||
|
||
[*Note [5](#note-5)*:
|
||
|
||
It is possible to write a constexpr function for which
|
||
no invocation satisfies the requirements of a core constant expression[.](#4.sentence-4)
|
||
|
||
â *end note*]
|
||
|
||
[5](#5)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L1010)
|
||
|
||
The constexpr and consteval specifiers have no
|
||
effect on the type of a constexpr function[.](#5.sentence-1)
|
||
|
||
[*Example [3](#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](#6)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L1023)
|
||
|
||
A constexpr specifier used in an object declaration
|
||
declares the object as const[.](#6.sentence-1)
|
||
|
||
Such an object
|
||
shall have literal type and
|
||
shall be initialized[.](#6.sentence-2)
|
||
|
||
A constexpr variable shall be constant-initializable ([[expr.const]](expr.const "7.7 Constant expressions"))[.](#6.sentence-3)
|
||
|
||
A constexpr variable that is an object,
|
||
as well as any temporary to which a constexpr reference is bound,
|
||
shall have constant destruction[.](#6.sentence-4)
|
||
|
||
[*Example [4](#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*]
|