This commit is contained in:
2025-10-25 03:02:53 +03:00
commit 043225d523
3416 changed files with 681196 additions and 0 deletions

102
cppdraft/dcl/align.md Normal file
View File

@@ -0,0 +1,102 @@
[dcl.align]
# 9 Declarations [[dcl]](./#dcl)
## 9.13 Attributes [[dcl.attr]](dcl.attr#dcl.align)
### 9.13.2 Alignment specifier [dcl.align]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L9569)
An [*alignment-specifier*](dcl.attr.grammar#nt:alignment-specifier "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") may be applied to a variable
or to a class data member, but it shall not be applied to a bit-field, a function
parameter, or an [*exception-declaration*](except.pre#nt:exception-declaration "14.1Preamble[except.pre]") ([[except.handle]](except.handle "14.4Handling an exception"))[.](#1.sentence-1)
An [*alignment-specifier*](dcl.attr.grammar#nt:alignment-specifier "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") may also be applied to the declaration
of a class (in an[*elaborated-type-specifier*](dcl.type.elab#nt:elaborated-type-specifier "9.2.9.5Elaborated type specifiers[dcl.type.elab]") ([[dcl.type.elab]](dcl.type.elab "9.2.9.5Elaborated type specifiers")) or[*class-head*](class.pre#nt:class-head "11.1Preamble[class.pre]") ([[class]](class "11Classes")), respectively)[.](#1.sentence-2)
An [*alignment-specifier*](dcl.attr.grammar#nt:alignment-specifier "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") with an ellipsis is a pack expansion ([[temp.variadic]](temp.variadic "13.7.4Variadic templates"))[.](#1.sentence-3)
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L9580)
When the [*alignment-specifier*](dcl.attr.grammar#nt:alignment-specifier "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") is of the formalignas( [*constant-expression*](expr.const#nt:constant-expression "7.7Constant expressions[expr.const]") ):
- [(2.1)](#2.1)
the [*constant-expression*](expr.const#nt:constant-expression "7.7Constant expressions[expr.const]") shall be an integral constant expression
- [(2.2)](#2.2)
if the constant expression does not evaluate to an alignment
value ([[basic.align]](basic.align "6.8.3Alignment")), or evaluates to an extended alignment and
the implementation does not support that alignment in the context of the
declaration, the program is ill-formed[.](#2.sentence-1)
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L9592)
An [*alignment-specifier*](dcl.attr.grammar#nt:alignment-specifier "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") of the formalignas( [*type-id*](dcl.name#nt:type-id "9.3.2Type names[dcl.name]") ) has the same
effect as alignas([alignof](expr.alignof "7.6.2.6Alignof[expr.alignof]")( [*type-id*](dcl.name#nt:type-id "9.3.2Type names[dcl.name]") ))[.](#3.sentence-1)
[4](#4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L9597)
The alignment requirement of an entity is the strictest nonzero alignment
specified by its [*alignment-specifier*](dcl.attr.grammar#nt:alignment-specifier "9.13.1Attribute syntax and semantics[dcl.attr.grammar]")*s*, if any;
otherwise, the [*alignment-specifier*](dcl.attr.grammar#nt:alignment-specifier "9.13.1Attribute syntax and semantics[dcl.attr.grammar]")*s* have no effect[.](#4.sentence-1)
[5](#5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L9602)
The combined effect of all [*alignment-specifier*](dcl.attr.grammar#nt:alignment-specifier "9.13.1Attribute syntax and semantics[dcl.attr.grammar]")*s* in a declaration shall not
specify an alignment that is less strict than the alignment that would
be required for the entity being declared if all [*alignment-specifier*](dcl.attr.grammar#nt:alignment-specifier "9.13.1Attribute syntax and semantics[dcl.attr.grammar]")*s* appertaining to that entity
were omitted[.](#5.sentence-1)
[*Example [1](#example-1)*: struct alignas(8) S {};struct alignas(1) U { S s;}; // error: U specifies an alignment that is less strict than if the alignas(1) were omitted. — *end example*]
[6](#6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L9617)
If the defining declaration of an entity has an[*alignment-specifier*](dcl.attr.grammar#nt:alignment-specifier "9.13.1Attribute syntax and semantics[dcl.attr.grammar]"), any non-defining
declaration of that entity shall either specify equivalent alignment or have no[*alignment-specifier*](dcl.attr.grammar#nt:alignment-specifier "9.13.1Attribute syntax and semantics[dcl.attr.grammar]")[.](#6.sentence-1)
Conversely, if any declaration of an entity has an[*alignment-specifier*](dcl.attr.grammar#nt:alignment-specifier "9.13.1Attribute syntax and semantics[dcl.attr.grammar]"),
every defining
declaration of that entity shall specify an equivalent alignment[.](#6.sentence-2)
No diagnostic is required if declarations of an entity have
different [*alignment-specifier*](dcl.attr.grammar#nt:alignment-specifier "9.13.1Attribute syntax and semantics[dcl.attr.grammar]")*s* in different translation units[.](#6.sentence-3)
[*Example [2](#example-2)*: // Translation unit #1:struct S { int x; } s, *p = &s;
// Translation unit #2:struct alignas(16) S; // ill-formed, no diagnostic required: definition of S lacks alignmentextern S* p; — *end example*]
[7](#7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L9640)
[*Example [3](#example-3)*:
An aligned buffer with an alignment requirement
of A and holding N elements of type T can be declared as:alignas(T) alignas(A) T buffer[N];
Specifying alignas(T) ensures
that the final requested alignment will not be weaker than alignof(T),
and therefore the program will not be ill-formed[.](#7.sentence-2)
— *end example*]
[8](#8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L9653)
[*Example [4](#example-4)*: alignas(double) void f(); // error: alignment applied to functionalignas(double) unsigned char c[sizeof(double)]; // array of characters, suitably aligned for a doubleextern unsigned char c[sizeof(double)]; // no alignas necessaryalignas(float)extern unsigned char c[sizeof(double)]; // error: different alignment in declaration — *end example*]

76
cppdraft/dcl/ambig/res.md Normal file
View File

@@ -0,0 +1,76 @@
[dcl.ambig.res]
# 9 Declarations [[dcl]](./#dcl)
## 9.3 Declarators [[dcl.decl]](dcl.decl#dcl.ambig.res)
### 9.3.3 Ambiguity resolution [dcl.ambig.res]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L2657)
The ambiguity arising from the similarity between a function-style cast and
a declaration mentioned in [[stmt.ambig]](stmt.ambig "8.11Ambiguity resolution") can also occur in the context of a declaration[.](#1.sentence-1)
In that context, the choice is between
an object declaration
with a function-style cast as the initializer and
a declaration involving a function declarator
with a redundant set of parentheses around a parameter name[.](#1.sentence-2)
Just as for the ambiguities mentioned in [[stmt.ambig]](stmt.ambig "8.11Ambiguity resolution"),
the resolution is to consider any construct,
such as the potential parameter declaration,
that could possibly be a declaration
to be a declaration[.](#1.sentence-3)
However, a construct that can syntactically be a [*declaration*](dcl.pre#nt:declaration "9.1Preamble[dcl.pre]") whose outermost [*declarator*](dcl.decl.general#nt:declarator "9.3.1General[dcl.decl.general]") would match the grammar of a [*declarator*](dcl.decl.general#nt:declarator "9.3.1General[dcl.decl.general]") with a [*trailing-return-type*](dcl.decl.general#nt:trailing-return-type "9.3.1General[dcl.decl.general]") is a declaration only if it starts with auto[.](#1.sentence-4)
[*Note [1](#note-1)*:
A declaration can be explicitly disambiguated by adding parentheses
around the argument[.](#1.sentence-5)
The ambiguity can be avoided by use of copy-initialization or
list-initialization syntax, or by use of a non-function-style cast[.](#1.sentence-6)
— *end note*]
[*Example [1](#example-1)*: struct S { S(int);};typedef struct BB { int C[2]; } *B, C;
void foo(double a) { S v(int(a)); // function declaration S w(int()); // function declaration S x((int(a))); // object declaration S y((int)a); // object declaration S z = int(a); // object declaration S a(B()->C); // object declaration S b(auto()->C); // function declaration} — *end example*]
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L2700)
An ambiguity can arise from the similarity between a function-style
cast and a[*type-id*](dcl.name#nt:type-id "9.3.2Type names[dcl.name]")[.](#2.sentence-1)
The resolution is that any construct that could possibly be a[*type-id*](dcl.name#nt:type-id "9.3.2Type names[dcl.name]") in its syntactic context shall be considered a[*type-id*](dcl.name#nt:type-id "9.3.2Type names[dcl.name]")[.](#2.sentence-2)
However, a construct that can syntactically be a [*type-id*](dcl.name#nt:type-id "9.3.2Type names[dcl.name]") whose outermost [*abstract-declarator*](dcl.name#nt:abstract-declarator "9.3.2Type names[dcl.name]") would match the grammar of an [*abstract-declarator*](dcl.name#nt:abstract-declarator "9.3.2Type names[dcl.name]") with a [*trailing-return-type*](dcl.decl.general#nt:trailing-return-type "9.3.1General[dcl.decl.general]") is considered a [*type-id*](dcl.name#nt:type-id "9.3.2Type names[dcl.name]") only if it starts with auto[.](#2.sentence-3)
[*Example [2](#example-2)*: template <class T> struct X {};template <int N> struct Y {};
X<int()> a; // type-id X<int(1)> b; // expression (ill-formed) Y<int()> c; // type-id (ill-formed) Y<int(1)> d; // expressionvoid foo(signed char a) {sizeof(int()); // type-id (ill-formed)sizeof(int(a)); // expressionsizeof(int(unsigned(a))); // type-id (ill-formed)(int())+1; // type-id (ill-formed)(int(a))+1; // expression(int(unsigned(a)))+1; // type-id (ill-formed)}typedef struct BB { int C[2]; } *B, C;void g() {sizeof(B()->C[1]); // OK, sizeof(expression)sizeof(auto()->C[1]); // error: sizeof of a function returning an array} — *end example*]
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L2740)
Another ambiguity arises in a[*parameter-declaration-clause*](dcl.fct#nt:parameter-declaration-clause "9.3.4.6Functions[dcl.fct]") when a[*type-name*](dcl.type.simple#nt:type-name "9.2.9.3Simple type specifiers[dcl.type.simple]") is nested in parentheses[.](#3.sentence-1)
In this case, the choice is between the declaration of a parameter of type
pointer to function and the declaration of a parameter with redundant
parentheses around the[*declarator-id*](dcl.decl.general#nt:declarator-id "9.3.1General[dcl.decl.general]")[.](#3.sentence-2)
The resolution is to consider the[*type-name*](dcl.type.simple#nt:type-name "9.2.9.3Simple type specifiers[dcl.type.simple]") as a[*simple-type-specifier*](dcl.type.simple#nt:simple-type-specifier "9.2.9.3Simple type specifiers[dcl.type.simple]") rather than a[*declarator-id*](dcl.decl.general#nt:declarator-id "9.3.1General[dcl.decl.general]")[.](#3.sentence-3)
[*Example [3](#example-3)*: class C { };void f(int(C)) { } // void f(int(*fp)(C c)) { }// not: void f(int C) { }int g(C);
void foo() { f(1); // error: cannot convert 1 to function pointer f(g); // OK}
For another example,class C { };void h(int *(C[10])); // void h(int *(*_fp)(C _parm[10]));// not: void h(int *C[10]);
— *end example*]

216
cppdraft/dcl/array.md Normal file
View File

@@ -0,0 +1,216 @@
[dcl.array]
# 9 Declarations [[dcl]](./#dcl)
## 9.3 Declarators [[dcl.decl]](dcl.decl#dcl.array)
### 9.3.4 Meaning of declarators [[dcl.meaning]](dcl.meaning#dcl.array)
#### 9.3.4.5 Arrays [dcl.array]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L3465)
In a declaration T D where D has the form
D1 [ [*constant-expression*](expr.const#nt:constant-expression "7.7Constant expressions[expr.const]")opt ] [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1Attribute syntax and semantics[dcl.attr.grammar]")opt
and the type of the contained [*declarator-id*](dcl.decl.general#nt:declarator-id "9.3.1General[dcl.decl.general]") in the declaration T D1 is “*derived-declarator-type-list* T”,
the type of the [*declarator-id*](dcl.decl.general#nt:declarator-id "9.3.1General[dcl.decl.general]") in D is
“*derived-declarator-type-list* array of N T”[.](#1.sentence-1)
The [*constant-expression*](expr.const#nt:constant-expression "7.7Constant expressions[expr.const]") shall be a converted constant expression of type std::size_t ([[expr.const]](expr.const "7.7Constant expressions"))[.](#1.sentence-2)
Its value N specifies the [*array bound*](#def:array,bound "9.3.4.5Arrays[dcl.array]"),
i.e., the number of elements in the array;N shall be greater than zero[.](#1.sentence-3)
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L3482)
In a declaration T D where D has the form
D1 [ ] [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1Attribute syntax and semantics[dcl.attr.grammar]")opt
and the type of the contained [*declarator-id*](dcl.decl.general#nt:declarator-id "9.3.1General[dcl.decl.general]") in the declaration T D1 is “*derived-declarator-type-list* T”,
the type of the [*declarator-id*](dcl.decl.general#nt:declarator-id "9.3.1General[dcl.decl.general]") in D is
“*derived-declarator-type-list* array of unknown bound of T”, except as specified below[.](#2.sentence-1)
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L3493)
A type of the form “array of N U” or
“array of unknown bound of U” is an [*array type*](#def:array_type "9.3.4.5Arrays[dcl.array]")[.](#3.sentence-1)
The optional [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") appertains to the array type[.](#3.sentence-2)
[4](#4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L3501)
U is called the array [*element type*](#def:element_type "9.3.4.5Arrays[dcl.array]");
this type shall not be
a reference type,
a function type,
an array of unknown bound, orcv void[.](#4.sentence-1)
[*Note [1](#note-1)*:
An array can be constructed
from one of the fundamental types (except void),
from a pointer,
from a pointer to member,
from a class,
from an enumeration type,
or from an array of known bound[.](#4.sentence-2)
— *end note*]
[*Example [1](#example-1)*:
float fa[17], *afp[17]; declares an array of float numbers and
an array of pointers to float numbers[.](#4.sentence-3)
— *end example*]
[5](#5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L3525)
Any type of the form
“[*cv-qualifier-seq*](dcl.decl.general#nt:cv-qualifier-seq "9.3.1General[dcl.decl.general]") array of N U”
is adjusted to
“array of N [*cv-qualifier-seq*](dcl.decl.general#nt:cv-qualifier-seq "9.3.1General[dcl.decl.general]") U”,
and similarly for “array of unknown bound of U”[.](#5.sentence-1)
[*Example [2](#example-2)*: typedef int A[5], AA[2][3];typedef const A CA; // type is “array of 5 const int''typedef const AA CAA; // type is “array of 2 array of 3 const int'' — *end example*]
[*Note [2](#note-2)*:
An “array of N [*cv-qualifier-seq*](dcl.decl.general#nt:cv-qualifier-seq "9.3.1General[dcl.decl.general]") U”
has cv-qualified type; see [[basic.type.qualifier]](basic.type.qualifier "6.9.5CV-qualifiers")[.](#5.sentence-2)
— *end note*]
[6](#6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L3543)
An object of type “array of N U” consists of
a contiguously allocated non-empty set
of N subobjects of type U,
known as the [*elements*](#def:array,element "9.3.4.5Arrays[dcl.array]") of the array,
and numbered 0 to N-1[.](#6.sentence-1)
[7](#7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L3550)
In addition to declarations in which an incomplete object type is allowed,
an array bound may be omitted in some cases in the declaration of a function
parameter ([[dcl.fct]](dcl.fct "9.3.4.6Functions"))[.](#7.sentence-1)
An array bound may also be omitted
when an object (but not a non-static data member) of array type is initialized
and the declarator is followed by
an initializer ([[dcl.init]](dcl.init "9.5Initializers"), [[class.mem]](class.mem "11.4Class members"), [[expr.type.conv]](expr.type.conv "7.6.1.4Explicit type conversion (functional notation)"), [[expr.new]](expr.new "7.6.2.8New"))[.](#7.sentence-2)
In these cases, the array bound is calculated
from the number of initial elements (say, N)
supplied ([[dcl.init.aggr]](dcl.init.aggr "9.5.2Aggregates")),
and the type of the array is “array of N U”[.](#7.sentence-3)
[8](#8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L3564)
Furthermore, if there is a reachable declaration of the entity
that specifies a bound and
has the same host scope ([[basic.scope.scope]](basic.scope.scope "6.4.1General")),
an omitted array bound is taken to
be the same as in that earlier declaration, and similarly for the definition
of a static data member of a class[.](#8.sentence-1)
[*Example [3](#example-3)*: extern int x[10];struct S {static int y[10];};
int x[]; // OK, bound is 10int S::y[]; // OK, bound is 10void f() {extern int x[]; int i = sizeof(x); // error: incomplete object type}namespace A { extern int z[3]; }int A::z[] = {}; // OK, defines an array of 3 elements — *end example*]
[9](#9)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L3591)
[*Note [3](#note-3)*:
When several “array of” specifications are adjacent,
a multidimensional array type is created;
only the first of the constant expressions
that specify the bounds of the arrays can be omitted[.](#9.sentence-1)
[*Example [4](#example-4)*:
int x3d[3][5][7]; declares an array of three elements,
each of which is an array of five elements,
each of which is an array of seven integers[.](#9.sentence-2)
The overall array can be viewed as a
three-dimensional array of integers,
with rank 3 ×5 ×7[.](#9.sentence-3)
Any of the expressionsx3d,x3d[i],x3d[i][j],x3d[i][j][k] can reasonably appear in an expression[.](#9.sentence-4)
The expressionx3d[i] is equivalent to*(x3d + i);
in that expression,x3d is subject to the array-to-pointer conversion ([[conv.array]](conv.array "7.3.3Array-to-pointer conversion"))
and is first converted to
a pointer to a 2-dimensional
array with rank5 ×7 that points to the first element of x3d[.](#9.sentence-5)
Then i is added,
which on typical implementations involves multiplyingi by the
length of the object to which the pointer points,
which is sizeof(int)×5 ×7[.](#9.sentence-6)
The result of the addition and indirection is
an lvalue denoting
the ith array element ofx3d (an array of five arrays of seven integers)[.](#9.sentence-7)
If there is another subscript,
the same argument applies again, sox3d[i][j] is
an lvalue denoting
the jth array element of
the ith array element ofx3d (an array of seven integers), andx3d[i][j][k] is
an lvalue denoting
the kth array element of
the jth array element of
the ith array element ofx3d (an integer)[.](#9.sentence-8)
— *end example*]
The first subscript in the declaration helps determine
the amount of storage consumed by an array
but plays no other part in subscript calculations[.](#9.sentence-9)
— *end note*]
[10](#10)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L3657)
[*Note [4](#note-4)*:
Conversions affecting expressions of array type are described in [[conv.array]](conv.array "7.3.3Array-to-pointer conversion")[.](#10.sentence-1)
— *end note*]
[11](#11)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L3662)
[*Note [5](#note-5)*:
The subscript operator can be overloaded for a class ([[over.sub]](over.sub "12.4.5Subscripting"))[.](#11.sentence-1)
For the operator's built-in meaning, see [[expr.sub]](expr.sub "7.6.1.2Subscripting")[.](#11.sentence-2)
— *end note*]

28
cppdraft/dcl/asm.md Normal file
View File

@@ -0,0 +1,28 @@
[dcl.asm]
# 9 Declarations [[dcl]](./#dcl)
## 9.11 The asm declaration [dcl.asm]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L9106)
An asm declaration has the form
[asm-declaration:](#nt:asm-declaration "9.11The asm declaration[dcl.asm]")
[*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1Attribute syntax and semantics[dcl.attr.grammar]")opt asm ( [*balanced-token-seq*](dcl.attr.grammar#nt:balanced-token-seq "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") ) ;
The asm declaration is conditionally-supported;
any restrictions on the [*balanced-token-seq*](dcl.attr.grammar#nt:balanced-token-seq "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") and
its meaning are implementation-defined[.](#1.sentence-2)
The optional [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") in
an [*asm-declaration*](#nt:asm-declaration "9.11The asm declaration[dcl.asm]") appertains to the asm declaration[.](#1.sentence-3)
[*Note [1](#note-1)*:
Typically it is used to pass information through the implementation to
an assembler[.](#1.sentence-4)
— *end note*]

881
cppdraft/dcl/attr.md Normal file
View File

@@ -0,0 +1,881 @@
[dcl.attr]
# 9 Declarations [[dcl]](./#dcl)
## 9.13 Attributes [dcl.attr]
### [9.13.1](#grammar) Attribute syntax and semantics [[dcl.attr.grammar]](dcl.attr.grammar)
[1](#grammar-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L9349)
Attributes and annotations specify additional information for various source constructs
such as types, variables, names, contract assertions, blocks, or translation units[.](#grammar-1.sentence-1)
[attribute-specifier-seq:](#nt:attribute-specifier-seq "9.13.1Attribute syntax and semantics[dcl.attr.grammar]")
[*attribute-specifier*](#nt:attribute-specifier "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") [*attribute-specifier-seq*](#nt:attribute-specifier-seq "9.13.1Attribute syntax and semantics[dcl.attr.grammar]")opt
[attribute-specifier:](#nt:attribute-specifier "9.13.1Attribute syntax and semantics[dcl.attr.grammar]")
[ [ [*attribute-using-prefix*](#nt:attribute-using-prefix "9.13.1Attribute syntax and semantics[dcl.attr.grammar]")opt [*attribute-list*](#nt:attribute-list "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") ] ]
[ [ [*annotation-list*](#nt:annotation-list "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") ] ]
[*alignment-specifier*](#nt:alignment-specifier "9.13.1Attribute syntax and semantics[dcl.attr.grammar]")
[alignment-specifier:](#nt:alignment-specifier "9.13.1Attribute syntax and semantics[dcl.attr.grammar]")
alignas ( [*type-id*](dcl.name#nt:type-id "9.3.2Type names[dcl.name]") ...opt )
alignas ( [*constant-expression*](expr.const#nt:constant-expression "7.7Constant expressions[expr.const]") ...opt )
[attribute-using-prefix:](#nt:attribute-using-prefix "9.13.1Attribute syntax and semantics[dcl.attr.grammar]")
using [*attribute-namespace*](#nt:attribute-namespace "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") :
[attribute-list:](#nt:attribute-list "9.13.1Attribute syntax and semantics[dcl.attr.grammar]")
[*attribute*](#nt:attribute "9.13.1Attribute syntax and semantics[dcl.attr.grammar]")opt
[*attribute-list*](#nt:attribute-list "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") , [*attribute*](#nt:attribute "9.13.1Attribute syntax and semantics[dcl.attr.grammar]")opt
[*attribute*](#nt:attribute "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") ...
[*attribute-list*](#nt:attribute-list "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") , [*attribute*](#nt:attribute "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") ...
[annotation-list:](#nt:annotation-list "9.13.1Attribute syntax and semantics[dcl.attr.grammar]")
[*annotation*](#nt:annotation "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") ...opt
[*annotation-list*](#nt:annotation-list "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") , [*annotation*](#nt:annotation "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") ...opt
[attribute:](#nt:attribute "9.13.1Attribute syntax and semantics[dcl.attr.grammar]")
[*attribute-token*](#nt:attribute-token "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") [*attribute-argument-clause*](#nt:attribute-argument-clause "9.13.1Attribute syntax and semantics[dcl.attr.grammar]")opt
[annotation:](#nt:annotation "9.13.1Attribute syntax and semantics[dcl.attr.grammar]")
= [*constant-expression*](expr.const#nt:constant-expression "7.7Constant expressions[expr.const]")
[attribute-token:](#nt:attribute-token "9.13.1Attribute syntax and semantics[dcl.attr.grammar]")
[*identifier*](lex.name#nt:identifier "5.11Identifiers[lex.name]")
[*attribute-scoped-token*](#nt:attribute-scoped-token "9.13.1Attribute syntax and semantics[dcl.attr.grammar]")
[attribute-scoped-token:](#nt:attribute-scoped-token "9.13.1Attribute syntax and semantics[dcl.attr.grammar]")
[*attribute-namespace*](#nt:attribute-namespace "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") :: [*identifier*](lex.name#nt:identifier "5.11Identifiers[lex.name]")
[attribute-namespace:](#nt:attribute-namespace "9.13.1Attribute syntax and semantics[dcl.attr.grammar]")
[*identifier*](lex.name#nt:identifier "5.11Identifiers[lex.name]")
[attribute-argument-clause:](#nt:attribute-argument-clause "9.13.1Attribute syntax and semantics[dcl.attr.grammar]")
( [*balanced-token-seq*](#nt:balanced-token-seq "9.13.1Attribute syntax and semantics[dcl.attr.grammar]")opt )
[balanced-token-seq:](#nt:balanced-token-seq "9.13.1Attribute syntax and semantics[dcl.attr.grammar]")
[*balanced-token*](#nt:balanced-token "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") [*balanced-token-seq*](#nt:balanced-token-seq "9.13.1Attribute syntax and semantics[dcl.attr.grammar]")opt
[balanced-token:](#nt:balanced-token "9.13.1Attribute syntax and semantics[dcl.attr.grammar]")
( [*balanced-token-seq*](#nt:balanced-token-seq "9.13.1Attribute syntax and semantics[dcl.attr.grammar]")opt )
[ [*balanced-token-seq*](#nt:balanced-token-seq "9.13.1Attribute syntax and semantics[dcl.attr.grammar]")opt ]
{ [*balanced-token-seq*](#nt:balanced-token-seq "9.13.1Attribute syntax and semantics[dcl.attr.grammar]")opt }
[: [*balanced-token-seq*](#nt:balanced-token-seq "9.13.1Attribute syntax and semantics[dcl.attr.grammar]")opt :]
any [*token*](lex.token#nt:token "5.10Tokens[lex.token]") other than (, ), [, ], {, }, [:, or :]
[2](#grammar-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L9437)
If an [*attribute-specifier*](#nt:attribute-specifier "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") contains an [*attribute-using-prefix*](#nt:attribute-using-prefix "9.13.1Attribute syntax and semantics[dcl.attr.grammar]"),
the [*attribute-list*](#nt:attribute-list "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") following that [*attribute-using-prefix*](#nt:attribute-using-prefix "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") shall not contain an [*attribute-scoped-token*](#nt:attribute-scoped-token "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") and every [*attribute-token*](#nt:attribute-token "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") in that [*attribute-list*](#nt:attribute-list "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") is treated as if
its [*identifier*](lex.name#nt:identifier "5.11Identifiers[lex.name]") were prefixed with N::,
where N is the [*attribute-namespace*](#nt:attribute-namespace "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") specified in the [*attribute-using-prefix*](#nt:attribute-using-prefix "9.13.1Attribute syntax and semantics[dcl.attr.grammar]")[.](#grammar-2.sentence-1)
[*Note [1](#grammar-note-1)*:
This rule imposes no constraints on how
an [*attribute-using-prefix*](#nt:attribute-using-prefix "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") affects the tokens in an [*attribute-argument-clause*](#nt:attribute-argument-clause "9.13.1Attribute syntax and semantics[dcl.attr.grammar]")[.](#grammar-2.sentence-2)
— *end note*]
[*Example [1](#grammar-example-1)*: [[using CC: opt(1), debug]] // same as [[CC::opt(1), CC::debug]]void f() {}[[using CC: opt(1)]] [[CC::debug]] // same as [[CC::opt(1)]] [[CC::debug]]void g() {}[[using CC: CC::opt(1)]] // error: cannot combine using and scoped attribute tokenvoid h() {} — *end example*]
[3](#grammar-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L9463)
[*Note [2](#grammar-note-2)*:
For each individual attribute, the form of the[*balanced-token-seq*](#nt:balanced-token-seq "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") will be specified[.](#grammar-3.sentence-1)
— *end note*]
[4](#grammar-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L9469)
In an [*attribute-list*](#nt:attribute-list "9.13.1Attribute syntax and semantics[dcl.attr.grammar]"), an ellipsis may appear only if that[*attribute*](#nt:attribute "9.13.1Attribute syntax and semantics[dcl.attr.grammar]")'s specification permits it[.](#grammar-4.sentence-1)
An [*attribute*](#nt:attribute "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") followed
by an ellipsis is a [pack expansion](temp.variadic#def:pack_expansion "13.7.4Variadic templates[temp.variadic]")[.](#grammar-4.sentence-2)
An [*attribute-specifier*](#nt:attribute-specifier "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") that contains
an [*attribute-list*](#nt:attribute-list "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") with no [*attribute*](#nt:attribute "9.13.1Attribute syntax and semantics[dcl.attr.grammar]")*s* and no [*alignment-specifier*](#nt:alignment-specifier "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") has no effect[.](#grammar-4.sentence-3)
The order in which the [*attribute-token*](#nt:attribute-token "9.13.1Attribute syntax and semantics[dcl.attr.grammar]")*s* appear in an[*attribute-list*](#nt:attribute-list "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") is not significant[.](#grammar-4.sentence-4)
If a[keyword](lex.key "5.12Keywords[lex.key]") or an [alternative token](lex.digraph "5.9Alternative tokens[lex.digraph]") that satisfies the syntactic requirements
of an [*identifier*](lex.name#nt:identifier "5.11Identifiers[lex.name]") ([[lex.name]](lex.name "5.11Identifiers")) is
contained in
an [*attribute-token*](#nt:attribute-token "9.13.1Attribute syntax and semantics[dcl.attr.grammar]"), it is considered an identifier[.](#grammar-4.sentence-5)
No[name lookup](basic.lookup "6.5Name lookup[basic.lookup]") is performed on any of the identifiers contained in an[*attribute-token*](#nt:attribute-token "9.13.1Attribute syntax and semantics[dcl.attr.grammar]")[.](#grammar-4.sentence-6)
The [*attribute-token*](#nt:attribute-token "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") determines additional
requirements on the [*attribute-argument-clause*](#nt:attribute-argument-clause "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") (if any)[.](#grammar-4.sentence-7)
[5](#grammar-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L9488)
An [*annotation*](#nt:annotation "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") followed by an ellipsis
is a pack expansion ([[temp.variadic]](temp.variadic "13.7.4Variadic templates"))[.](#grammar-5.sentence-1)
[6](#grammar-6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L9492)
Each [*attribute-specifier-seq*](#nt:attribute-specifier-seq "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") is said to [*appertain*](#def:appertain "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") to some entity or
statement, identified by the syntactic context
where it appears ([[stmt]](stmt "8Statements"), [[dcl]](dcl "9Declarations"), [[dcl.decl]](dcl.decl "9.3Declarators"))[.](#grammar-6.sentence-1)
If an [*attribute-specifier-seq*](#nt:attribute-specifier-seq "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") that appertains to some
entity or statement contains an [*attribute*](#nt:attribute "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") or [*alignment-specifier*](#nt:alignment-specifier "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") that
is not allowed to apply to that
entity or statement, the program is ill-formed[.](#grammar-6.sentence-2)
If an [*attribute-specifier-seq*](#nt:attribute-specifier-seq "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") appertains to a friend declaration ([[class.friend]](class.friend "11.8.4Friends")), that declaration shall be a
definition[.](#grammar-6.sentence-3)
[*Note [3](#grammar-note-3)*:
An [*attribute-specifier-seq*](#nt:attribute-specifier-seq "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") cannot appertain to
an explicit instantiation ([[temp.explicit]](temp.explicit "13.9.3Explicit instantiation"))[.](#grammar-6.sentence-4)
— *end note*]
[7](#grammar-7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L9507)
For an [*attribute-token*](#nt:attribute-token "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") (including an [*attribute-scoped-token*](#nt:attribute-scoped-token "9.13.1Attribute syntax and semantics[dcl.attr.grammar]"))
not specified in this document, the
behavior is implementation-defined;
any such [*attribute-token*](#nt:attribute-token "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") that is not recognized by the implementation
is ignored[.](#grammar-7.sentence-1)
[*Note [4](#grammar-note-4)*:
A program is ill-formed if it contains an [*attribute*](#nt:attribute "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") specified in [dcl.attr] that violates
the rules specifying to which entity or statement the attribute can apply or
the syntax rules for the attribute's [*attribute-argument-clause*](#nt:attribute-argument-clause "9.13.1Attribute syntax and semantics[dcl.attr.grammar]"), if any[.](#grammar-7.sentence-2)
— *end note*]
[*Note [5](#grammar-note-5)*:
The [*attribute*](#nt:attribute "9.13.1Attribute syntax and semantics[dcl.attr.grammar]")*s* specified in [dcl.attr]
have optional semantics:
given a well-formed program,
removing all instances of any one of those [*attribute*](#nt:attribute "9.13.1Attribute syntax and semantics[dcl.attr.grammar]")*s* results in a program whose set of possible executions ([[intro.abstract]](intro.abstract "4.1.2Abstract machine"))
for a given input is
a subset of those of the original program for the same input,
absent implementation-defined guarantees
with respect to that [*attribute*](#nt:attribute "9.13.1Attribute syntax and semantics[dcl.attr.grammar]")[.](#grammar-7.sentence-3)
— *end note*]
An [*attribute-token*](#nt:attribute-token "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") is reserved for future standardization if
- [(7.1)](#grammar-7.1)
it is not an [*attribute-scoped-token*](#nt:attribute-scoped-token "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") and
is not specified in this document, or
- [(7.2)](#grammar-7.2)
it is an [*attribute-scoped-token*](#nt:attribute-scoped-token "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") and
its [*attribute-namespace*](#nt:attribute-namespace "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") isstd followed by zero or more digits[.](#grammar-7.sentence-4)
Each implementation should choose a distinctive name for the[*attribute-namespace*](#nt:attribute-namespace "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") in an [*attribute-scoped-token*](#nt:attribute-scoped-token "9.13.1Attribute syntax and semantics[dcl.attr.grammar]")[.](#grammar-7.sentence-5)
[8](#grammar-8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L9542)
Two consecutive left square bracket tokens shall appear only
when introducing an [*attribute-specifier*](#nt:attribute-specifier "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") or
within the [*balanced-token-seq*](#nt:balanced-token-seq "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") of
an [*attribute-argument-clause*](#nt:attribute-argument-clause "9.13.1Attribute syntax and semantics[dcl.attr.grammar]")[.](#grammar-8.sentence-1)
[*Note [6](#grammar-note-6)*:
If two consecutive left square brackets appear
where an [*attribute-specifier*](#nt:attribute-specifier "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") is not allowed, the program is ill-formed even
if the brackets match an alternative grammar production[.](#grammar-8.sentence-2)
— *end note*]
[*Example [2](#grammar-example-2)*: int p[10];void f() {int x = 42, y[5]; int(p[[x] { return x; }()]); // error: invalid attribute on a nested [*declarator-id*](dcl.decl.general#nt:declarator-id "9.3.1General[dcl.decl.general]") and// not a function-style cast of an element of p. y[[] { return 2; }()] = 2; // error even though attributes are not allowed in this context.int i [[vendor::attr([[]])]]; // well-formed implementation-defined attribute.} — *end example*]
### [9.13.2](#dcl.align) Alignment specifier [[dcl.align]](dcl.align)
[1](#dcl.align-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L9569)
An [*alignment-specifier*](#nt:alignment-specifier "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") may be applied to a variable
or to a class data member, but it shall not be applied to a bit-field, a function
parameter, or an [*exception-declaration*](except.pre#nt:exception-declaration "14.1Preamble[except.pre]") ([[except.handle]](except.handle "14.4Handling an exception"))[.](#dcl.align-1.sentence-1)
An [*alignment-specifier*](#nt:alignment-specifier "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") may also be applied to the declaration
of a class (in an[*elaborated-type-specifier*](dcl.type.elab#nt:elaborated-type-specifier "9.2.9.5Elaborated type specifiers[dcl.type.elab]") ([[dcl.type.elab]](dcl.type.elab "9.2.9.5Elaborated type specifiers")) or[*class-head*](class.pre#nt:class-head "11.1Preamble[class.pre]") ([[class]](class "11Classes")), respectively)[.](#dcl.align-1.sentence-2)
An [*alignment-specifier*](#nt:alignment-specifier "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") with an ellipsis is a pack expansion ([[temp.variadic]](temp.variadic "13.7.4Variadic templates"))[.](#dcl.align-1.sentence-3)
[2](#dcl.align-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L9580)
When the [*alignment-specifier*](#nt:alignment-specifier "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") is of the formalignas( [*constant-expression*](expr.const#nt:constant-expression "7.7Constant expressions[expr.const]") ):
- [(2.1)](#dcl.align-2.1)
the [*constant-expression*](expr.const#nt:constant-expression "7.7Constant expressions[expr.const]") shall be an integral constant expression
- [(2.2)](#dcl.align-2.2)
if the constant expression does not evaluate to an alignment
value ([[basic.align]](basic.align "6.8.3Alignment")), or evaluates to an extended alignment and
the implementation does not support that alignment in the context of the
declaration, the program is ill-formed[.](#dcl.align-2.sentence-1)
[3](#dcl.align-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L9592)
An [*alignment-specifier*](#nt:alignment-specifier "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") of the formalignas( [*type-id*](dcl.name#nt:type-id "9.3.2Type names[dcl.name]") ) has the same
effect as alignas([alignof](expr.alignof "7.6.2.6Alignof[expr.alignof]")( [*type-id*](dcl.name#nt:type-id "9.3.2Type names[dcl.name]") ))[.](#dcl.align-3.sentence-1)
[4](#dcl.align-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L9597)
The alignment requirement of an entity is the strictest nonzero alignment
specified by its [*alignment-specifier*](#nt:alignment-specifier "9.13.1Attribute syntax and semantics[dcl.attr.grammar]")*s*, if any;
otherwise, the [*alignment-specifier*](#nt:alignment-specifier "9.13.1Attribute syntax and semantics[dcl.attr.grammar]")*s* have no effect[.](#dcl.align-4.sentence-1)
[5](#dcl.align-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L9602)
The combined effect of all [*alignment-specifier*](#nt:alignment-specifier "9.13.1Attribute syntax and semantics[dcl.attr.grammar]")*s* in a declaration shall not
specify an alignment that is less strict than the alignment that would
be required for the entity being declared if all [*alignment-specifier*](#nt:alignment-specifier "9.13.1Attribute syntax and semantics[dcl.attr.grammar]")*s* appertaining to that entity
were omitted[.](#dcl.align-5.sentence-1)
[*Example [1](#dcl.align-example-1)*: struct alignas(8) S {};struct alignas(1) U { S s;}; // error: U specifies an alignment that is less strict than if the alignas(1) were omitted. — *end example*]
[6](#dcl.align-6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L9617)
If the defining declaration of an entity has an[*alignment-specifier*](#nt:alignment-specifier "9.13.1Attribute syntax and semantics[dcl.attr.grammar]"), any non-defining
declaration of that entity shall either specify equivalent alignment or have no[*alignment-specifier*](#nt:alignment-specifier "9.13.1Attribute syntax and semantics[dcl.attr.grammar]")[.](#dcl.align-6.sentence-1)
Conversely, if any declaration of an entity has an[*alignment-specifier*](#nt:alignment-specifier "9.13.1Attribute syntax and semantics[dcl.attr.grammar]"),
every defining
declaration of that entity shall specify an equivalent alignment[.](#dcl.align-6.sentence-2)
No diagnostic is required if declarations of an entity have
different [*alignment-specifier*](#nt:alignment-specifier "9.13.1Attribute syntax and semantics[dcl.attr.grammar]")*s* in different translation units[.](#dcl.align-6.sentence-3)
[*Example [2](#dcl.align-example-2)*: // Translation unit #1:struct S { int x; } s, *p = &s;
// Translation unit #2:struct alignas(16) S; // ill-formed, no diagnostic required: definition of S lacks alignmentextern S* p; — *end example*]
[7](#dcl.align-7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L9640)
[*Example [3](#dcl.align-example-3)*:
An aligned buffer with an alignment requirement
of A and holding N elements of type T can be declared as:alignas(T) alignas(A) T buffer[N];
Specifying alignas(T) ensures
that the final requested alignment will not be weaker than alignof(T),
and therefore the program will not be ill-formed[.](#dcl.align-7.sentence-2)
— *end example*]
[8](#dcl.align-8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L9653)
[*Example [4](#dcl.align-example-4)*: alignas(double) void f(); // error: alignment applied to functionalignas(double) unsigned char c[sizeof(double)]; // array of characters, suitably aligned for a doubleextern unsigned char c[sizeof(double)]; // no alignas necessaryalignas(float)extern unsigned char c[sizeof(double)]; // error: different alignment in declaration — *end example*]
### [9.13.3](#assume) Assumption attribute [[dcl.attr.assume]](dcl.attr.assume)
[1](#assume-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L9666)
The [*attribute-token*](#nt:attribute-token "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") assume may be applied to a null statement;
such a statement is an [*assumption*](#def:assumption "9.13.3Assumption attribute[dcl.attr.assume]")[.](#assume-1.sentence-1)
An [*attribute-argument-clause*](#nt:attribute-argument-clause "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") shall be present and
shall have the form:
( [*conditional-expression*](expr.cond#nt:conditional-expression "7.6.16Conditional operator[expr.cond]") )
The expression is contextually converted to bool ([[conv.general]](conv.general "7.3.1General"))[.](#assume-1.sentence-2)
The expression is not evaluated[.](#assume-1.sentence-3)
If the converted expression would evaluate to true at the point where the assumption appears,
the assumption has no effect[.](#assume-1.sentence-4)
Otherwise,
evaluation of the assumption has runtime-undefined behavior[.](#assume-1.sentence-5)
[2](#assume-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L9682)
[*Note [1](#assume-note-1)*:
The expression is potentially evaluated ([[basic.def.odr]](basic.def.odr "6.3One-definition rule"))[.](#assume-2.sentence-1)
The use of assumptions is intended to allow implementations
to analyze the form of the expression and
deduce information used to optimize the program[.](#assume-2.sentence-2)
Implementations are not required to deduce
any information from any particular assumption[.](#assume-2.sentence-3)
It is expected that the value of
a [*has-attribute-expression*](cpp.cond#nt:has-attribute-expression "15.2Conditional inclusion[cpp.cond]") for the assume attribute
is 0 if an implementation does not attempt to deduce
any such information from assumptions[.](#assume-2.sentence-4)
— *end note*]
[3](#assume-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L9697)
[*Example [1](#assume-example-1)*: int divide_by_32(int x) {[[assume(x >= 0)]]; return x/32; // The instructions produced for the division// may omit handling of negative values.}int f(int y) {[[assume(++y == 43)]]; // y is not incrementedreturn y; // statement may be replaced with return 42;} — *end example*]
### [9.13.4](#deprecated) Deprecated attribute [[dcl.attr.deprecated]](dcl.attr.deprecated)
[1](#deprecated-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L9715)
The [*attribute-token*](#nt:attribute-token "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") deprecated can be used to mark names and entities
whose use is still allowed, but is discouraged for some reason[.](#deprecated-1.sentence-1)
[*Note [1](#deprecated-note-1)*:
In particular,deprecated is appropriate for names and entities that are deemed obsolescent or
unsafe[.](#deprecated-1.sentence-2)
— *end note*]
An[*attribute-argument-clause*](#nt:attribute-argument-clause "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") may be present and, if present, it shall have the form:
( [*unevaluated-string*](lex.string.uneval#nt:unevaluated-string "5.13.6Unevaluated strings[lex.string.uneval]") )
[*Note [2](#deprecated-note-2)*:
The [*unevaluated-string*](lex.string.uneval#nt:unevaluated-string "5.13.6Unevaluated strings[lex.string.uneval]") in the [*attribute-argument-clause*](#nt:attribute-argument-clause "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") can be used to explain the rationale for deprecation and/or to suggest a replacing entity[.](#deprecated-1.sentence-3)
— *end note*]
[2](#deprecated-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L9733)
The attribute may be applied to the declaration of
a class,
a type alias,
a variable,
a non-static data member,
a function,
a namespace,
an enumeration,
an enumerator,
a concept, or
a template specialization[.](#deprecated-2.sentence-1)
[3](#deprecated-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L9746)
An entity declared without the deprecated attribute can later be redeclared
with the attribute and vice-versa[.](#deprecated-3.sentence-1)
[*Note [3](#deprecated-note-3)*:
Thus, an entity initially declared without the
attribute can be marked as deprecated by a subsequent redeclaration[.](#deprecated-3.sentence-2)
However, after an entity
is marked as deprecated, later redeclarations do not un-deprecate the entity[.](#deprecated-3.sentence-3)
— *end note*]
Redeclarations using different forms of the attribute (with or without the[*attribute-argument-clause*](#nt:attribute-argument-clause "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") or with different[*attribute-argument-clause*](#nt:attribute-argument-clause "9.13.1Attribute syntax and semantics[dcl.attr.grammar]")*s*) are allowed[.](#deprecated-3.sentence-4)
[4](#deprecated-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L9758)
*Recommended practice*: Implementations should use the deprecated attribute to produce a diagnostic
message in case the program refers to a name or entity other than to declare it, after a
declaration that specifies the attribute[.](#deprecated-4.sentence-1)
The diagnostic message should include the text provided
within the [*attribute-argument-clause*](#nt:attribute-argument-clause "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") of any deprecated attribute applied
to the name or entity[.](#deprecated-4.sentence-2)
The value of
a [*has-attribute-expression*](cpp.cond#nt:has-attribute-expression "15.2Conditional inclusion[cpp.cond]") for the deprecated attribute
should be 0 unless the implementation can issue such diagnostic messages[.](#deprecated-4.sentence-3)
### [9.13.5](#fallthrough) Fallthrough attribute [[dcl.attr.fallthrough]](dcl.attr.fallthrough)
[1](#fallthrough-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L9773)
The [*attribute-token*](#nt:attribute-token "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") fallthrough may be applied to a [null statement](stmt.expr#def:statement,null "8.3Expression statement[stmt.expr]"); such a statement is a fallthrough statement[.](#fallthrough-1.sentence-1)
No [*attribute-argument-clause*](#nt:attribute-argument-clause "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") shall be present[.](#fallthrough-1.sentence-2)
A fallthrough statement may only appear within
an enclosing switch statement ([[stmt.switch]](stmt.switch "8.5.3The switch statement"))[.](#fallthrough-1.sentence-3)
The next statement that would be executed after a fallthrough statement
shall be a labeled statement whose label is a case label or
default label for the same switch statement and,
if the fallthrough statement is contained in an iteration statement,
the next statement shall be part of the same execution of
the substatement of the innermost enclosing iteration statement[.](#fallthrough-1.sentence-4)
The program is ill-formed if there is no such statement[.](#fallthrough-1.sentence-5)
[2](#fallthrough-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L9789)
*Recommended practice*: The use of a fallthrough statement should suppress
a warning that an implementation might otherwise issue
for a case or default label that is reachable
from another case or default label along some path of execution[.](#fallthrough-2.sentence-1)
The value of
a [*has-attribute-expression*](cpp.cond#nt:has-attribute-expression "15.2Conditional inclusion[cpp.cond]") for the fallthrough attribute
should be 0 if the attribute does not cause suppression of such warnings[.](#fallthrough-2.sentence-2)
Implementations should issue a warning
if a fallthrough statement is not dynamically reachable[.](#fallthrough-2.sentence-3)
[3](#fallthrough-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L9802)
[*Example [1](#fallthrough-example-1)*: void f(int n) {void g(), h(), i(); switch (n) {case 1:case 2: g(); [[fallthrough]]; case 3: // warning on fallthrough discourageddo {[[fallthrough]]; // error: next statement is not part of the same substatement execution} while (false); case 6:do {[[fallthrough]]; // error: next statement is not part of the same substatement execution} while (n--); case 7:while (false) {[[fallthrough]]; // error: next statement is not part of the same substatement execution}case 5: h(); case 4: // implementation may warn on fallthrough i(); [[fallthrough]]; // error}} — *end example*]
### [9.13.6](#indet) Indeterminate storage [[dcl.attr.indet]](dcl.attr.indet)
[1](#indet-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L9837)
The [*attribute-token*](#nt:attribute-token "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") indeterminate may be applied
to the definition of a block variable with automatic storage duration or
to a [*parameter-declaration*](dcl.fct#nt:parameter-declaration "9.3.4.6Functions[dcl.fct]") of a function declaration[.](#indet-1.sentence-1)
No [*attribute-argument-clause*](#nt:attribute-argument-clause "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") shall be present[.](#indet-1.sentence-2)
The attribute specifies
that the storage of an object with automatic storage duration
is initially indeterminate rather than erroneous ([[basic.indet]](basic.indet "6.8.5Indeterminate and erroneous values"))[.](#indet-1.sentence-3)
[2](#indet-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L9846)
If a function parameter is declared with the indeterminate attribute,
it shall be so declared in the first declaration of its function[.](#indet-2.sentence-1)
If a function parameter is declared with
the indeterminate attribute in the first declaration of its function
in one translation unit and
the same function is declared without the indeterminate attribute
on the same parameter in its first declaration in another translation unit,
the program is ill-formed, no diagnostic required[.](#indet-2.sentence-2)
[3](#indet-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L9856)
[*Note [1](#indet-note-1)*:
Reading from an uninitialized variable
that is marked [[indeterminate]] can cause undefined behavior[.](#indet-3.sentence-1)
void f(int);void g() {int x [[indeterminate]], y;
f(y); // erroneous behavior ([[basic.indet]](basic.indet "6.8.5Indeterminate and erroneous values")) f(x); // undefined behavior}struct T { T() {}int x;};int h(T t [[indeterminate]]) { f(t.x); // undefined behavior when called belowreturn 0;}int _ = h(T()); — *end note*]
### [9.13.7](#likelihood) Likelihood attributes [[dcl.attr.likelihood]](dcl.attr.likelihood)
[1](#likelihood-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L9884)
The [*attribute-token*](#nt:attribute-token "9.13.1Attribute syntax and semantics[dcl.attr.grammar]")*s*likely and unlikely may be applied to labels or statements[.](#likelihood-1.sentence-1)
No [*attribute-argument-clause*](#nt:attribute-argument-clause "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") shall be present[.](#likelihood-1.sentence-2)
The [*attribute-token*](#nt:attribute-token "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") likely shall not appear in an [*attribute-specifier-seq*](#nt:attribute-specifier-seq "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") that contains the [*attribute-token*](#nt:attribute-token "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") unlikely[.](#likelihood-1.sentence-3)
[2](#likelihood-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L9893)
[*Note [1](#likelihood-note-1)*:
The use of the likely attribute
is intended to allow implementations to optimize for
the case where paths of execution including it
are arbitrarily more likely
than any alternative path of execution
that does not include such an attribute on a statement or label[.](#likelihood-2.sentence-1)
The use of the unlikely attribute
is intended to allow implementations to optimize for
the case where paths of execution including it
are arbitrarily more unlikely
than any alternative path of execution
that does not include such an attribute on a statement or label[.](#likelihood-2.sentence-2)
It is expected that the value of a [*has-attribute-expression*](cpp.cond#nt:has-attribute-expression "15.2Conditional inclusion[cpp.cond]") for the likely and unlikely attributes
is 0 if the implementation does not attempt to use these attributes
for such optimizations[.](#likelihood-2.sentence-3)
A path of execution includes a label
if and only if it contains a jump to that label[.](#likelihood-2.sentence-4)
— *end note*]
[*Note [2](#likelihood-note-2)*:
Excessive usage of either of these attributes
is liable to result in performance degradation[.](#likelihood-2.sentence-5)
— *end note*]
[3](#likelihood-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L9920)
[*Example [1](#likelihood-example-1)*: void g(int);int f(int n) {if (n > 5) [[unlikely]] { // n > 5 is considered to be arbitrarily unlikely g(0); return n * 2 + 1; }switch (n) {case 1: g(1); [[fallthrough]]; [[likely]] case 2: // n == 2 is considered to be arbitrarily more g(2); // likely than any other value of nbreak; }return 3;} — *end example*]
### [9.13.8](#unused) Maybe unused attribute [[dcl.attr.unused]](dcl.attr.unused)
[1](#unused-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L9947)
The [*attribute-token*](#nt:attribute-token "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") maybe_unused indicates that a name, label, or entity is possibly intentionally unused[.](#unused-1.sentence-1)
No [*attribute-argument-clause*](#nt:attribute-argument-clause "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") shall be present[.](#unused-1.sentence-2)
[2](#unused-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L9952)
The attribute may be applied to the declaration of a class,
type alias,
variable (including a structured binding declaration),
structured binding,
result binding ([[dcl.contract.res]](dcl.contract.res "9.4.2Referring to the result object")),
non-static data member,
function,
enumeration, or
enumerator, or
to an [*identifier*](lex.name#nt:identifier "5.11Identifiers[lex.name]") label ([[stmt.label]](stmt.label "8.2Label"))[.](#unused-2.sentence-1)
[3](#unused-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L9964)
A name or entity declared without the maybe_unused attribute
can later be redeclared with the attribute
and vice versa[.](#unused-3.sentence-1)
An entity is considered marked
after the first declaration that marks it[.](#unused-3.sentence-2)
[4](#unused-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L9971)
*Recommended practice*: For an entity marked maybe_unused,
implementations should not emit a warning
that the entity or its structured bindings (if any)
are used or unused[.](#unused-4.sentence-1)
For a structured binding declaration not marked maybe_unused,
implementations should not emit such a warning unless
all of its structured bindings are unused[.](#unused-4.sentence-2)
For a label to which maybe_unused is applied,
implementations should not emit a warning that the label is used or unused[.](#unused-4.sentence-3)
The value of
a [*has-attribute-expression*](cpp.cond#nt:has-attribute-expression "15.2Conditional inclusion[cpp.cond]") for the maybe_unused attribute
should be 0 if the attribute does not cause suppression of such warnings[.](#unused-4.sentence-4)
[5](#unused-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L9987)
[*Example [1](#unused-example-1)*: [[maybe_unused]] void f([[maybe_unused]] bool thing1, [[maybe_unused]] bool thing2) {[[maybe_unused]] bool b = thing1 && thing2;
assert(b);#ifdef NDEBUG goto x;#endif[[maybe_unused]] x:}
Implementations should not warn that b or x is unused,
whether or not NDEBUG is defined[.](#unused-5.sentence-1)
— *end example*]
### [9.13.9](#nodiscard) Nodiscard attribute [[dcl.attr.nodiscard]](dcl.attr.nodiscard)
[1](#nodiscard-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L10007)
The [*attribute-token*](#nt:attribute-token "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") nodiscard may be applied to a function or a lambda call operator or
to the declaration of a class or enumeration[.](#nodiscard-1.sentence-1)
An [*attribute-argument-clause*](#nt:attribute-argument-clause "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") may be present
and, if present, shall have the form:
( [*unevaluated-string*](lex.string.uneval#nt:unevaluated-string "5.13.6Unevaluated strings[lex.string.uneval]") )
[2](#nodiscard-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L10017)
A name or entity declared without the nodiscard attribute
can later be redeclared with the attribute and vice-versa[.](#nodiscard-2.sentence-1)
[*Note [1](#nodiscard-note-1)*:
Thus, an entity initially declared without the attribute
can be marked as nodiscard by a subsequent redeclaration[.](#nodiscard-2.sentence-2)
However, after an entity is marked as nodiscard,
later redeclarations do not remove the nodiscard from the entity[.](#nodiscard-2.sentence-3)
— *end note*]
Redeclarations using different forms of the attribute
(with or without the [*attribute-argument-clause*](#nt:attribute-argument-clause "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") or with different [*attribute-argument-clause*](#nt:attribute-argument-clause "9.13.1Attribute syntax and semantics[dcl.attr.grammar]")*s*)
are allowed[.](#nodiscard-2.sentence-4)
[3](#nodiscard-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L10033)
A [*nodiscard type*](#def:type,nodiscard "9.13.9Nodiscard attribute[dcl.attr.nodiscard]") is
a (possibly cv-qualified) class or enumeration type
marked nodiscard in a reachable declaration[.](#nodiscard-3.sentence-1)
A [*nodiscard call*](#def:call,nodiscard "9.13.9Nodiscard attribute[dcl.attr.nodiscard]") is either
- [(3.1)](#nodiscard-3.1)
a function call expression ([[expr.call]](expr.call "7.6.1.3Function call"))
that calls a function declared nodiscard in a reachable declaration or
whose return type is a nodiscard type, or
- [(3.2)](#nodiscard-3.2)
an explicit type
conversion ([[expr.type.conv]](expr.type.conv "7.6.1.4Explicit type conversion (functional notation)"), [[expr.static.cast]](expr.static.cast "7.6.1.9Static cast"), [[expr.cast]](expr.cast "7.6.3Explicit type conversion (cast notation)"))
that constructs an object through
a constructor declared nodiscard in a reachable declaration, or
that initializes an object of a nodiscard type[.](#nodiscard-3.sentence-2)
[4](#nodiscard-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L10051)
*Recommended practice*: Appearance of a nodiscard call as
a potentially-evaluated discarded-value expression ([[expr.prop]](expr.prop "7.2Properties of expressions"))
of non-void type
is discouraged unless explicitly cast to void[.](#nodiscard-4.sentence-1)
Implementations should issue a warning in such cases[.](#nodiscard-4.sentence-2)
The value of
a [*has-attribute-expression*](cpp.cond#nt:has-attribute-expression "15.2Conditional inclusion[cpp.cond]") for the nodiscard attribute
should be 0 unless the implementation can issue such warnings[.](#nodiscard-4.sentence-3)
[*Note [2](#nodiscard-note-2)*:
This is typically because discarding the return value
of a nodiscard call has surprising consequences[.](#nodiscard-4.sentence-4)
— *end note*]
The [*unevaluated-string*](lex.string.uneval#nt:unevaluated-string "5.13.6Unevaluated strings[lex.string.uneval]") in a nodiscard [*attribute-argument-clause*](#nt:attribute-argument-clause "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") should be used in the message of the warning
as the rationale for why the result should not be discarded[.](#nodiscard-4.sentence-5)
[5](#nodiscard-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L10070)
[*Example [1](#nodiscard-example-1)*: struct [[nodiscard]] my_scopeguard { /* ... */ };struct my_unique { my_unique() = default; // does not acquire resource[[nodiscard]] my_unique(int fd) { /* ... */ } // acquires resource~my_unique() noexcept { /* ... */ } // releases resource, if any/* ... */};struct [[nodiscard]] error_info { /* ... */ };
error_info enable_missile_safety_mode();void launch_missiles();void test_missiles() { my_scopeguard(); // warning encouraged(void)my_scopeguard(), // warning not encouraged, cast to void launch_missiles(); // comma operator, statement continues my_unique(42); // warning encouraged my_unique(); // warning not encouraged enable_missile_safety_mode(); // warning encouraged launch_missiles();} error_info &foo();void f() { foo(); } // warning not encouraged: not a nodiscard call, because neither// the (reference) return type nor the function is declared nodiscard — *end example*]
### [9.13.10](#noreturn) Noreturn attribute [[dcl.attr.noreturn]](dcl.attr.noreturn)
[1](#noreturn-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L10101)
The [*attribute-token*](#nt:attribute-token "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") noreturn specifies that a function does not return[.](#noreturn-1.sentence-1)
No [*attribute-argument-clause*](#nt:attribute-argument-clause "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") shall be present[.](#noreturn-1.sentence-2)
The attribute may be applied to a function or a lambda call operator[.](#noreturn-1.sentence-3)
The first declaration of a function shall
specify the noreturn attribute if any declaration of that function specifies thenoreturn attribute[.](#noreturn-1.sentence-4)
If a function is declared with the noreturn attribute in one
translation unit and the same function is declared without the noreturn attribute in another
translation unit, the program is ill-formed, no diagnostic required[.](#noreturn-1.sentence-5)
[2](#noreturn-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L10111)
If a function f is invoked where f was previously declared with the noreturn attribute and that invocation eventually returns,
the behavior is runtime-undefined[.](#noreturn-2.sentence-1)
[*Note [1](#noreturn-note-1)*:
The function can
terminate by throwing an exception[.](#noreturn-2.sentence-2)
— *end note*]
[3](#noreturn-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L10120)
*Recommended practice*: Implementations should issue a
warning if a function marked [[noreturn]] might return[.](#noreturn-3.sentence-1)
The value of
a [*has-attribute-expression*](cpp.cond#nt:has-attribute-expression "15.2Conditional inclusion[cpp.cond]") for the noreturn attribute
should be 0 unless the implementation can issue such warnings[.](#noreturn-3.sentence-2)
[4](#noreturn-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L10128)
[*Example [1](#noreturn-example-1)*: [[ noreturn ]] void f() {throw "error"; // OK}[[ noreturn ]] void q(int i) { // behavior is undefined if called with an argument <= 0if (i > 0)throw "positive";} — *end example*]
### [9.13.11](#nouniqueaddr) No unique address attribute [[dcl.attr.nouniqueaddr]](dcl.attr.nouniqueaddr)
[1](#nouniqueaddr-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L10145)
The [*attribute-token*](#nt:attribute-token "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") no_unique_address specifies that a non-static data member
is a potentially-overlapping subobject ([[intro.object]](intro.object "6.8.2Object model"))[.](#nouniqueaddr-1.sentence-1)
No [*attribute-argument-clause*](#nt:attribute-argument-clause "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") shall be present[.](#nouniqueaddr-1.sentence-2)
The attribute may appertain to a non-static data member
other than a bit-field[.](#nouniqueaddr-1.sentence-3)
[2](#nouniqueaddr-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L10153)
[*Note [1](#nouniqueaddr-note-1)*:
The non-static data member can share the address of
another non-static data member or that of a base class,
and any padding that would normally be inserted
at the end of the object
can be reused as storage for other members[.](#nouniqueaddr-2.sentence-1)
— *end note*]
*Recommended practice*: The value of a [*has-attribute-expression*](cpp.cond#nt:has-attribute-expression "15.2Conditional inclusion[cpp.cond]") for the no_unique_address attribute
should be 0 for a given implementation
unless this attribute can cause a potentially-overlapping subobject
to have zero size[.](#nouniqueaddr-2.sentence-2)
[*Example [1](#nouniqueaddr-example-1)*: template<typename Key, typename Value, typename Hash, typename Pred, typename Allocator>class hash_map {[[no_unique_address]] Hash hasher; [[no_unique_address]] Pred pred; [[no_unique_address]] Allocator alloc;
Bucket *buckets; // ...public:// ...};
Here, hasher, pred, and alloc could have the same address as buckets if their respective types are all empty[.](#nouniqueaddr-2.sentence-3)
— *end example*]
### [9.13.12](#annotation) Annotations [[dcl.attr.annotation]](dcl.attr.annotation)
[1](#annotation-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L10191)
An annotation may be applied to any declaration of a
type,
type alias,
variable,
function,
namespace,
enumerator,[*base-specifier*](class.derived.general#nt:base-specifier "11.7.1General[class.derived.general]"), or
non-static data member[.](#annotation-1.sentence-1)
[2](#annotation-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L10202)
Let E be the expressionstd::meta::reflect_constant([*constant-expression*](expr.const#nt:constant-expression "7.7Constant expressions[expr.const]"))[.](#annotation-2.sentence-1)
E shall be a constant expression;
the result of E is the [*underlying constant*](#def:constant,underlying "9.13.12Annotations[dcl.attr.annotation]") of the annotation[.](#annotation-2.sentence-2)
[3](#annotation-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L10208)
Each [*annotation*](#nt:annotation "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") produces a unique annotation[.](#annotation-3.sentence-1)
[4](#annotation-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L10211)
Substituting into an [*annotation*](#nt:annotation "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") is not in the immediate context[.](#annotation-4.sentence-1)
[*Example [1](#annotation-example-1)*:
[[=1]] void f();[[=2, =3, =2]] void g();void g [[=4, =2]] ();f has one annotation
and g has five annotations[.](#annotation-4.sentence-2)
These can be queried with metafunctions
such as std::meta::annotations_of ([[meta.reflection.annotation]](meta.reflection.annotation "21.4.18Annotation reflection"))[.](#annotation-4.sentence-3)
— *end example*]
[*Example [2](#annotation-example-2)*: template<class T>[[=T::type()]] void f(T t);
void f(int);
void g() { f(0); // OK f('0'); // error, substituting into the annotation results in an invalid expression} — *end example*]

View File

@@ -0,0 +1,57 @@
[dcl.attr.annotation]
# 9 Declarations [[dcl]](./#dcl)
## 9.13 Attributes [[dcl.attr]](dcl.attr#annotation)
### 9.13.12 Annotations [dcl.attr.annotation]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L10191)
An annotation may be applied to any declaration of a
type,
type alias,
variable,
function,
namespace,
enumerator,[*base-specifier*](class.derived.general#nt:base-specifier "11.7.1General[class.derived.general]"), or
non-static data member[.](#1.sentence-1)
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L10202)
Let E be the expressionstd::meta::reflect_constant([*constant-expression*](expr.const#nt:constant-expression "7.7Constant expressions[expr.const]"))[.](#2.sentence-1)
E shall be a constant expression;
the result of E is the [*underlying constant*](#def:constant,underlying "9.13.12Annotations[dcl.attr.annotation]") of the annotation[.](#2.sentence-2)
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L10208)
Each [*annotation*](dcl.attr.grammar#nt:annotation "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") produces a unique annotation[.](#3.sentence-1)
[4](#4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L10211)
Substituting into an [*annotation*](dcl.attr.grammar#nt:annotation "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") is not in the immediate context[.](#4.sentence-1)
[*Example [1](#example-1)*:
[[=1]] void f();[[=2, =3, =2]] void g();void g [[=4, =2]] ();f has one annotation
and g has five annotations[.](#4.sentence-2)
These can be queried with metafunctions
such as std::meta::annotations_of ([[meta.reflection.annotation]](meta.reflection.annotation "21.4.18Annotation reflection"))[.](#4.sentence-3)
— *end example*]
[*Example [2](#example-2)*: template<class T>[[=T::type()]] void f(T t);
void f(int);
void g() { f(0); // OK f('0'); // error, substituting into the annotation results in an invalid expression} — *end example*]

View File

@@ -0,0 +1,57 @@
[dcl.attr.assume]
# 9 Declarations [[dcl]](./#dcl)
## 9.13 Attributes [[dcl.attr]](dcl.attr#assume)
### 9.13.3 Assumption attribute [dcl.attr.assume]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L9666)
The [*attribute-token*](dcl.attr.grammar#nt:attribute-token "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") assume may be applied to a null statement;
such a statement is an [*assumption*](#def:assumption "9.13.3Assumption attribute[dcl.attr.assume]")[.](#1.sentence-1)
An [*attribute-argument-clause*](dcl.attr.grammar#nt:attribute-argument-clause "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") shall be present and
shall have the form:
( [*conditional-expression*](expr.cond#nt:conditional-expression "7.6.16Conditional operator[expr.cond]") )
The expression is contextually converted to bool ([[conv.general]](conv.general "7.3.1General"))[.](#1.sentence-2)
The expression is not evaluated[.](#1.sentence-3)
If the converted expression would evaluate to true at the point where the assumption appears,
the assumption has no effect[.](#1.sentence-4)
Otherwise,
evaluation of the assumption has runtime-undefined behavior[.](#1.sentence-5)
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L9682)
[*Note [1](#note-1)*:
The expression is potentially evaluated ([[basic.def.odr]](basic.def.odr "6.3One-definition rule"))[.](#2.sentence-1)
The use of assumptions is intended to allow implementations
to analyze the form of the expression and
deduce information used to optimize the program[.](#2.sentence-2)
Implementations are not required to deduce
any information from any particular assumption[.](#2.sentence-3)
It is expected that the value of
a [*has-attribute-expression*](cpp.cond#nt:has-attribute-expression "15.2Conditional inclusion[cpp.cond]") for the assume attribute
is 0 if an implementation does not attempt to deduce
any such information from assumptions[.](#2.sentence-4)
— *end note*]
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L9697)
[*Example [1](#example-1)*: int divide_by_32(int x) {[[assume(x >= 0)]]; return x/32; // The instructions produced for the division// may omit handling of negative values.}int f(int y) {[[assume(++y == 43)]]; // y is not incrementedreturn y; // statement may be replaced with return 42;} — *end example*]

View File

@@ -0,0 +1,82 @@
[dcl.attr.deprecated]
# 9 Declarations [[dcl]](./#dcl)
## 9.13 Attributes [[dcl.attr]](dcl.attr#deprecated)
### 9.13.4 Deprecated attribute [dcl.attr.deprecated]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L9715)
The [*attribute-token*](dcl.attr.grammar#nt:attribute-token "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") deprecated can be used to mark names and entities
whose use is still allowed, but is discouraged for some reason[.](#1.sentence-1)
[*Note [1](#note-1)*:
In particular,deprecated is appropriate for names and entities that are deemed obsolescent or
unsafe[.](#1.sentence-2)
— *end note*]
An[*attribute-argument-clause*](dcl.attr.grammar#nt:attribute-argument-clause "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") may be present and, if present, it shall have the form:
( [*unevaluated-string*](lex.string.uneval#nt:unevaluated-string "5.13.6Unevaluated strings[lex.string.uneval]") )
[*Note [2](#note-2)*:
The [*unevaluated-string*](lex.string.uneval#nt:unevaluated-string "5.13.6Unevaluated strings[lex.string.uneval]") in the [*attribute-argument-clause*](dcl.attr.grammar#nt:attribute-argument-clause "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") can be used to explain the rationale for deprecation and/or to suggest a replacing entity[.](#1.sentence-3)
— *end note*]
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L9733)
The attribute may be applied to the declaration of
a class,
a type alias,
a variable,
a non-static data member,
a function,
a namespace,
an enumeration,
an enumerator,
a concept, or
a template specialization[.](#2.sentence-1)
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L9746)
An entity declared without the deprecated attribute can later be redeclared
with the attribute and vice-versa[.](#3.sentence-1)
[*Note [3](#note-3)*:
Thus, an entity initially declared without the
attribute can be marked as deprecated by a subsequent redeclaration[.](#3.sentence-2)
However, after an entity
is marked as deprecated, later redeclarations do not un-deprecate the entity[.](#3.sentence-3)
— *end note*]
Redeclarations using different forms of the attribute (with or without the[*attribute-argument-clause*](dcl.attr.grammar#nt:attribute-argument-clause "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") or with different[*attribute-argument-clause*](dcl.attr.grammar#nt:attribute-argument-clause "9.13.1Attribute syntax and semantics[dcl.attr.grammar]")*s*) are allowed[.](#3.sentence-4)
[4](#4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L9758)
*Recommended practice*: Implementations should use the deprecated attribute to produce a diagnostic
message in case the program refers to a name or entity other than to declare it, after a
declaration that specifies the attribute[.](#4.sentence-1)
The diagnostic message should include the text provided
within the [*attribute-argument-clause*](dcl.attr.grammar#nt:attribute-argument-clause "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") of any deprecated attribute applied
to the name or entity[.](#4.sentence-2)
The value of
a [*has-attribute-expression*](cpp.cond#nt:has-attribute-expression "15.2Conditional inclusion[cpp.cond]") for the deprecated attribute
should be 0 unless the implementation can issue such diagnostic messages[.](#4.sentence-3)

View File

@@ -0,0 +1,49 @@
[dcl.attr.fallthrough]
# 9 Declarations [[dcl]](./#dcl)
## 9.13 Attributes [[dcl.attr]](dcl.attr#fallthrough)
### 9.13.5 Fallthrough attribute [dcl.attr.fallthrough]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L9773)
The [*attribute-token*](dcl.attr.grammar#nt:attribute-token "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") fallthrough may be applied to a [null statement](stmt.expr#def:statement,null "8.3Expression statement[stmt.expr]"); such a statement is a fallthrough statement[.](#1.sentence-1)
No [*attribute-argument-clause*](dcl.attr.grammar#nt:attribute-argument-clause "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") shall be present[.](#1.sentence-2)
A fallthrough statement may only appear within
an enclosing switch statement ([[stmt.switch]](stmt.switch "8.5.3The switch statement"))[.](#1.sentence-3)
The next statement that would be executed after a fallthrough statement
shall be a labeled statement whose label is a case label or
default label for the same switch statement and,
if the fallthrough statement is contained in an iteration statement,
the next statement shall be part of the same execution of
the substatement of the innermost enclosing iteration statement[.](#1.sentence-4)
The program is ill-formed if there is no such statement[.](#1.sentence-5)
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L9789)
*Recommended practice*: The use of a fallthrough statement should suppress
a warning that an implementation might otherwise issue
for a case or default label that is reachable
from another case or default label along some path of execution[.](#2.sentence-1)
The value of
a [*has-attribute-expression*](cpp.cond#nt:has-attribute-expression "15.2Conditional inclusion[cpp.cond]") for the fallthrough attribute
should be 0 if the attribute does not cause suppression of such warnings[.](#2.sentence-2)
Implementations should issue a warning
if a fallthrough statement is not dynamically reachable[.](#2.sentence-3)
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L9802)
[*Example [1](#example-1)*: void f(int n) {void g(), h(), i(); switch (n) {case 1:case 2: g(); [[fallthrough]]; case 3: // warning on fallthrough discourageddo {[[fallthrough]]; // error: next statement is not part of the same substatement execution} while (false); case 6:do {[[fallthrough]]; // error: next statement is not part of the same substatement execution} while (n--); case 7:while (false) {[[fallthrough]]; // error: next statement is not part of the same substatement execution}case 5: h(); case 4: // implementation may warn on fallthrough i(); [[fallthrough]]; // error}} — *end example*]

View File

@@ -0,0 +1,213 @@
[dcl.attr.grammar]
# 9 Declarations [[dcl]](./#dcl)
## 9.13 Attributes [[dcl.attr]](dcl.attr#grammar)
### 9.13.1 Attribute syntax and semantics [dcl.attr.grammar]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L9349)
Attributes and annotations specify additional information for various source constructs
such as types, variables, names, contract assertions, blocks, or translation units[.](#1.sentence-1)
[attribute-specifier-seq:](#nt:attribute-specifier-seq "9.13.1Attribute syntax and semantics[dcl.attr.grammar]")
[*attribute-specifier*](#nt:attribute-specifier "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") [*attribute-specifier-seq*](#nt:attribute-specifier-seq "9.13.1Attribute syntax and semantics[dcl.attr.grammar]")opt
[attribute-specifier:](#nt:attribute-specifier "9.13.1Attribute syntax and semantics[dcl.attr.grammar]")
[ [ [*attribute-using-prefix*](#nt:attribute-using-prefix "9.13.1Attribute syntax and semantics[dcl.attr.grammar]")opt [*attribute-list*](#nt:attribute-list "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") ] ]
[ [ [*annotation-list*](#nt:annotation-list "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") ] ]
[*alignment-specifier*](#nt:alignment-specifier "9.13.1Attribute syntax and semantics[dcl.attr.grammar]")
[alignment-specifier:](#nt:alignment-specifier "9.13.1Attribute syntax and semantics[dcl.attr.grammar]")
alignas ( [*type-id*](dcl.name#nt:type-id "9.3.2Type names[dcl.name]") ...opt )
alignas ( [*constant-expression*](expr.const#nt:constant-expression "7.7Constant expressions[expr.const]") ...opt )
[attribute-using-prefix:](#nt:attribute-using-prefix "9.13.1Attribute syntax and semantics[dcl.attr.grammar]")
using [*attribute-namespace*](#nt:attribute-namespace "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") :
[attribute-list:](#nt:attribute-list "9.13.1Attribute syntax and semantics[dcl.attr.grammar]")
[*attribute*](#nt:attribute "9.13.1Attribute syntax and semantics[dcl.attr.grammar]")opt
[*attribute-list*](#nt:attribute-list "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") , [*attribute*](#nt:attribute "9.13.1Attribute syntax and semantics[dcl.attr.grammar]")opt
[*attribute*](#nt:attribute "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") ...
[*attribute-list*](#nt:attribute-list "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") , [*attribute*](#nt:attribute "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") ...
[annotation-list:](#nt:annotation-list "9.13.1Attribute syntax and semantics[dcl.attr.grammar]")
[*annotation*](#nt:annotation "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") ...opt
[*annotation-list*](#nt:annotation-list "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") , [*annotation*](#nt:annotation "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") ...opt
[attribute:](#nt:attribute "9.13.1Attribute syntax and semantics[dcl.attr.grammar]")
[*attribute-token*](#nt:attribute-token "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") [*attribute-argument-clause*](#nt:attribute-argument-clause "9.13.1Attribute syntax and semantics[dcl.attr.grammar]")opt
[annotation:](#nt:annotation "9.13.1Attribute syntax and semantics[dcl.attr.grammar]")
= [*constant-expression*](expr.const#nt:constant-expression "7.7Constant expressions[expr.const]")
[attribute-token:](#nt:attribute-token "9.13.1Attribute syntax and semantics[dcl.attr.grammar]")
[*identifier*](lex.name#nt:identifier "5.11Identifiers[lex.name]")
[*attribute-scoped-token*](#nt:attribute-scoped-token "9.13.1Attribute syntax and semantics[dcl.attr.grammar]")
[attribute-scoped-token:](#nt:attribute-scoped-token "9.13.1Attribute syntax and semantics[dcl.attr.grammar]")
[*attribute-namespace*](#nt:attribute-namespace "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") :: [*identifier*](lex.name#nt:identifier "5.11Identifiers[lex.name]")
[attribute-namespace:](#nt:attribute-namespace "9.13.1Attribute syntax and semantics[dcl.attr.grammar]")
[*identifier*](lex.name#nt:identifier "5.11Identifiers[lex.name]")
[attribute-argument-clause:](#nt:attribute-argument-clause "9.13.1Attribute syntax and semantics[dcl.attr.grammar]")
( [*balanced-token-seq*](#nt:balanced-token-seq "9.13.1Attribute syntax and semantics[dcl.attr.grammar]")opt )
[balanced-token-seq:](#nt:balanced-token-seq "9.13.1Attribute syntax and semantics[dcl.attr.grammar]")
[*balanced-token*](#nt:balanced-token "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") [*balanced-token-seq*](#nt:balanced-token-seq "9.13.1Attribute syntax and semantics[dcl.attr.grammar]")opt
[balanced-token:](#nt:balanced-token "9.13.1Attribute syntax and semantics[dcl.attr.grammar]")
( [*balanced-token-seq*](#nt:balanced-token-seq "9.13.1Attribute syntax and semantics[dcl.attr.grammar]")opt )
[ [*balanced-token-seq*](#nt:balanced-token-seq "9.13.1Attribute syntax and semantics[dcl.attr.grammar]")opt ]
{ [*balanced-token-seq*](#nt:balanced-token-seq "9.13.1Attribute syntax and semantics[dcl.attr.grammar]")opt }
[: [*balanced-token-seq*](#nt:balanced-token-seq "9.13.1Attribute syntax and semantics[dcl.attr.grammar]")opt :]
any [*token*](lex.token#nt:token "5.10Tokens[lex.token]") other than (, ), [, ], {, }, [:, or :]
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L9437)
If an [*attribute-specifier*](#nt:attribute-specifier "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") contains an [*attribute-using-prefix*](#nt:attribute-using-prefix "9.13.1Attribute syntax and semantics[dcl.attr.grammar]"),
the [*attribute-list*](#nt:attribute-list "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") following that [*attribute-using-prefix*](#nt:attribute-using-prefix "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") shall not contain an [*attribute-scoped-token*](#nt:attribute-scoped-token "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") and every [*attribute-token*](#nt:attribute-token "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") in that [*attribute-list*](#nt:attribute-list "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") is treated as if
its [*identifier*](lex.name#nt:identifier "5.11Identifiers[lex.name]") were prefixed with N::,
where N is the [*attribute-namespace*](#nt:attribute-namespace "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") specified in the [*attribute-using-prefix*](#nt:attribute-using-prefix "9.13.1Attribute syntax and semantics[dcl.attr.grammar]")[.](#2.sentence-1)
[*Note [1](#note-1)*:
This rule imposes no constraints on how
an [*attribute-using-prefix*](#nt:attribute-using-prefix "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") affects the tokens in an [*attribute-argument-clause*](#nt:attribute-argument-clause "9.13.1Attribute syntax and semantics[dcl.attr.grammar]")[.](#2.sentence-2)
— *end note*]
[*Example [1](#example-1)*: [[using CC: opt(1), debug]] // same as [[CC::opt(1), CC::debug]]void f() {}[[using CC: opt(1)]] [[CC::debug]] // same as [[CC::opt(1)]] [[CC::debug]]void g() {}[[using CC: CC::opt(1)]] // error: cannot combine using and scoped attribute tokenvoid h() {} — *end example*]
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L9463)
[*Note [2](#note-2)*:
For each individual attribute, the form of the[*balanced-token-seq*](#nt:balanced-token-seq "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") will be specified[.](#3.sentence-1)
— *end note*]
[4](#4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L9469)
In an [*attribute-list*](#nt:attribute-list "9.13.1Attribute syntax and semantics[dcl.attr.grammar]"), an ellipsis may appear only if that[*attribute*](#nt:attribute "9.13.1Attribute syntax and semantics[dcl.attr.grammar]")'s specification permits it[.](#4.sentence-1)
An [*attribute*](#nt:attribute "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") followed
by an ellipsis is a [pack expansion](temp.variadic#def:pack_expansion "13.7.4Variadic templates[temp.variadic]")[.](#4.sentence-2)
An [*attribute-specifier*](#nt:attribute-specifier "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") that contains
an [*attribute-list*](#nt:attribute-list "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") with no [*attribute*](#nt:attribute "9.13.1Attribute syntax and semantics[dcl.attr.grammar]")*s* and no [*alignment-specifier*](#nt:alignment-specifier "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") has no effect[.](#4.sentence-3)
The order in which the [*attribute-token*](#nt:attribute-token "9.13.1Attribute syntax and semantics[dcl.attr.grammar]")*s* appear in an[*attribute-list*](#nt:attribute-list "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") is not significant[.](#4.sentence-4)
If a[keyword](lex.key "5.12Keywords[lex.key]") or an [alternative token](lex.digraph "5.9Alternative tokens[lex.digraph]") that satisfies the syntactic requirements
of an [*identifier*](lex.name#nt:identifier "5.11Identifiers[lex.name]") ([[lex.name]](lex.name "5.11Identifiers")) is
contained in
an [*attribute-token*](#nt:attribute-token "9.13.1Attribute syntax and semantics[dcl.attr.grammar]"), it is considered an identifier[.](#4.sentence-5)
No[name lookup](basic.lookup "6.5Name lookup[basic.lookup]") is performed on any of the identifiers contained in an[*attribute-token*](#nt:attribute-token "9.13.1Attribute syntax and semantics[dcl.attr.grammar]")[.](#4.sentence-6)
The [*attribute-token*](#nt:attribute-token "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") determines additional
requirements on the [*attribute-argument-clause*](#nt:attribute-argument-clause "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") (if any)[.](#4.sentence-7)
[5](#5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L9488)
An [*annotation*](#nt:annotation "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") followed by an ellipsis
is a pack expansion ([[temp.variadic]](temp.variadic "13.7.4Variadic templates"))[.](#5.sentence-1)
[6](#6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L9492)
Each [*attribute-specifier-seq*](#nt:attribute-specifier-seq "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") is said to [*appertain*](#def:appertain "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") to some entity or
statement, identified by the syntactic context
where it appears ([[stmt]](stmt "8Statements"), [[dcl]](dcl "9Declarations"), [[dcl.decl]](dcl.decl "9.3Declarators"))[.](#6.sentence-1)
If an [*attribute-specifier-seq*](#nt:attribute-specifier-seq "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") that appertains to some
entity or statement contains an [*attribute*](#nt:attribute "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") or [*alignment-specifier*](#nt:alignment-specifier "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") that
is not allowed to apply to that
entity or statement, the program is ill-formed[.](#6.sentence-2)
If an [*attribute-specifier-seq*](#nt:attribute-specifier-seq "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") appertains to a friend declaration ([[class.friend]](class.friend "11.8.4Friends")), that declaration shall be a
definition[.](#6.sentence-3)
[*Note [3](#note-3)*:
An [*attribute-specifier-seq*](#nt:attribute-specifier-seq "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") cannot appertain to
an explicit instantiation ([[temp.explicit]](temp.explicit "13.9.3Explicit instantiation"))[.](#6.sentence-4)
— *end note*]
[7](#7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L9507)
For an [*attribute-token*](#nt:attribute-token "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") (including an [*attribute-scoped-token*](#nt:attribute-scoped-token "9.13.1Attribute syntax and semantics[dcl.attr.grammar]"))
not specified in this document, the
behavior is implementation-defined;
any such [*attribute-token*](#nt:attribute-token "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") that is not recognized by the implementation
is ignored[.](#7.sentence-1)
[*Note [4](#note-4)*:
A program is ill-formed if it contains an [*attribute*](#nt:attribute "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") specified in [[dcl.attr]](dcl.attr "9.13Attributes") that violates
the rules specifying to which entity or statement the attribute can apply or
the syntax rules for the attribute's [*attribute-argument-clause*](#nt:attribute-argument-clause "9.13.1Attribute syntax and semantics[dcl.attr.grammar]"), if any[.](#7.sentence-2)
— *end note*]
[*Note [5](#note-5)*:
The [*attribute*](#nt:attribute "9.13.1Attribute syntax and semantics[dcl.attr.grammar]")*s* specified in [[dcl.attr]](dcl.attr "9.13Attributes") have optional semantics:
given a well-formed program,
removing all instances of any one of those [*attribute*](#nt:attribute "9.13.1Attribute syntax and semantics[dcl.attr.grammar]")*s* results in a program whose set of possible executions ([[intro.abstract]](intro.abstract "4.1.2Abstract machine"))
for a given input is
a subset of those of the original program for the same input,
absent implementation-defined guarantees
with respect to that [*attribute*](#nt:attribute "9.13.1Attribute syntax and semantics[dcl.attr.grammar]")[.](#7.sentence-3)
— *end note*]
An [*attribute-token*](#nt:attribute-token "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") is reserved for future standardization if
- [(7.1)](#7.1)
it is not an [*attribute-scoped-token*](#nt:attribute-scoped-token "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") and
is not specified in this document, or
- [(7.2)](#7.2)
it is an [*attribute-scoped-token*](#nt:attribute-scoped-token "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") and
its [*attribute-namespace*](#nt:attribute-namespace "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") isstd followed by zero or more digits[.](#7.sentence-4)
Each implementation should choose a distinctive name for the[*attribute-namespace*](#nt:attribute-namespace "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") in an [*attribute-scoped-token*](#nt:attribute-scoped-token "9.13.1Attribute syntax and semantics[dcl.attr.grammar]")[.](#7.sentence-5)
[8](#8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L9542)
Two consecutive left square bracket tokens shall appear only
when introducing an [*attribute-specifier*](#nt:attribute-specifier "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") or
within the [*balanced-token-seq*](#nt:balanced-token-seq "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") of
an [*attribute-argument-clause*](#nt:attribute-argument-clause "9.13.1Attribute syntax and semantics[dcl.attr.grammar]")[.](#8.sentence-1)
[*Note [6](#note-6)*:
If two consecutive left square brackets appear
where an [*attribute-specifier*](#nt:attribute-specifier "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") is not allowed, the program is ill-formed even
if the brackets match an alternative grammar production[.](#8.sentence-2)
— *end note*]
[*Example [2](#example-2)*: int p[10];void f() {int x = 42, y[5]; int(p[[x] { return x; }()]); // error: invalid attribute on a nested [*declarator-id*](dcl.decl.general#nt:declarator-id "9.3.1General[dcl.decl.general]") and// not a function-style cast of an element of p. y[[] { return 2; }()] = 2; // error even though attributes are not allowed in this context.int i [[vendor::attr([[]])]]; // well-formed implementation-defined attribute.} — *end example*]

View File

@@ -0,0 +1,47 @@
[dcl.attr.indet]
# 9 Declarations [[dcl]](./#dcl)
## 9.13 Attributes [[dcl.attr]](dcl.attr#indet)
### 9.13.6 Indeterminate storage [dcl.attr.indet]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L9837)
The [*attribute-token*](dcl.attr.grammar#nt:attribute-token "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") indeterminate may be applied
to the definition of a block variable with automatic storage duration or
to a [*parameter-declaration*](dcl.fct#nt:parameter-declaration "9.3.4.6Functions[dcl.fct]") of a function declaration[.](#1.sentence-1)
No [*attribute-argument-clause*](dcl.attr.grammar#nt:attribute-argument-clause "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") shall be present[.](#1.sentence-2)
The attribute specifies
that the storage of an object with automatic storage duration
is initially indeterminate rather than erroneous ([[basic.indet]](basic.indet "6.8.5Indeterminate and erroneous values"))[.](#1.sentence-3)
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L9846)
If a function parameter is declared with the indeterminate attribute,
it shall be so declared in the first declaration of its function[.](#2.sentence-1)
If a function parameter is declared with
the indeterminate attribute in the first declaration of its function
in one translation unit and
the same function is declared without the indeterminate attribute
on the same parameter in its first declaration in another translation unit,
the program is ill-formed, no diagnostic required[.](#2.sentence-2)
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L9856)
[*Note [1](#note-1)*:
Reading from an uninitialized variable
that is marked [[indeterminate]] can cause undefined behavior[.](#3.sentence-1)
void f(int);void g() {int x [[indeterminate]], y;
f(y); // erroneous behavior ([[basic.indet]](basic.indet "6.8.5Indeterminate and erroneous values")) f(x); // undefined behavior}struct T { T() {}int x;};int h(T t [[indeterminate]]) { f(t.x); // undefined behavior when called belowreturn 0;}int _ = h(T()); — *end note*]

View File

@@ -0,0 +1,59 @@
[dcl.attr.likelihood]
# 9 Declarations [[dcl]](./#dcl)
## 9.13 Attributes [[dcl.attr]](dcl.attr#likelihood)
### 9.13.7 Likelihood attributes [dcl.attr.likelihood]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L9884)
The [*attribute-token*](dcl.attr.grammar#nt:attribute-token "9.13.1Attribute syntax and semantics[dcl.attr.grammar]")*s*likely and unlikely may be applied to labels or statements[.](#1.sentence-1)
No [*attribute-argument-clause*](dcl.attr.grammar#nt:attribute-argument-clause "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") shall be present[.](#1.sentence-2)
The [*attribute-token*](dcl.attr.grammar#nt:attribute-token "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") likely shall not appear in an [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") that contains the [*attribute-token*](dcl.attr.grammar#nt:attribute-token "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") unlikely[.](#1.sentence-3)
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L9893)
[*Note [1](#note-1)*:
The use of the likely attribute
is intended to allow implementations to optimize for
the case where paths of execution including it
are arbitrarily more likely
than any alternative path of execution
that does not include such an attribute on a statement or label[.](#2.sentence-1)
The use of the unlikely attribute
is intended to allow implementations to optimize for
the case where paths of execution including it
are arbitrarily more unlikely
than any alternative path of execution
that does not include such an attribute on a statement or label[.](#2.sentence-2)
It is expected that the value of a [*has-attribute-expression*](cpp.cond#nt:has-attribute-expression "15.2Conditional inclusion[cpp.cond]") for the likely and unlikely attributes
is 0 if the implementation does not attempt to use these attributes
for such optimizations[.](#2.sentence-3)
A path of execution includes a label
if and only if it contains a jump to that label[.](#2.sentence-4)
— *end note*]
[*Note [2](#note-2)*:
Excessive usage of either of these attributes
is liable to result in performance degradation[.](#2.sentence-5)
— *end note*]
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L9920)
[*Example [1](#example-1)*: void g(int);int f(int n) {if (n > 5) [[unlikely]] { // n > 5 is considered to be arbitrarily unlikely g(0); return n * 2 + 1; }switch (n) {case 1: g(1); [[fallthrough]]; [[likely]] case 2: // n == 2 is considered to be arbitrarily more g(2); // likely than any other value of nbreak; }return 3;} — *end example*]

View File

@@ -0,0 +1,96 @@
[dcl.attr.nodiscard]
# 9 Declarations [[dcl]](./#dcl)
## 9.13 Attributes [[dcl.attr]](dcl.attr#nodiscard)
### 9.13.9 Nodiscard attribute [dcl.attr.nodiscard]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L10007)
The [*attribute-token*](dcl.attr.grammar#nt:attribute-token "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") nodiscard may be applied to a function or a lambda call operator or
to the declaration of a class or enumeration[.](#1.sentence-1)
An [*attribute-argument-clause*](dcl.attr.grammar#nt:attribute-argument-clause "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") may be present
and, if present, shall have the form:
( [*unevaluated-string*](lex.string.uneval#nt:unevaluated-string "5.13.6Unevaluated strings[lex.string.uneval]") )
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L10017)
A name or entity declared without the nodiscard attribute
can later be redeclared with the attribute and vice-versa[.](#2.sentence-1)
[*Note [1](#note-1)*:
Thus, an entity initially declared without the attribute
can be marked as nodiscard by a subsequent redeclaration[.](#2.sentence-2)
However, after an entity is marked as nodiscard,
later redeclarations do not remove the nodiscard from the entity[.](#2.sentence-3)
— *end note*]
Redeclarations using different forms of the attribute
(with or without the [*attribute-argument-clause*](dcl.attr.grammar#nt:attribute-argument-clause "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") or with different [*attribute-argument-clause*](dcl.attr.grammar#nt:attribute-argument-clause "9.13.1Attribute syntax and semantics[dcl.attr.grammar]")*s*)
are allowed[.](#2.sentence-4)
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L10033)
A [*nodiscard type*](#def:type,nodiscard "9.13.9Nodiscard attribute[dcl.attr.nodiscard]") is
a (possibly cv-qualified) class or enumeration type
marked nodiscard in a reachable declaration[.](#3.sentence-1)
A [*nodiscard call*](#def:call,nodiscard "9.13.9Nodiscard attribute[dcl.attr.nodiscard]") is either
- [(3.1)](#3.1)
a function call expression ([[expr.call]](expr.call "7.6.1.3Function call"))
that calls a function declared nodiscard in a reachable declaration or
whose return type is a nodiscard type, or
- [(3.2)](#3.2)
an explicit type
conversion ([[expr.type.conv]](expr.type.conv "7.6.1.4Explicit type conversion (functional notation)"), [[expr.static.cast]](expr.static.cast "7.6.1.9Static cast"), [[expr.cast]](expr.cast "7.6.3Explicit type conversion (cast notation)"))
that constructs an object through
a constructor declared nodiscard in a reachable declaration, or
that initializes an object of a nodiscard type[.](#3.sentence-2)
[4](#4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L10051)
*Recommended practice*: Appearance of a nodiscard call as
a potentially-evaluated discarded-value expression ([[expr.prop]](expr.prop "7.2Properties of expressions"))
of non-void type
is discouraged unless explicitly cast to void[.](#4.sentence-1)
Implementations should issue a warning in such cases[.](#4.sentence-2)
The value of
a [*has-attribute-expression*](cpp.cond#nt:has-attribute-expression "15.2Conditional inclusion[cpp.cond]") for the nodiscard attribute
should be 0 unless the implementation can issue such warnings[.](#4.sentence-3)
[*Note [2](#note-2)*:
This is typically because discarding the return value
of a nodiscard call has surprising consequences[.](#4.sentence-4)
— *end note*]
The [*unevaluated-string*](lex.string.uneval#nt:unevaluated-string "5.13.6Unevaluated strings[lex.string.uneval]") in a nodiscard [*attribute-argument-clause*](dcl.attr.grammar#nt:attribute-argument-clause "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") should be used in the message of the warning
as the rationale for why the result should not be discarded[.](#4.sentence-5)
[5](#5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L10070)
[*Example [1](#example-1)*: struct [[nodiscard]] my_scopeguard { /* ... */ };struct my_unique { my_unique() = default; // does not acquire resource[[nodiscard]] my_unique(int fd) { /* ... */ } // acquires resource~my_unique() noexcept { /* ... */ } // releases resource, if any/* ... */};struct [[nodiscard]] error_info { /* ... */ };
error_info enable_missile_safety_mode();void launch_missiles();void test_missiles() { my_scopeguard(); // warning encouraged(void)my_scopeguard(), // warning not encouraged, cast to void launch_missiles(); // comma operator, statement continues my_unique(42); // warning encouraged my_unique(); // warning not encouraged enable_missile_safety_mode(); // warning encouraged launch_missiles();} error_info &foo();void f() { foo(); } // warning not encouraged: not a nodiscard call, because neither// the (reference) return type nor the function is declared nodiscard — *end example*]

View File

@@ -0,0 +1,55 @@
[dcl.attr.noreturn]
# 9 Declarations [[dcl]](./#dcl)
## 9.13 Attributes [[dcl.attr]](dcl.attr#noreturn)
### 9.13.10 Noreturn attribute [dcl.attr.noreturn]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L10101)
The [*attribute-token*](dcl.attr.grammar#nt:attribute-token "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") noreturn specifies that a function does not return[.](#1.sentence-1)
No [*attribute-argument-clause*](dcl.attr.grammar#nt:attribute-argument-clause "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") shall be present[.](#1.sentence-2)
The attribute may be applied to a function or a lambda call operator[.](#1.sentence-3)
The first declaration of a function shall
specify the noreturn attribute if any declaration of that function specifies thenoreturn attribute[.](#1.sentence-4)
If a function is declared with the noreturn attribute in one
translation unit and the same function is declared without the noreturn attribute in another
translation unit, the program is ill-formed, no diagnostic required[.](#1.sentence-5)
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L10111)
If a function f is invoked where f was previously declared with the noreturn attribute and that invocation eventually returns,
the behavior is runtime-undefined[.](#2.sentence-1)
[*Note [1](#note-1)*:
The function can
terminate by throwing an exception[.](#2.sentence-2)
— *end note*]
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L10120)
*Recommended practice*: Implementations should issue a
warning if a function marked [[noreturn]] might return[.](#3.sentence-1)
The value of
a [*has-attribute-expression*](cpp.cond#nt:has-attribute-expression "15.2Conditional inclusion[cpp.cond]") for the noreturn attribute
should be 0 unless the implementation can issue such warnings[.](#3.sentence-2)
[4](#4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L10128)
[*Example [1](#example-1)*: [[ noreturn ]] void f() {throw "error"; // OK}[[ noreturn ]] void q(int i) { // behavior is undefined if called with an argument <= 0if (i > 0)throw "positive";} — *end example*]

View File

@@ -0,0 +1,45 @@
[dcl.attr.nouniqueaddr]
# 9 Declarations [[dcl]](./#dcl)
## 9.13 Attributes [[dcl.attr]](dcl.attr#nouniqueaddr)
### 9.13.11 No unique address attribute [dcl.attr.nouniqueaddr]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L10145)
The [*attribute-token*](dcl.attr.grammar#nt:attribute-token "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") no_unique_address specifies that a non-static data member
is a potentially-overlapping subobject ([[intro.object]](intro.object "6.8.2Object model"))[.](#1.sentence-1)
No [*attribute-argument-clause*](dcl.attr.grammar#nt:attribute-argument-clause "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") shall be present[.](#1.sentence-2)
The attribute may appertain to a non-static data member
other than a bit-field[.](#1.sentence-3)
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L10153)
[*Note [1](#note-1)*:
The non-static data member can share the address of
another non-static data member or that of a base class,
and any padding that would normally be inserted
at the end of the object
can be reused as storage for other members[.](#2.sentence-1)
— *end note*]
*Recommended practice*: The value of a [*has-attribute-expression*](cpp.cond#nt:has-attribute-expression "15.2Conditional inclusion[cpp.cond]") for the no_unique_address attribute
should be 0 for a given implementation
unless this attribute can cause a potentially-overlapping subobject
to have zero size[.](#2.sentence-2)
[*Example [1](#example-1)*: template<typename Key, typename Value, typename Hash, typename Pred, typename Allocator>class hash_map {[[no_unique_address]] Hash hasher; [[no_unique_address]] Pred pred; [[no_unique_address]] Allocator alloc;
Bucket *buckets; // ...public:// ...};
Here, hasher, pred, and alloc could have the same address as buckets if their respective types are all empty[.](#2.sentence-3)
— *end example*]

View File

@@ -0,0 +1,73 @@
[dcl.attr.unused]
# 9 Declarations [[dcl]](./#dcl)
## 9.13 Attributes [[dcl.attr]](dcl.attr#unused)
### 9.13.8 Maybe unused attribute [dcl.attr.unused]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L9947)
The [*attribute-token*](dcl.attr.grammar#nt:attribute-token "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") maybe_unused indicates that a name, label, or entity is possibly intentionally unused[.](#1.sentence-1)
No [*attribute-argument-clause*](dcl.attr.grammar#nt:attribute-argument-clause "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") shall be present[.](#1.sentence-2)
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L9952)
The attribute may be applied to the declaration of a class,
type alias,
variable (including a structured binding declaration),
structured binding,
result binding ([[dcl.contract.res]](dcl.contract.res "9.4.2Referring to the result object")),
non-static data member,
function,
enumeration, or
enumerator, or
to an [*identifier*](lex.name#nt:identifier "5.11Identifiers[lex.name]") label ([[stmt.label]](stmt.label "8.2Label"))[.](#2.sentence-1)
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L9964)
A name or entity declared without the maybe_unused attribute
can later be redeclared with the attribute
and vice versa[.](#3.sentence-1)
An entity is considered marked
after the first declaration that marks it[.](#3.sentence-2)
[4](#4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L9971)
*Recommended practice*: For an entity marked maybe_unused,
implementations should not emit a warning
that the entity or its structured bindings (if any)
are used or unused[.](#4.sentence-1)
For a structured binding declaration not marked maybe_unused,
implementations should not emit such a warning unless
all of its structured bindings are unused[.](#4.sentence-2)
For a label to which maybe_unused is applied,
implementations should not emit a warning that the label is used or unused[.](#4.sentence-3)
The value of
a [*has-attribute-expression*](cpp.cond#nt:has-attribute-expression "15.2Conditional inclusion[cpp.cond]") for the maybe_unused attribute
should be 0 if the attribute does not cause suppression of such warnings[.](#4.sentence-4)
[5](#5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L9987)
[*Example [1](#example-1)*: [[maybe_unused]] void f([[maybe_unused]] bool thing1, [[maybe_unused]] bool thing2) {[[maybe_unused]] bool b = thing1 && thing2;
assert(b);#ifdef NDEBUG goto x;#endif[[maybe_unused]] x:}
Implementations should not warn that b or x is unused,
whether or not NDEBUG is defined[.](#5.sentence-1)
— *end example*]

136
cppdraft/dcl/constexpr.md Normal file
View File

@@ -0,0 +1,136 @@
[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.8The 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.7Constant 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.6The 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.7Constant 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.6The constexpr and consteval specifiers[dcl.constexpr]") if
it is not a coroutine ([[dcl.fct.def.coroutine]](dcl.fct.def.coroutine "9.6.4Coroutine 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.7Constant expressions")) and
- [(4.2)](#4.2)
copy elision is not performed in a constant expression ([[class.copy.elision]](class.copy.elision "11.9.6Copy/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.7Constant 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*]

50
cppdraft/dcl/constinit.md Normal file
View File

@@ -0,0 +1,50 @@
[dcl.constinit]
# 9 Declarations [[dcl]](./#dcl)
## 9.2 Specifiers [[dcl.spec]](dcl.spec#dcl.constinit)
### 9.2.7 The constinit specifier [dcl.constinit]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L1056)
The constinit specifier shall be applied only
to a declaration of a variable with static or thread storage duration
or to a structured binding declaration ([[dcl.struct.bind]](dcl.struct.bind "9.7Structured binding declarations"))[.](#1.sentence-1)
[*Note [1](#note-1)*:
A structured binding declaration introduces a uniquely named variable,
to which the constinit specifier applies[.](#1.sentence-2)
— *end note*]
If the specifier is applied to any declaration of a variable,
it shall be applied to the initializing declaration[.](#1.sentence-3)
No diagnostic is required if no constinit declaration
is reachable at the point of the initializing declaration[.](#1.sentence-4)
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L1069)
If a variable declared with the constinit specifier has
dynamic initialization ([[basic.start.dynamic]](basic.start.dynamic "6.10.3.3Dynamic initialization of non-block variables")), the program is ill-formed,
even if the implementation would perform that initialization as
a static initialization ([[basic.start.static]](basic.start.static "6.10.3.2Static initialization"))[.](#2.sentence-1)
[*Note [2](#note-2)*:
The constinit specifier ensures that the variable
is initialized during static initialization[.](#2.sentence-2)
— *end note*]
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L1079)
[*Example [1](#example-1)*: const char * g() { return "dynamic initialization"; }constexpr const char * f(bool p) { return p ? "constant initializer" : g(); }constinit const char * c = f(true); // OKconstinit const char * d = f(false); // error — *end example*]

266
cppdraft/dcl/contract.md Normal file
View File

@@ -0,0 +1,266 @@
[dcl.contract]
# 9 Declarations [[dcl]](./#dcl)
## 9.4 Function contract specifiers [dcl.contract]
### [9.4.1](#func) General [[dcl.contract.func]](dcl.contract.func)
[function-contract-specifier-seq:](#nt:function-contract-specifier-seq "9.4.1General[dcl.contract.func]")
[*function-contract-specifier*](#nt:function-contract-specifier "9.4.1General[dcl.contract.func]") [*function-contract-specifier-seq*](#nt:function-contract-specifier-seq "9.4.1General[dcl.contract.func]")opt
[function-contract-specifier:](#nt:function-contract-specifier "9.4.1General[dcl.contract.func]")
[*precondition-specifier*](#nt:precondition-specifier "9.4.1General[dcl.contract.func]")
[*postcondition-specifier*](#nt:postcondition-specifier "9.4.1General[dcl.contract.func]")
[precondition-specifier:](#nt:precondition-specifier "9.4.1General[dcl.contract.func]")
pre [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1Attribute syntax and semantics[dcl.attr.grammar]")opt ( [*conditional-expression*](expr.cond#nt:conditional-expression "7.6.16Conditional operator[expr.cond]") )
[postcondition-specifier:](#nt:postcondition-specifier "9.4.1General[dcl.contract.func]")
post [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1Attribute syntax and semantics[dcl.attr.grammar]")opt ( [*result-name-introducer*](#nt:result-name-introducer "9.4.2Referring to the result object[dcl.contract.res]")opt [*conditional-expression*](expr.cond#nt:conditional-expression "7.6.16Conditional operator[expr.cond]") )
[1](#func-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L4613)
A [*function contract assertion*](#def:contract_assertion,function "9.4.1General[dcl.contract.func]") is a contract assertion ([[basic.contract.general]](basic.contract.general "6.11.1General"))
associated with a function[.](#func-1.sentence-1)
A [*precondition-specifier*](#nt:precondition-specifier "9.4.1General[dcl.contract.func]") introduces a [*precondition assertion*](#def:assertion,precondition "9.4.1General[dcl.contract.func]"),
which is a function contract assertion
associated with entering a function[.](#func-1.sentence-2)
A [*postcondition-specifier*](#nt:postcondition-specifier "9.4.1General[dcl.contract.func]") introduces a [*postcondition assertion*](#def:assertion,postcondition "9.4.1General[dcl.contract.func]"),
which is a function contract assertion
associated with exiting a function normally[.](#func-1.sentence-3)
[*Note [1](#func-note-1)*:
A postcondition assertion
is not associated with exiting a function
in any other fashion,
such as via an exception ([[expr.throw]](expr.throw "7.6.18Throwing an exception"))
or via a call to longjmp ([[csetjmp.syn]](csetjmp.syn "17.14.3Header <csetjmp> synopsis"))[.](#func-1.sentence-4)
— *end note*]
[2](#func-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L4635)
The predicate ([[basic.contract.general]](basic.contract.general "6.11.1General"))
of a function contract assertion
is its [*conditional-expression*](expr.cond#nt:conditional-expression "7.6.16Conditional operator[expr.cond]") contextually converted to bool[.](#func-2.sentence-1)
[3](#func-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L4641)
Each [*function-contract-specifier*](#nt:function-contract-specifier "9.4.1General[dcl.contract.func]") of a [*function-contract-specifier-seq*](#nt:function-contract-specifier-seq "9.4.1General[dcl.contract.func]") (if any)
of an unspecified first declaration ([[basic.def]](basic.def "6.2Declarations and definitions"))
of a function
introduces a corresponding function contract assertion for that function[.](#func-3.sentence-1)
The optional [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") following pre or post appertains to the introduced contract assertion[.](#func-3.sentence-2)
[*Note [2](#func-note-2)*:
The [*function-contract-specifier-seq*](#nt:function-contract-specifier-seq "9.4.1General[dcl.contract.func]") of a [*lambda-declarator*](expr.prim.lambda.general#nt:lambda-declarator "7.5.6.1General[expr.prim.lambda.general]") applies to the function call operator or operator template
of the corresponding closure type ([[expr.prim.lambda.closure]](expr.prim.lambda.closure "7.5.6.2Closure types"))[.](#func-3.sentence-3)
— *end note*]
[4](#func-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L4657)
A declaration D of a function or function template *f* that is not a first declaration shall have either
no [*function-contract-specifier-seq*](#nt:function-contract-specifier-seq "9.4.1General[dcl.contract.func]") or the same [*function-contract-specifier-seq*](#nt:function-contract-specifier-seq "9.4.1General[dcl.contract.func]") (see below)
as any first declaration F reachable from D[.](#func-4.sentence-1)
If D and F are
in different translation units,
a diagnostic is required only if D is attached to a named module[.](#func-4.sentence-2)
If a declaration F1 is a
first declaration of f in one translation unit and
a declaration F2 is a
first declaration of f in another translation unit,F1 and F2 shall specify the same[*function-contract-specifier-seq*](#nt:function-contract-specifier-seq "9.4.1General[dcl.contract.func]"), no diagnostic required[.](#func-4.sentence-3)
[5](#func-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L4675)
A [*function-contract-specifier-seq*](#nt:function-contract-specifier-seq "9.4.1General[dcl.contract.func]") S1 is the same as
a [*function-contract-specifier-seq*](#nt:function-contract-specifier-seq "9.4.1General[dcl.contract.func]") S2 if S1 and S2 consist of
the same [*function-contract-specifier*](#nt:function-contract-specifier "9.4.1General[dcl.contract.func]")*s* in the same order[.](#func-5.sentence-1)
A [*function-contract-specifier*](#nt:function-contract-specifier "9.4.1General[dcl.contract.func]") C1 on a function declaration D1 is
the same as
a [*function-contract-specifier*](#nt:function-contract-specifier "9.4.1General[dcl.contract.func]") C2 on a function declaration D2 if
- [(5.1)](#func-5.1)
their predicates P1 and P2 would
satisfy the one-definition rule ([[basic.def.odr]](basic.def.odr "6.3One-definition rule"))
if placed in function definitions on
the declarations D1 and D2, respectively, except for
* [(5.1.1)](#func-5.1.1)
renaming of the parameters of *f*,
* [(5.1.2)](#func-5.1.2)
renaming of template parameters of
a template enclosing , and
* [(5.1.3)](#func-5.1.3)
renaming of the result binding ([[dcl.contract.res]](#res "9.4.2Referring to the result object")), if any,
and,
if D1 and D2 are in different translation units,
corresponding entities defined within each predicate
behave as if there is a single entity with a single definition, and
- [(5.2)](#func-5.2)
both C1 and C2 specify a [*result-name-introducer*](#nt:result-name-introducer "9.4.2Referring to the result object[dcl.contract.res]") or neither do[.](#func-5.sentence-2)
If this condition is not met
solely due to the comparison of two [*lambda-expression*](expr.prim.lambda.general#nt:lambda-expression "7.5.6.1General[expr.prim.lambda.general]")*s* that are contained within P1 and P2,
no diagnostic is required[.](#func-5.sentence-3)
[*Note [3](#func-note-3)*:
Equivalent[*function-contract-specifier-seq*](#nt:function-contract-specifier-seq "9.4.1General[dcl.contract.func]")*s* apply to all uses and definitions
of a function across all translation units[.](#func-5.sentence-4)
— *end note*]
[*Example [1](#func-example-1)*: bool b1, b2;
void f() pre (b1) pre ([]{ return b2; }());void f(); // OK, [*function-contract-specifier*](#nt:function-contract-specifier "9.4.1General[dcl.contract.func]")*s* omittedvoid f() pre (b1) pre ([]{ return b2; }()); // error: closures have different types.void f() pre (b1); // error: [*function-contract-specifier*](#nt:function-contract-specifier "9.4.1General[dcl.contract.func]")*s* only partially repeatedint g() post(r : b1);int g() post(b1); // error: mismatched [*result-name-introducer*](#nt:result-name-introducer "9.4.2Referring to the result object[dcl.contract.res]") presencenamespace N {void h() pre (b1); bool b1; void h() pre (b1); // error: [*function-contract-specifier*](#nt:function-contract-specifier "9.4.1General[dcl.contract.func]")*s* differ according to// the one-definition rule ([[basic.def.odr]](basic.def.odr "6.3One-definition rule")).} — *end example*]
[6](#func-6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L4745)
A virtual function ([[class.virtual]](class.virtual "11.7.3Virtual functions")),
a deleted function ([[dcl.fct.def.delete]](dcl.fct.def.delete "9.6.3Deleted definitions")),
or a function defaulted on its first declaration ([[dcl.fct.def.default]](dcl.fct.def.default "9.6.2Explicitly-defaulted functions"))
shall not have a [*function-contract-specifier-seq*](#nt:function-contract-specifier-seq "9.4.1General[dcl.contract.func]")[.](#func-6.sentence-1)
[7](#func-7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L4751)
If the predicate of a postcondition assertion
of a function *f* odr-uses ([[basic.def.odr]](basic.def.odr "6.3One-definition rule"))
a non-reference parameter of *f*,
that parameter
and the corresponding parameter on all declarations of *f* shall have const type[.](#func-7.sentence-1)
[*Note [4](#func-note-4)*:
This requirement applies
even to declarations that do not specify the [*postcondition-specifier*](#nt:postcondition-specifier "9.4.1General[dcl.contract.func]")[.](#func-7.sentence-2)
Parameters with array or function type
will decay to non-const types
even if a const qualifier is present[.](#func-7.sentence-3)
[*Example [2](#func-example-2)*: int f(const int i[10]) post(r : r == i[0]); // error: i has type const int * (not int* const). — *end example*]
— *end note*]
[8](#func-8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L4773)
[*Note [5](#func-note-5)*:
The function contract assertions of a function
are evaluated even when invoked indirectly,
such as through a pointer to function or a pointer to member function[.](#func-8.sentence-1)
A pointer to function,
pointer to member function,
or function type alias
cannot have a [*function-contract-specifier-seq*](#nt:function-contract-specifier-seq "9.4.1General[dcl.contract.func]") associated directly with it[.](#func-8.sentence-2)
— *end note*]
[9](#func-9)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L4785)
The function contract assertions of a function
are considered to be [*needed*](#def:needed,function_contract_assertion "9.4.1General[dcl.contract.func]") ([[temp.inst]](temp.inst "13.9.2Implicit instantiation")) when
- [(9.1)](#func-9.1)
the function is odr-used ([[basic.def.odr]](basic.def.odr "6.3One-definition rule")) or
- [(9.2)](#func-9.2)
the function is defined[.](#func-9.sentence-1)
[*Note [6](#func-note-6)*:
Overload resolution does not consider[*function-contract-specifier*](#nt:function-contract-specifier "9.4.1General[dcl.contract.func]")*s* ([[temp.deduct]](temp.deduct "13.10.3Template argument deduction"), [[temp.inst]](temp.inst "13.9.2Implicit instantiation"))[.](#func-9.sentence-2)
[*Example [3](#func-example-3)*: template <typename T> void f(T t) pre( t == "" );template <typename T> void f(T&& t);void g(){ f(5); // error: ambiguous} — *end example*]
— *end note*]
### [9.4.2](#res) Referring to the result object [[dcl.contract.res]](dcl.contract.res)
[attributed-identifier:](#nt:attributed-identifier "9.4.2Referring to the result object[dcl.contract.res]")
[*identifier*](lex.name#nt:identifier "5.11Identifiers[lex.name]") [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1Attribute syntax and semantics[dcl.attr.grammar]")opt
[result-name-introducer:](#nt:result-name-introducer "9.4.2Referring to the result object[dcl.contract.res]")
[*attributed-identifier*](#nt:attributed-identifier "9.4.2Referring to the result object[dcl.contract.res]") :
[1](#res-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L4822)
The [*result-name-introducer*](#nt:result-name-introducer "9.4.2Referring to the result object[dcl.contract.res]") of a [*postcondition-specifier*](#nt:postcondition-specifier "9.4.1General[dcl.contract.func]") is a declaration[.](#res-1.sentence-1)
The [*result-name-introducer*](#nt:result-name-introducer "9.4.2Referring to the result object[dcl.contract.res]") introduces the [*identifier*](lex.name#nt:identifier "5.11Identifiers[lex.name]") as the name of a [*result binding*](#def:result_binding "9.4.2Referring to the result object[dcl.contract.res]") of the associated function[.](#res-1.sentence-2)
If a postcondition assertion has a [*result-name-introducer*](#nt:result-name-introducer "9.4.2Referring to the result object[dcl.contract.res]") and the return type of the function is cv void,
the program is ill-formed[.](#res-1.sentence-3)
A result binding denotes
the object or reference returned by
invocation of that function[.](#res-1.sentence-4)
The type of a result binding
is the return type of its associated function[.](#res-1.sentence-5)
The optional [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") of the [*attributed-identifier*](#nt:attributed-identifier "9.4.2Referring to the result object[dcl.contract.res]") in the [*result-name-introducer*](#nt:result-name-introducer "9.4.2Referring to the result object[dcl.contract.res]") appertains to the result binding so introduced[.](#res-1.sentence-6)
[*Note [1](#res-note-1)*:
An [*id-expression*](expr.prim.id.general#nt:id-expression "7.5.5.1General[expr.prim.id.general]") that names a result binding is a const lvalue ([[expr.prim.id.unqual]](expr.prim.id.unqual "7.5.5.2Unqualified names"))[.](#res-1.sentence-7)
— *end note*]
[*Example [1](#res-example-1)*: int f() post(r : r == 1){return 1;}int i = f(); // Postcondition check succeeds. — *end example*]
[*Example [2](#res-example-2)*: struct A {};struct B { B() {} B(const B&) {}};
template <typename T> T f(T* const ptr) post(r: &r == ptr){return {};}int main() { A a = f(&a); // The postcondition check can fail if the implementation introduces// a temporary for the return value ([[class.temporary]](class.temporary "6.8.7Temporary objects")). B b = f(&b); // The postcondition check succeeds, no temporary is introduced.} — *end example*]
[2](#res-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L4882)
When the declared return type
of a non-templated function
contains a placeholder type,
a [*postcondition-specifier*](#nt:postcondition-specifier "9.4.1General[dcl.contract.func]") with a [*result-name-introducer*](#nt:result-name-introducer "9.4.2Referring to the result object[dcl.contract.res]") shall be present only on a definition[.](#res-2.sentence-1)
[*Example [3](#res-example-3)*: auto g(auto&) post (r: r >= 0); // OK, g is a template.auto h() post (r: r >= 0); // error: cannot name the return valueauto k() post (r: r >= 0) // OK{return 0;} — *end example*]

View File

@@ -0,0 +1,215 @@
[dcl.contract.func]
# 9 Declarations [[dcl]](./#dcl)
## 9.4 Function contract specifiers [[dcl.contract]](dcl.contract#func)
### 9.4.1 General [dcl.contract.func]
[function-contract-specifier-seq:](#nt:function-contract-specifier-seq "9.4.1General[dcl.contract.func]")
[*function-contract-specifier*](#nt:function-contract-specifier "9.4.1General[dcl.contract.func]") [*function-contract-specifier-seq*](#nt:function-contract-specifier-seq "9.4.1General[dcl.contract.func]")opt
[function-contract-specifier:](#nt:function-contract-specifier "9.4.1General[dcl.contract.func]")
[*precondition-specifier*](#nt:precondition-specifier "9.4.1General[dcl.contract.func]")
[*postcondition-specifier*](#nt:postcondition-specifier "9.4.1General[dcl.contract.func]")
[precondition-specifier:](#nt:precondition-specifier "9.4.1General[dcl.contract.func]")
pre [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1Attribute syntax and semantics[dcl.attr.grammar]")opt ( [*conditional-expression*](expr.cond#nt:conditional-expression "7.6.16Conditional operator[expr.cond]") )
[postcondition-specifier:](#nt:postcondition-specifier "9.4.1General[dcl.contract.func]")
post [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1Attribute syntax and semantics[dcl.attr.grammar]")opt ( [*result-name-introducer*](dcl.contract.res#nt:result-name-introducer "9.4.2Referring to the result object[dcl.contract.res]")opt [*conditional-expression*](expr.cond#nt:conditional-expression "7.6.16Conditional operator[expr.cond]") )
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L4613)
A [*function contract assertion*](#def:contract_assertion,function "9.4.1General[dcl.contract.func]") is a contract assertion ([[basic.contract.general]](basic.contract.general "6.11.1General"))
associated with a function[.](#1.sentence-1)
A [*precondition-specifier*](#nt:precondition-specifier "9.4.1General[dcl.contract.func]") introduces a [*precondition assertion*](#def:assertion,precondition "9.4.1General[dcl.contract.func]"),
which is a function contract assertion
associated with entering a function[.](#1.sentence-2)
A [*postcondition-specifier*](#nt:postcondition-specifier "9.4.1General[dcl.contract.func]") introduces a [*postcondition assertion*](#def:assertion,postcondition "9.4.1General[dcl.contract.func]"),
which is a function contract assertion
associated with exiting a function normally[.](#1.sentence-3)
[*Note [1](#note-1)*:
A postcondition assertion
is not associated with exiting a function
in any other fashion,
such as via an exception ([[expr.throw]](expr.throw "7.6.18Throwing an exception"))
or via a call to longjmp ([[csetjmp.syn]](csetjmp.syn "17.14.3Header <csetjmp> synopsis"))[.](#1.sentence-4)
— *end note*]
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L4635)
The predicate ([[basic.contract.general]](basic.contract.general "6.11.1General"))
of a function contract assertion
is its [*conditional-expression*](expr.cond#nt:conditional-expression "7.6.16Conditional operator[expr.cond]") contextually converted to bool[.](#2.sentence-1)
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L4641)
Each [*function-contract-specifier*](#nt:function-contract-specifier "9.4.1General[dcl.contract.func]") of a [*function-contract-specifier-seq*](#nt:function-contract-specifier-seq "9.4.1General[dcl.contract.func]") (if any)
of an unspecified first declaration ([[basic.def]](basic.def "6.2Declarations and definitions"))
of a function
introduces a corresponding function contract assertion for that function[.](#3.sentence-1)
The optional [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") following pre or post appertains to the introduced contract assertion[.](#3.sentence-2)
[*Note [2](#note-2)*:
The [*function-contract-specifier-seq*](#nt:function-contract-specifier-seq "9.4.1General[dcl.contract.func]") of a [*lambda-declarator*](expr.prim.lambda.general#nt:lambda-declarator "7.5.6.1General[expr.prim.lambda.general]") applies to the function call operator or operator template
of the corresponding closure type ([[expr.prim.lambda.closure]](expr.prim.lambda.closure "7.5.6.2Closure types"))[.](#3.sentence-3)
— *end note*]
[4](#4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L4657)
A declaration D of a function or function template *f* that is not a first declaration shall have either
no [*function-contract-specifier-seq*](#nt:function-contract-specifier-seq "9.4.1General[dcl.contract.func]") or the same [*function-contract-specifier-seq*](#nt:function-contract-specifier-seq "9.4.1General[dcl.contract.func]") (see below)
as any first declaration F reachable from D[.](#4.sentence-1)
If D and F are
in different translation units,
a diagnostic is required only if D is attached to a named module[.](#4.sentence-2)
If a declaration F1 is a
first declaration of f in one translation unit and
a declaration F2 is a
first declaration of f in another translation unit,F1 and F2 shall specify the same[*function-contract-specifier-seq*](#nt:function-contract-specifier-seq "9.4.1General[dcl.contract.func]"), no diagnostic required[.](#4.sentence-3)
[5](#5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L4675)
A [*function-contract-specifier-seq*](#nt:function-contract-specifier-seq "9.4.1General[dcl.contract.func]") S1 is the same as
a [*function-contract-specifier-seq*](#nt:function-contract-specifier-seq "9.4.1General[dcl.contract.func]") S2 if S1 and S2 consist of
the same [*function-contract-specifier*](#nt:function-contract-specifier "9.4.1General[dcl.contract.func]")*s* in the same order[.](#5.sentence-1)
A [*function-contract-specifier*](#nt:function-contract-specifier "9.4.1General[dcl.contract.func]") C1 on a function declaration D1 is
the same as
a [*function-contract-specifier*](#nt:function-contract-specifier "9.4.1General[dcl.contract.func]") C2 on a function declaration D2 if
- [(5.1)](#5.1)
their predicates P1 and P2 would
satisfy the one-definition rule ([[basic.def.odr]](basic.def.odr "6.3One-definition rule"))
if placed in function definitions on
the declarations D1 and D2, respectively, except for
* [(5.1.1)](#5.1.1)
renaming of the parameters of *f*,
* [(5.1.2)](#5.1.2)
renaming of template parameters of
a template enclosing , and
* [(5.1.3)](#5.1.3)
renaming of the result binding ([[dcl.contract.res]](dcl.contract.res "9.4.2Referring to the result object")), if any,
and,
if D1 and D2 are in different translation units,
corresponding entities defined within each predicate
behave as if there is a single entity with a single definition, and
- [(5.2)](#5.2)
both C1 and C2 specify a [*result-name-introducer*](dcl.contract.res#nt:result-name-introducer "9.4.2Referring to the result object[dcl.contract.res]") or neither do[.](#5.sentence-2)
If this condition is not met
solely due to the comparison of two [*lambda-expression*](expr.prim.lambda.general#nt:lambda-expression "7.5.6.1General[expr.prim.lambda.general]")*s* that are contained within P1 and P2,
no diagnostic is required[.](#5.sentence-3)
[*Note [3](#note-3)*:
Equivalent[*function-contract-specifier-seq*](#nt:function-contract-specifier-seq "9.4.1General[dcl.contract.func]")*s* apply to all uses and definitions
of a function across all translation units[.](#5.sentence-4)
— *end note*]
[*Example [1](#example-1)*: bool b1, b2;
void f() pre (b1) pre ([]{ return b2; }());void f(); // OK, [*function-contract-specifier*](#nt:function-contract-specifier "9.4.1General[dcl.contract.func]")*s* omittedvoid f() pre (b1) pre ([]{ return b2; }()); // error: closures have different types.void f() pre (b1); // error: [*function-contract-specifier*](#nt:function-contract-specifier "9.4.1General[dcl.contract.func]")*s* only partially repeatedint g() post(r : b1);int g() post(b1); // error: mismatched [*result-name-introducer*](dcl.contract.res#nt:result-name-introducer "9.4.2Referring to the result object[dcl.contract.res]") presencenamespace N {void h() pre (b1); bool b1; void h() pre (b1); // error: [*function-contract-specifier*](#nt:function-contract-specifier "9.4.1General[dcl.contract.func]")*s* differ according to// the one-definition rule ([[basic.def.odr]](basic.def.odr "6.3One-definition rule")).} — *end example*]
[6](#6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L4745)
A virtual function ([[class.virtual]](class.virtual "11.7.3Virtual functions")),
a deleted function ([[dcl.fct.def.delete]](dcl.fct.def.delete "9.6.3Deleted definitions")),
or a function defaulted on its first declaration ([[dcl.fct.def.default]](dcl.fct.def.default "9.6.2Explicitly-defaulted functions"))
shall not have a [*function-contract-specifier-seq*](#nt:function-contract-specifier-seq "9.4.1General[dcl.contract.func]")[.](#6.sentence-1)
[7](#7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L4751)
If the predicate of a postcondition assertion
of a function *f* odr-uses ([[basic.def.odr]](basic.def.odr "6.3One-definition rule"))
a non-reference parameter of *f*,
that parameter
and the corresponding parameter on all declarations of *f* shall have const type[.](#7.sentence-1)
[*Note [4](#note-4)*:
This requirement applies
even to declarations that do not specify the [*postcondition-specifier*](#nt:postcondition-specifier "9.4.1General[dcl.contract.func]")[.](#7.sentence-2)
Parameters with array or function type
will decay to non-const types
even if a const qualifier is present[.](#7.sentence-3)
[*Example [2](#example-2)*: int f(const int i[10]) post(r : r == i[0]); // error: i has type const int * (not int* const). — *end example*]
— *end note*]
[8](#8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L4773)
[*Note [5](#note-5)*:
The function contract assertions of a function
are evaluated even when invoked indirectly,
such as through a pointer to function or a pointer to member function[.](#8.sentence-1)
A pointer to function,
pointer to member function,
or function type alias
cannot have a [*function-contract-specifier-seq*](#nt:function-contract-specifier-seq "9.4.1General[dcl.contract.func]") associated directly with it[.](#8.sentence-2)
— *end note*]
[9](#9)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L4785)
The function contract assertions of a function
are considered to be [*needed*](#def:needed,function_contract_assertion "9.4.1General[dcl.contract.func]") ([[temp.inst]](temp.inst "13.9.2Implicit instantiation")) when
- [(9.1)](#9.1)
the function is odr-used ([[basic.def.odr]](basic.def.odr "6.3One-definition rule")) or
- [(9.2)](#9.2)
the function is defined[.](#9.sentence-1)
[*Note [6](#note-6)*:
Overload resolution does not consider[*function-contract-specifier*](#nt:function-contract-specifier "9.4.1General[dcl.contract.func]")*s* ([[temp.deduct]](temp.deduct "13.10.3Template argument deduction"), [[temp.inst]](temp.inst "13.9.2Implicit instantiation"))[.](#9.sentence-2)
[*Example [3](#example-3)*: template <typename T> void f(T t) pre( t == "" );template <typename T> void f(T&& t);void g(){ f(5); // error: ambiguous} — *end example*]
— *end note*]

View File

@@ -0,0 +1,56 @@
[dcl.contract.res]
# 9 Declarations [[dcl]](./#dcl)
## 9.4 Function contract specifiers [[dcl.contract]](dcl.contract#res)
### 9.4.2 Referring to the result object [dcl.contract.res]
[attributed-identifier:](#nt:attributed-identifier "9.4.2Referring to the result object[dcl.contract.res]")
[*identifier*](lex.name#nt:identifier "5.11Identifiers[lex.name]") [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1Attribute syntax and semantics[dcl.attr.grammar]")opt
[result-name-introducer:](#nt:result-name-introducer "9.4.2Referring to the result object[dcl.contract.res]")
[*attributed-identifier*](#nt:attributed-identifier "9.4.2Referring to the result object[dcl.contract.res]") :
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L4822)
The [*result-name-introducer*](#nt:result-name-introducer "9.4.2Referring to the result object[dcl.contract.res]") of a [*postcondition-specifier*](dcl.contract.func#nt:postcondition-specifier "9.4.1General[dcl.contract.func]") is a declaration[.](#1.sentence-1)
The [*result-name-introducer*](#nt:result-name-introducer "9.4.2Referring to the result object[dcl.contract.res]") introduces the [*identifier*](lex.name#nt:identifier "5.11Identifiers[lex.name]") as the name of a [*result binding*](#def:result_binding "9.4.2Referring to the result object[dcl.contract.res]") of the associated function[.](#1.sentence-2)
If a postcondition assertion has a [*result-name-introducer*](#nt:result-name-introducer "9.4.2Referring to the result object[dcl.contract.res]") and the return type of the function is cv void,
the program is ill-formed[.](#1.sentence-3)
A result binding denotes
the object or reference returned by
invocation of that function[.](#1.sentence-4)
The type of a result binding
is the return type of its associated function[.](#1.sentence-5)
The optional [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") of the [*attributed-identifier*](#nt:attributed-identifier "9.4.2Referring to the result object[dcl.contract.res]") in the [*result-name-introducer*](#nt:result-name-introducer "9.4.2Referring to the result object[dcl.contract.res]") appertains to the result binding so introduced[.](#1.sentence-6)
[*Note [1](#note-1)*:
An [*id-expression*](expr.prim.id.general#nt:id-expression "7.5.5.1General[expr.prim.id.general]") that names a result binding is a const lvalue ([[expr.prim.id.unqual]](expr.prim.id.unqual "7.5.5.2Unqualified names"))[.](#1.sentence-7)
— *end note*]
[*Example [1](#example-1)*: int f() post(r : r == 1){return 1;}int i = f(); // Postcondition check succeeds. — *end example*]
[*Example [2](#example-2)*: struct A {};struct B { B() {} B(const B&) {}};
template <typename T> T f(T* const ptr) post(r: &r == ptr){return {};}int main() { A a = f(&a); // The postcondition check can fail if the implementation introduces// a temporary for the return value ([[class.temporary]](class.temporary "6.8.7Temporary objects")). B b = f(&b); // The postcondition check succeeds, no temporary is introduced.} — *end example*]
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L4882)
When the declared return type
of a non-templated function
contains a placeholder type,
a [*postcondition-specifier*](dcl.contract.func#nt:postcondition-specifier "9.4.1General[dcl.contract.func]") with a [*result-name-introducer*](#nt:result-name-introducer "9.4.2Referring to the result object[dcl.contract.res]") shall be present only on a definition[.](#2.sentence-1)
[*Example [3](#example-3)*: auto g(auto&) post (r: r >= 0); // OK, g is a template.auto h() post (r: r >= 0); // error: cannot name the return valueauto k() post (r: r >= 0) // OK{return 0;} — *end example*]

1803
cppdraft/dcl/decl.md Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,143 @@
[dcl.decl.general]
# 9 Declarations [[dcl]](./#dcl)
## 9.3 Declarators [[dcl.decl]](dcl.decl#general)
### 9.3.1 General [dcl.decl.general]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L2376)
A declarator declares a single variable, function, or type, within a declaration[.](#1.sentence-1)
The[*init-declarator-list*](#nt:init-declarator-list "9.3.1General[dcl.decl.general]") appearing in a [*simple-declaration*](dcl.pre#nt:simple-declaration "9.1Preamble[dcl.pre]") is a comma-separated sequence of declarators,
each of which can have an initializer[.](#1.sentence-2)
[init-declarator-list:](#nt:init-declarator-list "9.3.1General[dcl.decl.general]")
[*init-declarator*](#nt:init-declarator "9.3.1General[dcl.decl.general]")
[*init-declarator-list*](#nt:init-declarator-list "9.3.1General[dcl.decl.general]") , [*init-declarator*](#nt:init-declarator "9.3.1General[dcl.decl.general]")
[init-declarator:](#nt:init-declarator "9.3.1General[dcl.decl.general]")
[*declarator*](#nt:declarator "9.3.1General[dcl.decl.general]") [*initializer*](dcl.init.general#nt:initializer "9.5.1General[dcl.init.general]")
[*declarator*](#nt:declarator "9.3.1General[dcl.decl.general]") [*requires-clause*](temp.pre#nt:requires-clause "13.1Preamble[temp.pre]")opt [*function-contract-specifier-seq*](dcl.contract.func#nt:function-contract-specifier-seq "9.4.1General[dcl.contract.func]")opt
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L2396)
In all contexts, a [*declarator*](#nt:declarator "9.3.1General[dcl.decl.general]") is interpreted as given below[.](#2.sentence-1)
Where an [*abstract-declarator*](dcl.name#nt:abstract-declarator "9.3.2Type names[dcl.name]") can be used (or omitted)
in place of a [*declarator*](#nt:declarator "9.3.1General[dcl.decl.general]") ([[dcl.fct]](dcl.fct "9.3.4.6Functions"), [[except.pre]](except.pre "14.1Preamble")),
it is as if a unique identifier were included in
the appropriate place ([[dcl.name]](dcl.name "9.3.2Type names"))[.](#2.sentence-2)
The preceding specifiers indicate
the type, storage duration, linkage, or other properties
of the entity or entities being declared[.](#2.sentence-3)
Each declarator specifies one entity and
(optionally) names it and/or
modifies the type of the specifiers with operators such as* (pointer to) and () (function returning)[.](#2.sentence-4)
[*Note [1](#note-1)*:
An [*init-declarator*](#nt:init-declarator "9.3.1General[dcl.decl.general]") can also specify an initializer ([[dcl.init]](dcl.init "9.5Initializers"))[.](#2.sentence-5)
— *end note*]
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L2413)
Each [*init-declarator*](#nt:init-declarator "9.3.1General[dcl.decl.general]") or [*member-declarator*](class.mem.general#nt:member-declarator "11.4.1General[class.mem.general]") in a declaration is analyzed separately as if it were in a declaration by itself[.](#3.sentence-1)
[*Note [2](#note-2)*:
A declaration with several declarators is usually equivalent to the corresponding
sequence of declarations each with a single declarator[.](#3.sentence-2)
That is,T D1, D2, ... Dn; is usually equivalent toT D1; T D2; ... T Dn; where T is a [*decl-specifier-seq*](dcl.spec.general#nt:decl-specifier-seq "9.2.1General[dcl.spec.general]") and each Di is
an [*init-declarator*](#nt:init-declarator "9.3.1General[dcl.decl.general]") or [*member-declarator*](class.mem.general#nt:member-declarator "11.4.1General[class.mem.general]")[.](#3.sentence-3)
One exception is when a name introduced by one of the[*declarator*](#nt:declarator "9.3.1General[dcl.decl.general]")*s* hides a type name used by the[*decl-specifier*](dcl.spec.general#nt:decl-specifier "9.2.1General[dcl.spec.general]")*s*, so that when the same[*decl-specifier*](dcl.spec.general#nt:decl-specifier "9.2.1General[dcl.spec.general]")*s* are used in a subsequent declaration,
they do not have the same meaning, as instruct S { /* ... */ };
S S, T; // declare two instances of struct S which is not equivalent tostruct S { /* ... */ };
S S;
S T; // error
Another exception is when T is auto ([[dcl.spec.auto]](dcl.spec.auto "9.2.9.7Placeholder type specifiers")),
for example:auto i = 1, j = 2.0; // error: deduced types for i and j do not match as opposed toauto i = 1; // OK, i deduced to have type intauto j = 2.0; // OK, j deduced to have type double
— *end note*]
[4](#4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L2456)
The optional [*requires-clause*](temp.pre#nt:requires-clause "13.1Preamble[temp.pre]") in an[*init-declarator*](#nt:init-declarator "9.3.1General[dcl.decl.general]") or [*member-declarator*](class.mem.general#nt:member-declarator "11.4.1General[class.mem.general]") shall be present only if the declarator declares a
templated function ([[temp.pre]](temp.pre "13.1Preamble"))[.](#4.sentence-1)
When present after a declarator, the [*requires-clause*](temp.pre#nt:requires-clause "13.1Preamble[temp.pre]") is called the [*trailing* ](#def:requires-clause,trailing "9.3.1General[dcl.decl.general]")*[*requires-clause*](temp.pre#nt:requires-clause "13.1Preamble[temp.pre]")*[.](#4.sentence-2)
The trailing [*requires-clause*](temp.pre#nt:requires-clause "13.1Preamble[temp.pre]") introduces the[*constraint-expression*](temp.constr.decl#nt:constraint-expression "13.5.3Constrained declarations[temp.constr.decl]") that results from interpreting
its [*constraint-logical-or-expression*](temp.pre#nt:constraint-logical-or-expression "13.1Preamble[temp.pre]") as a[*constraint-expression*](temp.constr.decl#nt:constraint-expression "13.5.3Constrained declarations[temp.constr.decl]")[.](#4.sentence-3)
[*Example [1](#example-1)*: void f1(int a) requires true; // error: non-templated functiontemplate<typename T>auto f2(T a) -> bool requires true; // OKtemplate<typename T>auto f3(T a) requires true -> bool; // error: [*requires-clause*](temp.pre#nt:requires-clause "13.1Preamble[temp.pre]") precedes [*trailing-return-type*](#nt:trailing-return-type "9.3.1General[dcl.decl.general]")void (*pf)() requires true; // error: constraint on a variablevoid g(int (*)() requires true); // error: constraint on a [*parameter-declaration*](dcl.fct#nt:parameter-declaration "9.3.4.6Functions[dcl.fct]")auto* p = new void(*)(char) requires true; // error: not a function declaration — *end example*]
[5](#5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L2485)
The optional [*function-contract-specifier-seq*](dcl.contract.func#nt:function-contract-specifier-seq "9.4.1General[dcl.contract.func]") ([[dcl.contract.func]](dcl.contract.func "9.4.1General"))
in an [*init-declarator*](#nt:init-declarator "9.3.1General[dcl.decl.general]") shall be present only if
the [*declarator*](#nt:declarator "9.3.1General[dcl.decl.general]") declares a function[.](#5.sentence-1)
[6](#6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L2491)
Declarators have the syntax
[declarator:](#nt:declarator "9.3.1General[dcl.decl.general]")
[*ptr-declarator*](#nt:ptr-declarator "9.3.1General[dcl.decl.general]")
[*noptr-declarator*](#nt:noptr-declarator "9.3.1General[dcl.decl.general]") [*parameters-and-qualifiers*](#nt:parameters-and-qualifiers "9.3.1General[dcl.decl.general]") [*trailing-return-type*](#nt:trailing-return-type "9.3.1General[dcl.decl.general]")
[ptr-declarator:](#nt:ptr-declarator "9.3.1General[dcl.decl.general]")
[*noptr-declarator*](#nt:noptr-declarator "9.3.1General[dcl.decl.general]")
[*ptr-operator*](#nt:ptr-operator "9.3.1General[dcl.decl.general]") [*ptr-declarator*](#nt:ptr-declarator "9.3.1General[dcl.decl.general]")
[noptr-declarator:](#nt:noptr-declarator "9.3.1General[dcl.decl.general]")
[*declarator-id*](#nt:declarator-id "9.3.1General[dcl.decl.general]") [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1Attribute syntax and semantics[dcl.attr.grammar]")opt
[*noptr-declarator*](#nt:noptr-declarator "9.3.1General[dcl.decl.general]") [*parameters-and-qualifiers*](#nt:parameters-and-qualifiers "9.3.1General[dcl.decl.general]")
[*noptr-declarator*](#nt:noptr-declarator "9.3.1General[dcl.decl.general]") [ [*constant-expression*](expr.const#nt:constant-expression "7.7Constant expressions[expr.const]")opt ] [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1Attribute syntax and semantics[dcl.attr.grammar]")opt
( [*ptr-declarator*](#nt:ptr-declarator "9.3.1General[dcl.decl.general]") )
[parameters-and-qualifiers:](#nt:parameters-and-qualifiers "9.3.1General[dcl.decl.general]")
( [*parameter-declaration-clause*](dcl.fct#nt:parameter-declaration-clause "9.3.4.6Functions[dcl.fct]") ) [*cv-qualifier-seq*](#nt:cv-qualifier-seq "9.3.1General[dcl.decl.general]")opt
[*ref-qualifier*](#nt:ref-qualifier "9.3.1General[dcl.decl.general]")opt [*noexcept-specifier*](except.spec#nt:noexcept-specifier "14.5Exception specifications[except.spec]")opt [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1Attribute syntax and semantics[dcl.attr.grammar]")opt
[trailing-return-type:](#nt:trailing-return-type "9.3.1General[dcl.decl.general]")
-> [*type-id*](dcl.name#nt:type-id "9.3.2Type names[dcl.name]")
[ptr-operator:](#nt:ptr-operator "9.3.1General[dcl.decl.general]")
* [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1Attribute syntax and semantics[dcl.attr.grammar]")opt [*cv-qualifier-seq*](#nt:cv-qualifier-seq "9.3.1General[dcl.decl.general]")opt
& [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1Attribute syntax and semantics[dcl.attr.grammar]")opt
&& [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1Attribute syntax and semantics[dcl.attr.grammar]")opt
[*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3Qualified names[expr.prim.id.qual]") * [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1Attribute syntax and semantics[dcl.attr.grammar]")opt [*cv-qualifier-seq*](#nt:cv-qualifier-seq "9.3.1General[dcl.decl.general]")opt
[cv-qualifier-seq:](#nt:cv-qualifier-seq "9.3.1General[dcl.decl.general]")
[*cv-qualifier*](#nt:cv-qualifier "9.3.1General[dcl.decl.general]") [*cv-qualifier-seq*](#nt:cv-qualifier-seq "9.3.1General[dcl.decl.general]")opt
[cv-qualifier:](#nt:cv-qualifier "9.3.1General[dcl.decl.general]")
const
volatile
[ref-qualifier:](#nt:ref-qualifier "9.3.1General[dcl.decl.general]")
&
&&
[declarator-id:](#nt:declarator-id "9.3.1General[dcl.decl.general]")
...opt [*id-expression*](expr.prim.id.general#nt:id-expression "7.5.5.1General[expr.prim.id.general]")

336
cppdraft/dcl/enum.md Normal file
View File

@@ -0,0 +1,336 @@
[dcl.enum]
# 9 Declarations [[dcl]](./#dcl)
## 9.8 Enumerations [[enum]](enum#dcl.enum)
### 9.8.1 Enumeration declarations [dcl.enum]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L7788)
An enumeration is a distinct type ([[basic.compound]](basic.compound "6.9.4Compound types")) with named
constants[.](#1.sentence-1)
Its name becomes an [*enum-name*](#nt:enum-name "9.8.1Enumeration declarations[dcl.enum]") within its scope[.](#1.sentence-2)
[enum-name:](#nt:enum-name "9.8.1Enumeration declarations[dcl.enum]")
[*identifier*](lex.name#nt:identifier "5.11Identifiers[lex.name]")
[enum-specifier:](#nt:enum-specifier "9.8.1Enumeration declarations[dcl.enum]")
[*enum-head*](#nt:enum-head "9.8.1Enumeration declarations[dcl.enum]") { [*enumerator-list*](#nt:enumerator-list "9.8.1Enumeration declarations[dcl.enum]")opt }
[*enum-head*](#nt:enum-head "9.8.1Enumeration declarations[dcl.enum]") { [*enumerator-list*](#nt:enumerator-list "9.8.1Enumeration declarations[dcl.enum]") , }
[enum-head:](#nt:enum-head "9.8.1Enumeration declarations[dcl.enum]")
[*enum-key*](#nt:enum-key "9.8.1Enumeration declarations[dcl.enum]") [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1Attribute syntax and semantics[dcl.attr.grammar]")opt [*enum-head-name*](#nt:enum-head-name "9.8.1Enumeration declarations[dcl.enum]")opt [*enum-base*](#nt:enum-base "9.8.1Enumeration declarations[dcl.enum]")opt
[enum-head-name:](#nt:enum-head-name "9.8.1Enumeration declarations[dcl.enum]")
[*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3Qualified names[expr.prim.id.qual]")opt [*identifier*](lex.name#nt:identifier "5.11Identifiers[lex.name]")
[opaque-enum-declaration:](#nt:opaque-enum-declaration "9.8.1Enumeration declarations[dcl.enum]")
[*enum-key*](#nt:enum-key "9.8.1Enumeration declarations[dcl.enum]") [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1Attribute syntax and semantics[dcl.attr.grammar]")opt [*enum-head-name*](#nt:enum-head-name "9.8.1Enumeration declarations[dcl.enum]") [*enum-base*](#nt:enum-base "9.8.1Enumeration declarations[dcl.enum]")opt ;
[enum-key:](#nt:enum-key "9.8.1Enumeration declarations[dcl.enum]")
enum
enum class
enum struct
[enum-base:](#nt:enum-base "9.8.1Enumeration declarations[dcl.enum]")
: [*type-specifier-seq*](dcl.type.general#nt:type-specifier-seq "9.2.9.1General[dcl.type.general]")
[enumerator-list:](#nt:enumerator-list "9.8.1Enumeration declarations[dcl.enum]")
[*enumerator-definition*](#nt:enumerator-definition "9.8.1Enumeration declarations[dcl.enum]")
[*enumerator-list*](#nt:enumerator-list "9.8.1Enumeration declarations[dcl.enum]") , [*enumerator-definition*](#nt:enumerator-definition "9.8.1Enumeration declarations[dcl.enum]")
[enumerator-definition:](#nt:enumerator-definition "9.8.1Enumeration declarations[dcl.enum]")
[*enumerator*](#nt:enumerator "9.8.1Enumeration declarations[dcl.enum]")
[*enumerator*](#nt:enumerator "9.8.1Enumeration declarations[dcl.enum]") = [*constant-expression*](expr.const#nt:constant-expression "7.7Constant expressions[expr.const]")
[enumerator:](#nt:enumerator "9.8.1Enumeration declarations[dcl.enum]")
[*identifier*](lex.name#nt:identifier "5.11Identifiers[lex.name]") [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1Attribute syntax and semantics[dcl.attr.grammar]")opt
The optional [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") in the [*enum-head*](#nt:enum-head "9.8.1Enumeration declarations[dcl.enum]") and
the [*opaque-enum-declaration*](#nt:opaque-enum-declaration "9.8.1Enumeration declarations[dcl.enum]") appertains to the enumeration; the attributes
in that [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") are thereafter considered attributes of the
enumeration whenever it is named[.](#1.sentence-3)
A : following
“enum [*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3Qualified names[expr.prim.id.qual]")opt [*identifier*](lex.name#nt:identifier "5.11Identifiers[lex.name]")”
within the [*decl-specifier-seq*](dcl.spec.general#nt:decl-specifier-seq "9.2.1General[dcl.spec.general]") of a [*member-declaration*](class.mem.general#nt:member-declaration "11.4.1General[class.mem.general]") is parsed as part of an [*enum-base*](#nt:enum-base "9.8.1Enumeration declarations[dcl.enum]")[.](#1.sentence-4)
[*Note [1](#note-1)*:
This resolves a potential ambiguity between the declaration of an enumeration
with an [*enum-base*](#nt:enum-base "9.8.1Enumeration declarations[dcl.enum]") and the declaration of an unnamed bit-field of enumeration
type[.](#1.sentence-5)
[*Example [1](#example-1)*: struct S {enum E : int {}; enum E : int {}; // error: redeclaration of enumeration}; — *end example*]
— *end note*]
The [*identifier*](lex.name#nt:identifier "5.11Identifiers[lex.name]") in an [*enum-head-name*](#nt:enum-head-name "9.8.1Enumeration declarations[dcl.enum]") is not looked up and is introduced by
the [*enum-specifier*](#nt:enum-specifier "9.8.1Enumeration declarations[dcl.enum]") or [*opaque-enum-declaration*](#nt:opaque-enum-declaration "9.8.1Enumeration declarations[dcl.enum]")[.](#1.sentence-6)
If the [*enum-head-name*](#nt:enum-head-name "9.8.1Enumeration declarations[dcl.enum]") of an [*opaque-enum-declaration*](#nt:opaque-enum-declaration "9.8.1Enumeration declarations[dcl.enum]") contains
a [*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3Qualified names[expr.prim.id.qual]"),
the declaration shall be an [explicit specialization](temp.expl.spec "13.9.4Explicit specialization[temp.expl.spec]")[.](#1.sentence-7)
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L7875)
The enumeration type declared with an [*enum-key*](#nt:enum-key "9.8.1Enumeration declarations[dcl.enum]") of only enum is an [*unscoped enumeration*](#def:enumeration,unscoped "9.8.1Enumeration declarations[dcl.enum]"),
and its [*enumerator*](#nt:enumerator "9.8.1Enumeration declarations[dcl.enum]")*s* are [*unscoped enumerators*](#def:enumerator,unscoped "9.8.1Enumeration declarations[dcl.enum]")[.](#2.sentence-1)
The [*enum-key*](#nt:enum-key "9.8.1Enumeration declarations[dcl.enum]")*s* enum class andenum struct are semantically equivalent; an enumeration
type declared with one of these is a [*scoped enumeration*](#def:enumeration,scoped "9.8.1Enumeration declarations[dcl.enum]"),
and its [*enumerator*](#nt:enumerator "9.8.1Enumeration declarations[dcl.enum]")*s* are [*scoped enumerators*](#def:enumerator,scoped "9.8.1Enumeration declarations[dcl.enum]")[.](#2.sentence-2)
The optional [*enum-head-name*](#nt:enum-head-name "9.8.1Enumeration declarations[dcl.enum]") shall not be omitted in the declaration of a scoped enumeration[.](#2.sentence-3)
The [*type-specifier-seq*](dcl.type.general#nt:type-specifier-seq "9.2.9.1General[dcl.type.general]") of an [*enum-base*](#nt:enum-base "9.8.1Enumeration declarations[dcl.enum]") shall name an integral type; any cv-qualification is ignored[.](#2.sentence-4)
An [*opaque-enum-declaration*](#nt:opaque-enum-declaration "9.8.1Enumeration declarations[dcl.enum]") declaring an unscoped enumeration shall
not omit the [*enum-base*](#nt:enum-base "9.8.1Enumeration declarations[dcl.enum]")[.](#2.sentence-5)
The identifiers in an [*enumerator-list*](#nt:enumerator-list "9.8.1Enumeration declarations[dcl.enum]") are declared as
constants, and can appear wherever constants are required[.](#2.sentence-6)
The same identifier shall not appear as
the name of multiple enumerators in an [*enumerator-list*](#nt:enumerator-list "9.8.1Enumeration declarations[dcl.enum]")[.](#2.sentence-7)
An [*enumerator-definition*](#nt:enumerator-definition "9.8.1Enumeration declarations[dcl.enum]") with = gives the associated[*enumerator*](#nt:enumerator "9.8.1Enumeration declarations[dcl.enum]") the value indicated by the[*constant-expression*](expr.const#nt:constant-expression "7.7Constant expressions[expr.const]")[.](#2.sentence-8)
An [*enumerator-definition*](#nt:enumerator-definition "9.8.1Enumeration declarations[dcl.enum]") without = gives the associated[*enumerator*](#nt:enumerator "9.8.1Enumeration declarations[dcl.enum]") the value zero
if it is the first [*enumerator-definition*](#nt:enumerator-definition "9.8.1Enumeration declarations[dcl.enum]"),
and the value of the previous [*enumerator*](#nt:enumerator "9.8.1Enumeration declarations[dcl.enum]") increased by one otherwise[.](#2.sentence-9)
[*Example [2](#example-2)*:
enum { a, b, c=0 };enum { d, e, f=e+2 }; defines a, c, and d to be zero, b ande to be 1, and f to be 3[.](#2.sentence-10)
— *end example*]
The optional [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") in an[*enumerator*](#nt:enumerator "9.8.1Enumeration declarations[dcl.enum]") appertains to that enumerator[.](#2.sentence-11)
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L7913)
An [*opaque-enum-declaration*](#nt:opaque-enum-declaration "9.8.1Enumeration declarations[dcl.enum]") is either a redeclaration
of an enumeration in the current scope or a declaration of a new enumeration[.](#3.sentence-1)
[*Note [2](#note-2)*:
An enumeration declared by an[*opaque-enum-declaration*](#nt:opaque-enum-declaration "9.8.1Enumeration declarations[dcl.enum]") has a fixed underlying type and is a
complete type[.](#3.sentence-2)
The list of enumerators can be provided in a later redeclaration
with an [*enum-specifier*](#nt:enum-specifier "9.8.1Enumeration declarations[dcl.enum]")[.](#3.sentence-3)
— *end note*]
A scoped enumeration
shall not be later redeclared as unscoped or with a different underlying type[.](#3.sentence-4)
An unscoped enumeration shall not be later redeclared as scoped and each
redeclaration shall include an [*enum-base*](#nt:enum-base "9.8.1Enumeration declarations[dcl.enum]") specifying the same
underlying type as in the original declaration[.](#3.sentence-5)
[4](#4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L7928)
If an [*enum-head-name*](#nt:enum-head-name "9.8.1Enumeration declarations[dcl.enum]") contains a[*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3Qualified names[expr.prim.id.qual]"),
the enclosing [*enum-specifier*](#nt:enum-specifier "9.8.1Enumeration declarations[dcl.enum]") or [*opaque-enum-declaration*](#nt:opaque-enum-declaration "9.8.1Enumeration declarations[dcl.enum]") D shall not inhabit a class scope and
shall correspond to one or more declarations nominable
in the class, class template, or namespace
to which the [*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3Qualified names[expr.prim.id.qual]") refers ([[basic.scope.scope]](basic.scope.scope "6.4.1General"))[.](#4.sentence-1)
All those declarations shall have the same target scope;
the target scope of D is that scope[.](#4.sentence-2)
[5](#5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L7940)
Each enumeration defines a type that is different from all other types[.](#5.sentence-1)
Each enumeration also has an [*underlying type*](#def:type,underlying,enumeration "9.8.1Enumeration declarations[dcl.enum]")[.](#5.sentence-2)
The underlying type can be explicitly specified using an [*enum-base*](#nt:enum-base "9.8.1Enumeration declarations[dcl.enum]")[.](#5.sentence-3)
For a scoped enumeration type, the underlying type is int if it is not
explicitly specified[.](#5.sentence-4)
In both of these cases, the underlying type is said to be[*fixed*](#def:type,underlying,fixed "9.8.1Enumeration declarations[dcl.enum]")[.](#5.sentence-5)
Following the closing brace of an [*enum-specifier*](#nt:enum-specifier "9.8.1Enumeration declarations[dcl.enum]"), each
enumerator has the type of its enumeration[.](#5.sentence-6)
If the underlying type is fixed, the type of each enumerator
prior to the closing brace is the underlying
type
and the [*constant-expression*](expr.const#nt:constant-expression "7.7Constant expressions[expr.const]") in the [*enumerator-definition*](#nt:enumerator-definition "9.8.1Enumeration declarations[dcl.enum]") shall be a[converted constant expression](expr.const#def:expression,converted_constant "7.7Constant expressions[expr.const]") of the underlying type[.](#5.sentence-7)
If the underlying
type is not fixed,
the type of each enumerator prior to the closing brace is determined as
follows:
- [(5.1)](#5.1)
If an
initializer is specified for an enumerator, the[*constant-expression*](expr.const#nt:constant-expression "7.7Constant expressions[expr.const]") shall be an[integral constant expression](expr.const#def:expression,integral_constant "7.7Constant expressions[expr.const]")[.](#5.1.sentence-1)
If the expression has
unscoped enumeration type, the enumerator has the underlying type of that
enumeration type, otherwise it has the same type as the expression[.](#5.1.sentence-2)
- [(5.2)](#5.2)
If no initializer is specified for the
first enumerator, its type is an unspecified signed integral type[.](#5.2.sentence-1)
- [(5.3)](#5.3)
Otherwise
the type of the enumerator is the same as that of the
preceding enumerator unless the incremented value is not representable
in that type, in which case the type is an unspecified integral type
sufficient to contain the incremented value[.](#5.3.sentence-1)
If no such type exists, the program
is ill-formed[.](#5.3.sentence-2)
[6](#6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L7982)
An enumeration whose underlying type is fixed is an incomplete type
until immediately after its[*enum-base*](#nt:enum-base "9.8.1Enumeration declarations[dcl.enum]") (if any), at which point it becomes a complete type[.](#6.sentence-1)
An enumeration whose underlying type is not fixed is an incomplete type
until the closing } of its[*enum-specifier*](#nt:enum-specifier "9.8.1Enumeration declarations[dcl.enum]"), at which point it becomes a complete type[.](#6.sentence-2)
[7](#7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L7990)
For an enumeration whose underlying type is not fixed,
the underlying type
is an
integral type that can represent all the enumerator values defined in
the enumeration[.](#7.sentence-1)
If no integral type can represent all the enumerator
values, the enumeration is ill-formed[.](#7.sentence-2)
It is implementation-defined
which integral type is used as the underlying type
except that the underlying type shall not be larger than int unless the value of an enumerator cannot fit in an int orunsigned int[.](#7.sentence-3)
If the [*enumerator-list*](#nt:enumerator-list "9.8.1Enumeration declarations[dcl.enum]") is empty, the
underlying type is as if the enumeration had a single enumerator with
value 0[.](#7.sentence-4)
[8](#8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L8004)
For an enumeration whose underlying type is fixed, the values of
the enumeration are the values of the underlying type[.](#8.sentence-1)
Otherwise,
the values of the enumeration are the values representable by
a hypothetical integer type with minimal width M such that all enumerators can be represented[.](#8.sentence-2)
The width of the smallest bit-field large enough to hold all the values of the
enumeration type is M[.](#8.sentence-3)
It is possible to define an enumeration that has values not defined by
any of its enumerators[.](#8.sentence-4)
If the [*enumerator-list*](#nt:enumerator-list "9.8.1Enumeration declarations[dcl.enum]") is empty, the
values of the enumeration are as if the enumeration had a single enumerator with
value 0[.](#8.sentence-5)[82](#footnote-82 "This set of values is used to define promotion and conversion semantics for the enumeration type. It does not preclude an expression of enumeration type from having a value that falls outside this range.")
[9](#9)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L8024)
An enumeration has
the same size,
value representation, and
alignment requirements ([[basic.align]](basic.align "6.8.3Alignment"))
as its underlying type[.](#9.sentence-1)
Furthermore, each value of an enumeration has the same representation
as the corresponding value of the underlying type[.](#9.sentence-2)
[10](#10)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L8033)
Two enumeration types are [*layout-compatible enumerations*](#def:layout-compatible,enumeration "9.8.1Enumeration declarations[dcl.enum]") if they have the same underlying type[.](#10.sentence-1)
[11](#11)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L8037)
The value of an enumerator or an object of an unscoped enumeration type is
converted to an integer by [integral promotion](conv.prom#def:integral_promotion "7.3.7Integral promotions[conv.prom]")[.](#11.sentence-1)
[*Example [3](#example-3)*:
enum color { red, yellow, green=20, blue };
color col = red;
color* cp = &col;if (*cp == blue) // ... makes color a type describing various colors, and then declarescol as an object of that type, and cp as a pointer to an
object of that type[.](#11.sentence-2)
The possible values of an object of typecolor are red, yellow, green,blue; these values can be converted to the integral values0, 1, 20, and 21[.](#11.sentence-3)
Since enumerations are
distinct types, objects of type color can be assigned only
values of type color[.](#11.sentence-4)
color c = 1; // error: type mismatch, no conversion from int to colorint i = yellow; // OK, yellow converted to integral value 1, integral promotion
Note that this implicit enum to int conversion is not provided for a scoped enumeration:enum class Col { red, yellow, green };int x = Col::red; // error: no Col to int conversion Col y = Col::red;if (y) { } // error: no Col to bool conversion
— *end example*]
[12](#12)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L8069)
The name of each unscoped enumerator is also bound
in the scope that immediately contains the [*enum-specifier*](#nt:enum-specifier "9.8.1Enumeration declarations[dcl.enum]")[.](#12.sentence-1)
An unnamed enumeration
that does not have a typedef name for linkage purposes ([[dcl.typedef]](dcl.typedef "9.2.4The typedef specifier")) and
that has a first enumerator
is denoted, for linkage purposes ([[basic.link]](basic.link "6.7Program and linkage")),
by its underlying type and its first enumerator;
such an enumeration is said to have
an enumerator as a name for linkage purposes[.](#12.sentence-2)
[*Note [3](#note-3)*:
Each unnamed enumeration with no enumerators is a distinct type[.](#12.sentence-3)
— *end note*]
[*Example [4](#example-4)*: enum direction { left='l', right='r' };
void g() { direction d; // OK d = left; // OK d = direction::right; // OK}enum class altitude { high='h', low='l' };
void h() { altitude a; // OK a = high; // error: high not in scope a = altitude::low; // OK} — *end example*]
[82)](#footnote-82)[82)](#footnoteref-82)
This set of values is used to define promotion and
conversion semantics for the enumeration type[.](#footnote-82.sentence-1)
It does not preclude an
expression of enumeration type from having a value that falls outside
this range[.](#footnote-82.sentence-2)

563
cppdraft/dcl/fct.md Normal file
View File

@@ -0,0 +1,563 @@
[dcl.fct]
# 9 Declarations [[dcl]](./#dcl)
## 9.3 Declarators [[dcl.decl]](dcl.decl#dcl.fct)
### 9.3.4 Meaning of declarators [[dcl.meaning]](dcl.meaning#dcl.fct)
#### 9.3.4.6 Functions [dcl.fct]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L3671)
In a declarationTD whereT may be empty andD has the form
D1 ( [*parameter-declaration-clause*](#nt:parameter-declaration-clause "9.3.4.6Functions[dcl.fct]") ) [*cv-qualifier-seq*](dcl.decl.general#nt:cv-qualifier-seq "9.3.1General[dcl.decl.general]")opt
[*ref-qualifier*](dcl.decl.general#nt:ref-qualifier "9.3.1General[dcl.decl.general]")opt [*noexcept-specifier*](except.spec#nt:noexcept-specifier "14.5Exception specifications[except.spec]")opt [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1Attribute syntax and semantics[dcl.attr.grammar]")opt [*trailing-return-type*](dcl.decl.general#nt:trailing-return-type "9.3.1General[dcl.decl.general]")opt
a *derived-declarator-type-list* is determined as follows:
- [(1.1)](#1.1)
If the [*unqualified-id*](expr.prim.id.unqual#nt:unqualified-id "7.5.5.2Unqualified names[expr.prim.id.unqual]") of the [*declarator-id*](dcl.decl.general#nt:declarator-id "9.3.1General[dcl.decl.general]") is a [*conversion-function-id*](class.conv.fct#nt:conversion-function-id "11.4.8.3Conversion functions[class.conv.fct]"),
the *derived-declarator-type-list* is empty[.](#1.1.sentence-1)
- [(1.2)](#1.2)
Otherwise, the *derived-declarator-type-list* is as appears in
the type “*derived-declarator-type-list* T”
of the contained[*declarator-id*](dcl.decl.general#nt:declarator-id "9.3.1General[dcl.decl.general]") in the declarationTD1[.](#1.2.sentence-1)
The declared return type U of the function type
is determined as follows:
- [(1.3)](#1.3)
If the [*trailing-return-type*](dcl.decl.general#nt:trailing-return-type "9.3.1General[dcl.decl.general]") is present,T shall be the single [*type-specifier*](dcl.type.general#nt:type-specifier "9.2.9.1General[dcl.type.general]") auto, andU is the type specified by the [*trailing-return-type*](dcl.decl.general#nt:trailing-return-type "9.3.1General[dcl.decl.general]")[.](#1.3.sentence-1)
- [(1.4)](#1.4)
Otherwise, if the declaration declares a conversion function,
see [[class.conv.fct]](class.conv.fct "11.4.8.3Conversion functions")[.](#1.4.sentence-1)
- [(1.5)](#1.5)
Otherwise, U is T[.](#1.5.sentence-1)
The type of the[*declarator-id*](dcl.decl.general#nt:declarator-id "9.3.1General[dcl.decl.general]") inD is
“*derived-declarator-type-list*noexceptopt function of parameter-type-list[*cv-qualifier-seq*](dcl.decl.general#nt:cv-qualifier-seq "9.3.1General[dcl.decl.general]")opt [*ref-qualifier*](dcl.decl.general#nt:ref-qualifier "9.3.1General[dcl.decl.general]")opt returning U”, where
- [(1.6)](#1.6)
the parameter-type-list is derived from
the [*parameter-declaration-clause*](#nt:parameter-declaration-clause "9.3.4.6Functions[dcl.fct]") as described below and
- [(1.7)](#1.7)
the optional noexcept is present if and only if
the exception specification ([[except.spec]](except.spec "14.5Exception specifications")) is non-throwing[.](#1.sentence-3)
Such a type is a [*function type*](#def:type,function "9.3.4.6Functions[dcl.fct]")[.](#1.sentence-4)[75](#footnote-75 "As indicated by syntax, cv-qualifiers are a significant component in function return types.")
The optional [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") appertains to the function type[.](#1.sentence-5)
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L3740)
[parameter-declaration-clause:](#nt:parameter-declaration-clause "9.3.4.6Functions[dcl.fct]")
...
[*parameter-declaration-list*](#nt:parameter-declaration-list "9.3.4.6Functions[dcl.fct]")opt
[*parameter-declaration-list*](#nt:parameter-declaration-list "9.3.4.6Functions[dcl.fct]") , ...
[*parameter-declaration-list*](#nt:parameter-declaration-list "9.3.4.6Functions[dcl.fct]") ...
[parameter-declaration-list:](#nt:parameter-declaration-list "9.3.4.6Functions[dcl.fct]")
[*parameter-declaration*](#nt:parameter-declaration "9.3.4.6Functions[dcl.fct]")
[*parameter-declaration-list*](#nt:parameter-declaration-list "9.3.4.6Functions[dcl.fct]") , [*parameter-declaration*](#nt:parameter-declaration "9.3.4.6Functions[dcl.fct]")
[parameter-declaration:](#nt:parameter-declaration "9.3.4.6Functions[dcl.fct]")
[*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1Attribute syntax and semantics[dcl.attr.grammar]")opt thisopt [*decl-specifier-seq*](dcl.spec.general#nt:decl-specifier-seq "9.2.1General[dcl.spec.general]") [*declarator*](dcl.decl.general#nt:declarator "9.3.1General[dcl.decl.general]")
[*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1Attribute syntax and semantics[dcl.attr.grammar]")opt [*decl-specifier-seq*](dcl.spec.general#nt:decl-specifier-seq "9.2.1General[dcl.spec.general]") [*declarator*](dcl.decl.general#nt:declarator "9.3.1General[dcl.decl.general]") = [*initializer-clause*](dcl.init.general#nt:initializer-clause "9.5.1General[dcl.init.general]")
[*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1Attribute syntax and semantics[dcl.attr.grammar]")opt thisopt [*decl-specifier-seq*](dcl.spec.general#nt:decl-specifier-seq "9.2.1General[dcl.spec.general]") [*abstract-declarator*](dcl.name#nt:abstract-declarator "9.3.2Type names[dcl.name]")opt
[*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1Attribute syntax and semantics[dcl.attr.grammar]")opt [*decl-specifier-seq*](dcl.spec.general#nt:decl-specifier-seq "9.2.1General[dcl.spec.general]") [*abstract-declarator*](dcl.name#nt:abstract-declarator "9.3.2Type names[dcl.name]")opt = [*initializer-clause*](dcl.init.general#nt:initializer-clause "9.5.1General[dcl.init.general]")
The optional [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") in a [*parameter-declaration*](#nt:parameter-declaration "9.3.4.6Functions[dcl.fct]") appertains to the parameter[.](#2.sentence-1)
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L3767)
The[*parameter-declaration-clause*](#nt:parameter-declaration-clause "9.3.4.6Functions[dcl.fct]") determines the arguments that can be specified, and their processing, when the function is called[.](#3.sentence-1)
[*Note [1](#note-1)*:
The[*parameter-declaration-clause*](#nt:parameter-declaration-clause "9.3.4.6Functions[dcl.fct]") is used to convert the arguments specified on the function call;
see [[expr.call]](expr.call "7.6.1.3Function call")[.](#3.sentence-2)
— *end note*]
If the[*parameter-declaration-clause*](#nt:parameter-declaration-clause "9.3.4.6Functions[dcl.fct]") is empty, the function takes no arguments[.](#3.sentence-3)
A parameter list consisting of a single unnamed non-object parameter of
non-dependent type void is equivalent to an empty parameter
list[.](#3.sentence-4)
Except for this special case, a parameter shall not have type cv void[.](#3.sentence-5)
A parameter with volatile-qualified type is deprecated;
see [[depr.volatile.type]](depr.volatile.type "D.4Deprecated volatile types")[.](#3.sentence-6)
If the[*parameter-declaration-clause*](#nt:parameter-declaration-clause "9.3.4.6Functions[dcl.fct]")terminates with an ellipsis or a function parameter
pack ([[temp.variadic]](temp.variadic "13.7.4Variadic templates")), the number of arguments shall be equal
to or greater than the number of parameters that do not have a default
argument and are not function parameter packs[.](#3.sentence-7)
Where syntactically correct and where “...” is not
part of an [*abstract-declarator*](dcl.name#nt:abstract-declarator "9.3.2Type names[dcl.name]"),
“...”
is synonymous with
“, ...”[.](#3.sentence-8)
A [*parameter-declaration-clause*](#nt:parameter-declaration-clause "9.3.4.6Functions[dcl.fct]") of the form[*parameter-declaration-list*](#nt:parameter-declaration-list "9.3.4.6Functions[dcl.fct]") ... is deprecated ([[depr.ellipsis.comma]](depr.ellipsis.comma "D.5Non-comma-separated ellipsis parameters"))[.](#3.sentence-9)
[*Example [1](#example-1)*:
The declarationint printf(const char*, ...); declares a function that can be called with varying numbers and types of arguments[.](#3.sentence-10)
printf("hello world");
printf("a=%d b=%d", a, b);
However, the first argument must be of a type
that can be converted to aconstchar*[.](#3.sentence-11)
— *end example*]
[*Note [2](#note-2)*:
The standard header [<cstdarg>](cstdarg.syn#header:%3ccstdarg%3e "17.14.2Header <cstdarg> synopsis[cstdarg.syn]") contains a mechanism for accessing arguments passed using the ellipsis
(see [[expr.call]](expr.call "7.6.1.3Function call") and [[support.runtime]](support.runtime "17.14Other runtime support"))[.](#3.sentence-12)
— *end note*]
[4](#4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L3833)
The type of a function is determined using the following rules[.](#4.sentence-1)
The type of each parameter (including function parameter packs) is
determined from its own [*parameter-declaration*](#nt:parameter-declaration "9.3.4.6Functions[dcl.fct]") ([[dcl.decl]](dcl.decl "9.3Declarators"))[.](#4.sentence-2)
After determining the type of each parameter, any parameterof type “array of T” orof function type T is adjusted to be “pointer to T”[.](#4.sentence-3)
After producing the list of parameter types,
any top-level[*cv-qualifier*](dcl.decl.general#nt:cv-qualifier "9.3.1General[dcl.decl.general]")*s* modifying a parameter type are deleted
when forming the function type[.](#4.sentence-4)
The resulting list of transformed parameter types
and the presence or absence of the ellipsis or a function parameter pack
is the function's[*parameter-type-list*](#def:parameter-type-list "9.3.4.6Functions[dcl.fct]")[.](#4.sentence-5)
[*Note [3](#note-3)*:
This transformation does not affect the types of the parameters[.](#4.sentence-6)
For example, int(*)(const int p, decltype(p)*) andint(*)(int, const int*) are identical types[.](#4.sentence-7)
— *end note*]
[*Example [2](#example-2)*: void f(char*); // #1void f(char[]) {} // defines #1void f(const char*) {} // OK, another overloadvoid f(char *const) {} // error: redefines #1void g(char(*)[2]); // #2void g(char[3][2]) {} // defines #2void g(char[3][3]) {} // OK, another overloadvoid h(int x(const int)); // #3void h(int (*)(int)) {} // defines #3 — *end example*]
[5](#5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L3874)
An [*explicit-object-parameter-declaration*](#def:explicit-object-parameter-declaration "9.3.4.6Functions[dcl.fct]") is
a [*parameter-declaration*](#nt:parameter-declaration "9.3.4.6Functions[dcl.fct]") with a this specifier[.](#5.sentence-1)
An explicit-object-parameter-declaration shall appear only as
the first [*parameter-declaration*](#nt:parameter-declaration "9.3.4.6Functions[dcl.fct]") of
a [*parameter-declaration-list*](#nt:parameter-declaration-list "9.3.4.6Functions[dcl.fct]") of one of:
- [(5.1)](#5.1)
a declaration of
a member function or member function template ([[class.mem]](class.mem "11.4Class members")), or
- [(5.2)](#5.2)
an explicit instantiation ([[temp.explicit]](temp.explicit "13.9.3Explicit instantiation")) or
explicit specialization ([[temp.expl.spec]](temp.expl.spec "13.9.4Explicit specialization")) of
a templated member function, or
- [(5.3)](#5.3)
a [*lambda-declarator*](expr.prim.lambda.general#nt:lambda-declarator "7.5.6.1General[expr.prim.lambda.general]") ([[expr.prim.lambda]](expr.prim.lambda "7.5.6Lambda expressions"))[.](#5.sentence-2)
A [*member-declarator*](class.mem.general#nt:member-declarator "11.4.1General[class.mem.general]") with an explicit-object-parameter-declaration
shall not include
a [*ref-qualifier*](dcl.decl.general#nt:ref-qualifier "9.3.1General[dcl.decl.general]") or a [*cv-qualifier-seq*](dcl.decl.general#nt:cv-qualifier-seq "9.3.1General[dcl.decl.general]") and
shall not be declared static or virtual[.](#5.sentence-3)
[*Example [3](#example-3)*: struct C {void f(this C& self); template <typename Self> void g(this Self&& self, int); void h(this C) const; // error: const not allowed here};
void test(C c) { c.f(); // OK, calls C::f c.g(42); // OK, calls C::g<C&> std::move(c).g(42); // OK, calls C::g<C>} — *end example*]
[6](#6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L3912)
A function parameter declared with an explicit-object-parameter-declaration
is an [*explicit object parameter*](#def:parameter,explicit_object "9.3.4.6Functions[dcl.fct]")[.](#6.sentence-1)
An explicit object parameter shall not be
a function parameter pack ([[temp.variadic]](temp.variadic "13.7.4Variadic templates"))[.](#6.sentence-2)
An [*explicit object member function*](#def:member_function,explicit_object "9.3.4.6Functions[dcl.fct]") is a non-static member function
with an explicit object parameter[.](#6.sentence-3)
An [*implicit object member function*](#def:member_function,implicit_object "9.3.4.6Functions[dcl.fct]") is a non-static member function
without an explicit object parameter[.](#6.sentence-4)
[7](#7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L3922)
The [*object parameter*](#def:parameter,object "9.3.4.6Functions[dcl.fct]") of a non-static member function is either
the explicit object parameter or
the implicit object parameter ([[over.match.funcs]](over.match.funcs "12.2.2Candidate functions and argument lists"))[.](#7.sentence-1)
[8](#8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L3927)
A [*non-object parameter*](#def:parameter,non-object "9.3.4.6Functions[dcl.fct]") is a function parameter
that is not the explicit object parameter[.](#8.sentence-1)
The [*non-object-parameter-type-list*](#def:non-object-parameter-type-list "9.3.4.6Functions[dcl.fct]") of a member function is
the parameter-type-list of that function with the explicit object parameter,
if any, omitted[.](#8.sentence-2)
[*Note [4](#note-4)*:
The non-object-parameter-type-list consists of
the adjusted types of all the non-object parameters[.](#8.sentence-3)
— *end note*]
[9](#9)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L3938)
A function type with a [*cv-qualifier-seq*](dcl.decl.general#nt:cv-qualifier-seq "9.3.1General[dcl.decl.general]") or a[*ref-qualifier*](dcl.decl.general#nt:ref-qualifier "9.3.1General[dcl.decl.general]") (including a type denoted by[*typedef-name*](dcl.typedef#nt:typedef-name "9.2.4The typedef specifier[dcl.typedef]") ([[dcl.typedef]](dcl.typedef "9.2.4The typedef specifier"), [[temp.param]](temp.param "13.2Template parameters")))
shall appear only as:
- [(9.1)](#9.1)
the function type for a non-static member function,
- [(9.2)](#9.2)
the function type to which a pointer to member refers,
- [(9.3)](#9.3)
the top-level function type of a function typedef declaration
or [*alias-declaration*](dcl.pre#nt:alias-declaration "9.1Preamble[dcl.pre]"),
- [(9.4)](#9.4)
the [*type-id*](dcl.name#nt:type-id "9.3.2Type names[dcl.name]") in the default argument of a[*type-parameter*](temp.param#nt:type-parameter "13.2Template parameters[temp.param]") ([[temp.param]](temp.param "13.2Template parameters")),
- [(9.5)](#9.5)
the [*type-id*](dcl.name#nt:type-id "9.3.2Type names[dcl.name]") of a [*template-argument*](temp.names#nt:template-argument "13.3Names of template specializations[temp.names]") for a[*type-parameter*](temp.param#nt:type-parameter "13.2Template parameters[temp.param]") ([[temp.arg.type]](temp.arg.type "13.4.2Type template arguments")), or
- [(9.6)](#9.6)
the operand of a [*reflect-expression*](expr.reflect#nt:reflect-expression "7.6.2.10The reflection operator[expr.reflect]") ([[expr.reflect]](expr.reflect "7.6.2.10The reflection operator"))[.](#9.sentence-1)
[*Example [4](#example-4)*: typedef int FIC(int) const;
FIC f; // error: does not declare a member functionstruct S { FIC f; // OK};
FIC S::*pm = &S::f; // OKconstexpr std::meta::info yeti = ^^void(int) const &; // OK — *end example*]
[10](#10)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L3971)
The effect of a[*cv-qualifier-seq*](dcl.decl.general#nt:cv-qualifier-seq "9.3.1General[dcl.decl.general]") in a function declarator is not the same as
adding cv-qualification on top of the function type[.](#10.sentence-1)
In the latter case, the cv-qualifiers are ignored[.](#10.sentence-2)
[*Note [5](#note-5)*:
A function type that has a [*cv-qualifier-seq*](dcl.decl.general#nt:cv-qualifier-seq "9.3.1General[dcl.decl.general]") is not a
cv-qualified type; there are no cv-qualified function types[.](#10.sentence-3)
— *end note*]
[*Example [5](#example-5)*: typedef void F();struct S {const F f; // OK, equivalent to: void f();}; — *end example*]
[11](#11)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L3990)
The return type, the parameter-type-list, the [*ref-qualifier*](dcl.decl.general#nt:ref-qualifier "9.3.1General[dcl.decl.general]"),
the [*cv-qualifier-seq*](dcl.decl.general#nt:cv-qualifier-seq "9.3.1General[dcl.decl.general]"), and
the exception specification,
but not the default arguments ([[dcl.fct.default]](dcl.fct.default "9.3.4.7Default arguments"))
or the trailing [*requires-clause*](temp.pre#nt:requires-clause "13.1Preamble[temp.pre]") ([[dcl.decl]](dcl.decl "9.3Declarators")),
are part of the function type[.](#11.sentence-1)
[*Note [6](#note-6)*:
Function types are checked during the assignments and initializations of
pointers to functions, references to functions, and pointers to member functions[.](#11.sentence-2)
— *end note*]
[12](#12)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L4002)
[*Example [6](#example-6)*:
The declarationint fseek(FILE*, long, int); declares a function taking three arguments of the specified types,
and returningint ([[dcl.type]](dcl.type "9.2.9Type specifiers"))[.](#12.sentence-1)
— *end example*]
[13](#13)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L4013)
[*Note [7](#note-7)*:
A single name can be used for several different functions in a single scope;
this is function overloading ([[over]](over "12Overloading"))[.](#13.sentence-1)
— *end note*]
[14](#14)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L4020)
The return type shall be a non-array object type, a reference type, or cv void[.](#14.sentence-1)
[*Note [8](#note-8)*:
An array of placeholder type is considered an array type[.](#14.sentence-2)
— *end note*]
[15](#15)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L4028)
A volatile-qualified return type is deprecated;
see [[depr.volatile.type]](depr.volatile.type "D.4Deprecated volatile types")[.](#15.sentence-1)
[16](#16)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L4032)
Types shall not be defined in return or parameter types[.](#16.sentence-1)
[17](#17)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L4035)
A typedef of function type may be used to declare a function but shall not be
used to define a function ([[dcl.fct.def]](dcl.fct.def "9.6Function definitions"))[.](#17.sentence-1)
[*Example [7](#example-7)*: typedef void F();
F fv; // OK, equivalent to void fv(); F fv { } // errorvoid fv() { } // OK, definition of fv — *end example*]
[18](#18)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L4048)
An identifier can optionally be provided as a parameter name;
if present in a function definition ([[dcl.fct.def]](dcl.fct.def "9.6Function definitions")), it names a parameter[.](#18.sentence-1)
[*Note [9](#note-9)*:
In particular, parameter names are also optional in function definitions
and names used for a parameter in different declarations and the definition
of a function need not be the same[.](#18.sentence-2)
— *end note*]
[19](#19)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L4057)
[*Example [8](#example-8)*:
The declarationint i, *pi,
f(), *fpi(int), (*pif)(const char*, const char*), (*fpif(int))(int); declares an integeri,
a pointerpi to an integer,
a functionf taking no arguments and returning an integer,
a functionfpi taking an integer argument and returning a pointer to an integer,
a pointerpif to a function which
takes two pointers to constant characters and returns an integer,
a functionfpif taking an integer argument and returning a pointer to a function that takes an integer argument and returns an integer[.](#19.sentence-1)
It is especially useful to comparefpi andpif[.](#19.sentence-2)
The binding of*fpi(int) is*(fpi(int)),
so the declaration suggests,
and the same construction in an expression
requires, the calling of a functionfpi,
and then using indirection through the (pointer) result
to yield an integer[.](#19.sentence-3)
In the declarator(*pif)(const char*, const char*),
the extra parentheses are necessary to indicate that indirection through
a pointer to a function yields a function, which is then called[.](#19.sentence-4)
— *end example*]
[*Note [10](#note-10)*:
Typedefs and [*trailing-return-type*](dcl.decl.general#nt:trailing-return-type "9.3.1General[dcl.decl.general]")*s* are sometimes convenient when the return type of a function is complex[.](#19.sentence-5)
For example,
the functionfpif above can be declaredtypedef int IFUNC(int);
IFUNC* fpif(int); orauto fpif(int)->int(*)(int);
A [*trailing-return-type*](dcl.decl.general#nt:trailing-return-type "9.3.1General[dcl.decl.general]") is most useful for a type that would be more complicated to specify before the [*declarator-id*](dcl.decl.general#nt:declarator-id "9.3.1General[dcl.decl.general]"):template <class T, class U> auto add(T t, U u) -> decltype(t + u); rather thantemplate <class T, class U> decltype((*(T*)0) + (*(U*)0)) add(T t, U u);
— *end note*]
[20](#20)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L4130)
A [*non-template function*](#def:function,non-template "9.3.4.6Functions[dcl.fct]") is a function that is not a function template
specialization[.](#20.sentence-1)
[*Note [11](#note-11)*:
A function template is not a function[.](#20.sentence-2)
— *end note*]
[21](#21)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L4137)
An [*abbreviated function template*](#def:template,function,abbreviated "9.3.4.6Functions[dcl.fct]") is a function declaration that has
one or more generic parameter type placeholders ([[dcl.spec.auto]](dcl.spec.auto "9.2.9.7Placeholder type specifiers"))[.](#21.sentence-1)
An abbreviated function template is equivalent to
a function template ([[temp.fct]](temp.fct "13.7.7Function templates"))
whose [*template-parameter-list*](temp.pre#nt:template-parameter-list "13.1Preamble[temp.pre]") includes
one invented [*type-parameter*](temp.param#nt:type-parameter "13.2Template parameters[temp.param]") for each generic parameter type placeholder
of the function declaration, in order of appearance[.](#21.sentence-2)
For a [*placeholder-type-specifier*](dcl.spec.auto.general#nt:placeholder-type-specifier "9.2.9.7.1General[dcl.spec.auto.general]") of the form auto,
the invented parameter is
an unconstrained [*type-parameter*](temp.param#nt:type-parameter "13.2Template parameters[temp.param]")[.](#21.sentence-3)
For a [*placeholder-type-specifier*](dcl.spec.auto.general#nt:placeholder-type-specifier "9.2.9.7.1General[dcl.spec.auto.general]") of the form[*type-constraint*](temp.param#nt:type-constraint "13.2Template parameters[temp.param]") auto,
the invented parameter is a [*type-parameter*](temp.param#nt:type-parameter "13.2Template parameters[temp.param]") with
that [*type-constraint*](temp.param#nt:type-constraint "13.2Template parameters[temp.param]")[.](#21.sentence-4)
The invented [*type-parameter*](temp.param#nt:type-parameter "13.2Template parameters[temp.param]") declares
a template parameter pack
if the corresponding [*parameter-declaration*](#nt:parameter-declaration "9.3.4.6Functions[dcl.fct]") declares a function parameter pack[.](#21.sentence-5)
If the placeholder contains decltype(auto),
the program is ill-formed[.](#21.sentence-6)
The adjusted function parameters of an abbreviated function template
are derived from the [*parameter-declaration-clause*](#nt:parameter-declaration-clause "9.3.4.6Functions[dcl.fct]") by
replacing each occurrence of a placeholder with
the name of the corresponding invented [*type-parameter*](temp.param#nt:type-parameter "13.2Template parameters[temp.param]")[.](#21.sentence-7)
[*Example [9](#example-9)*: template<typename T> concept C1 = /* ... */;template<typename T> concept C2 = /* ... */;template<typename... Ts> concept C3 = /* ... */;
void g1(const C1 auto*, C2 auto&);void g2(C1 auto&...);void g3(C3 auto...);void g4(C3 auto);
The declarations above are functionally equivalent (but not equivalent) to
their respective declarations below:template<C1 T, C2 U> void g1(const T*, U&);template<C1... Ts> void g2(Ts&...);template<C3... Ts> void g3(Ts...);template<C3 T> void g4(T);
Abbreviated function templates can be specialized like all function templates[.](#21.sentence-9)
template<> void g1<int>(const int*, const double&); // OK, specialization of g1<int, const double> — *end example*]
[22](#22)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L4190)
An abbreviated function template can have a [*template-head*](temp.pre#nt:template-head "13.1Preamble[temp.pre]")[.](#22.sentence-1)
The invented [*type-parameter*](temp.param#nt:type-parameter "13.2Template parameters[temp.param]")*s* are
appended to the [*template-parameter-list*](temp.pre#nt:template-parameter-list "13.1Preamble[temp.pre]") after
the explicitly declared [*template-parameter*](temp.param#nt:template-parameter "13.2Template parameters[temp.param]")*s*[.](#22.sentence-2)
[*Example [10](#example-10)*: template<typename> concept C = /* ... */;
template <typename T, C U>void g(T x, U y, C auto z);
This is functionally equivalent to each of the following two declarations[.](#22.sentence-3)
template<typename T, C U, C W>void g(T x, U y, W z);
template<typename T, typename U, typename W>requires C<U> && C<W>void g(T x, U y, W z); — *end example*]
[23](#23)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L4214)
A function declaration at block scope
shall not declare an abbreviated function template[.](#23.sentence-1)
[24](#24)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L4218)
A [*declarator-id*](dcl.decl.general#nt:declarator-id "9.3.1General[dcl.decl.general]") or [*abstract-declarator*](dcl.name#nt:abstract-declarator "9.3.2Type names[dcl.name]") containing an ellipsis shall only
be used in a [*parameter-declaration*](#nt:parameter-declaration "9.3.4.6Functions[dcl.fct]")[.](#24.sentence-1)
When it is part of a[*parameter-declaration-clause*](#nt:parameter-declaration-clause "9.3.4.6Functions[dcl.fct]"),
the [*parameter-declaration*](#nt:parameter-declaration "9.3.4.6Functions[dcl.fct]") declares a
function parameter pack ([[temp.variadic]](temp.variadic "13.7.4Variadic templates"))[.](#24.sentence-2)
Otherwise, the [*parameter-declaration*](#nt:parameter-declaration "9.3.4.6Functions[dcl.fct]") is part of a[*template-parameter-list*](temp.pre#nt:template-parameter-list "13.1Preamble[temp.pre]") and declares a
template parameter pack; see [[temp.param]](temp.param "13.2Template parameters")[.](#24.sentence-3)
A function parameter pack is a pack expansion ([[temp.variadic]](temp.variadic "13.7.4Variadic templates"))[.](#24.sentence-4)
[*Example [11](#example-11)*: template<typename... T> void f(T (* ...t)(int, int));
int add(int, int);float subtract(int, int);
void g() { f(add, subtract);} — *end example*]
[25](#25)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L4243)
There is a syntactic ambiguity when an ellipsis occurs at the end
of a [*parameter-declaration-clause*](#nt:parameter-declaration-clause "9.3.4.6Functions[dcl.fct]") without a preceding
comma[.](#25.sentence-1)
In this case, the ellipsis is parsed as part of the[*abstract-declarator*](dcl.name#nt:abstract-declarator "9.3.2Type names[dcl.name]") if the type of the parameter either names
a template parameter pack that has not been expanded or contains auto;
otherwise, it is
parsed as part of the [*parameter-declaration-clause*](#nt:parameter-declaration-clause "9.3.4.6Functions[dcl.fct]")[.](#25.sentence-2)[76](#footnote-76 "One can explicitly disambiguate the parse either by introducing a comma (so the ellipsis will be parsed as part of the parameter-declaration-clause) or by introducing a name for the parameter (so the ellipsis will be parsed as part of the declarator-id).")
[75)](#footnote-75)[75)](#footnoteref-75)
As indicated by syntax, cv-qualifiers are a significant component in function return types[.](#footnote-75.sentence-1)
[76)](#footnote-76)[76)](#footnoteref-76)
One can explicitly disambiguate the parse either by
introducing a comma (so the ellipsis will be parsed as part of the[*parameter-declaration-clause*](#nt:parameter-declaration-clause "9.3.4.6Functions[dcl.fct]")) or by introducing a name for the
parameter (so the ellipsis will be parsed as part of the[*declarator-id*](dcl.decl.general#nt:declarator-id "9.3.1General[dcl.decl.general]"))[.](#footnote-76.sentence-1)

792
cppdraft/dcl/fct/def.md Normal file
View File

@@ -0,0 +1,792 @@
[dcl.fct.def]
# 9 Declarations [[dcl]](./#dcl)
## 9.6 Function definitions [dcl.fct.def]
### [9.6.1](#general) General [[dcl.fct.def.general]](dcl.fct.def.general)
[1](#general-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L6827)
Function definitions have the form
[function-definition:](#nt:function-definition "9.6.1General[dcl.fct.def.general]")
[*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1Attribute syntax and semantics[dcl.attr.grammar]")opt [*decl-specifier-seq*](dcl.spec.general#nt:decl-specifier-seq "9.2.1General[dcl.spec.general]")opt [*declarator*](dcl.decl.general#nt:declarator "9.3.1General[dcl.decl.general]") [*virt-specifier-seq*](class.mem.general#nt:virt-specifier-seq "11.4.1General[class.mem.general]")opt
[*function-contract-specifier-seq*](dcl.contract.func#nt:function-contract-specifier-seq "9.4.1General[dcl.contract.func]")opt [*function-body*](#nt:function-body "9.6.1General[dcl.fct.def.general]")
[*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1Attribute syntax and semantics[dcl.attr.grammar]")opt [*decl-specifier-seq*](dcl.spec.general#nt:decl-specifier-seq "9.2.1General[dcl.spec.general]")opt [*declarator*](dcl.decl.general#nt:declarator "9.3.1General[dcl.decl.general]") [*requires-clause*](temp.pre#nt:requires-clause "13.1Preamble[temp.pre]")
[*function-contract-specifier-seq*](dcl.contract.func#nt:function-contract-specifier-seq "9.4.1General[dcl.contract.func]")opt [*function-body*](#nt:function-body "9.6.1General[dcl.fct.def.general]")
[function-body:](#nt:function-body "9.6.1General[dcl.fct.def.general]")
[*ctor-initializer*](class.base.init#nt:ctor-initializer "11.9.3Initializing bases and members[class.base.init]")opt [*compound-statement*](stmt.block#nt:compound-statement "8.4Compound statement or block[stmt.block]")
[*function-try-block*](except.pre#nt:function-try-block "14.1Preamble[except.pre]")
= default ;
[*deleted-function-body*](#nt:deleted-function-body "9.6.1General[dcl.fct.def.general]")
[deleted-function-body:](#nt:deleted-function-body "9.6.1General[dcl.fct.def.general]")
= delete ;
= delete ( [*unevaluated-string*](lex.string.uneval#nt:unevaluated-string "5.13.6Unevaluated strings[lex.string.uneval]") ) ;
Any informal reference to the body of a function should be interpreted as a reference to
the non-terminal [*function-body*](#nt:function-body "9.6.1General[dcl.fct.def.general]"),
including, for a constructor,
default member initializers or default initialization
used to initialize
a base or member subobject in the absence of
a [*mem-initializer-id*](class.base.init#nt:mem-initializer-id "11.9.3Initializing bases and members[class.base.init]") ([[class.base.init]](class.base.init "11.9.3Initializing bases and members"))[.](#general-1.sentence-2)
The optional [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") in a [*function-definition*](#nt:function-definition "9.6.1General[dcl.fct.def.general]") appertains to the function[.](#general-1.sentence-3)
A [*function-definition*](#nt:function-definition "9.6.1General[dcl.fct.def.general]") with a [*virt-specifier-seq*](class.mem.general#nt:virt-specifier-seq "11.4.1General[class.mem.general]") shall be a [*member-declaration*](class.mem.general#nt:member-declaration "11.4.1General[class.mem.general]") ([[class.mem]](class.mem "11.4Class members"))[.](#general-1.sentence-4)
A [*function-definition*](#nt:function-definition "9.6.1General[dcl.fct.def.general]") with a [*requires-clause*](temp.pre#nt:requires-clause "13.1Preamble[temp.pre]") shall define a templated function[.](#general-1.sentence-5)
[2](#general-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L6868)
In a [*function-definition*](#nt:function-definition "9.6.1General[dcl.fct.def.general]"),
either void [*declarator*](dcl.decl.general#nt:declarator "9.3.1General[dcl.decl.general]") ; or [*declarator*](dcl.decl.general#nt:declarator "9.3.1General[dcl.decl.general]") ; shall be a well-formed function declaration
as described in [[dcl.fct]](dcl.fct "9.3.4.6Functions")[.](#general-2.sentence-1)
A function shall be defined only in namespace or class scope[.](#general-2.sentence-2)
The type of a parameter or the return type for a function
definition shall not be
a (possibly cv-qualified) class type that is
incomplete or abstract within the function body
unless the function is deleted ([[dcl.fct.def.delete]](#delete "9.6.3Deleted definitions"))[.](#general-2.sentence-3)
[3](#general-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L6881)
[*Example [1](#general-example-1)*:
A simple example of a complete function definition isint max(int a, int b, int c) {int m = (a > b) ? a : b; return (m > c) ? m : c;}
Hereint is the[*decl-specifier-seq*](dcl.spec.general#nt:decl-specifier-seq "9.2.1General[dcl.spec.general]");max(inta,intb,intc) is the[*declarator*](dcl.decl.general#nt:declarator "9.3.1General[dcl.decl.general]");{ /* ... */ } is the[*function-body*](#nt:function-body "9.6.1General[dcl.fct.def.general]")[.](#general-3.sentence-2)
— *end example*]
[4](#general-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L6908)
A[*ctor-initializer*](class.base.init#nt:ctor-initializer "11.9.3Initializing bases and members[class.base.init]") is used only in a constructor; see [[class.ctor]](class.ctor "11.4.5Constructors") and [[class.init]](class.init "11.9Initialization")[.](#general-4.sentence-1)
[5](#general-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L6916)
[*Note [1](#general-note-1)*:
A [*cv-qualifier-seq*](dcl.decl.general#nt:cv-qualifier-seq "9.3.1General[dcl.decl.general]") affects the type of this in the body of a member function; see [[expr.prim.this]](expr.prim.this "7.5.3This")[.](#general-5.sentence-1)
— *end note*]
[6](#general-6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L6922)
[*Note [2](#general-note-2)*:
Unused parameters need not be named[.](#general-6.sentence-1)
For example,
void print(int a, int) { std::printf("a = %d\n",a);} — *end note*]
[7](#general-7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L6934)
A [*function-local predefined variable*](#def:variable,function-local_predefined "9.6.1General[dcl.fct.def.general]") is a variable with static
storage duration that is implicitly defined in a function parameter scope[.](#general-7.sentence-1)
[8](#general-8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L6938)
The function-local predefined variable __func__ is
defined as if a definition of the formstatic const char __func__[] = "*function-name*"; had been provided, where *function-name* is an implementation-defined string[.](#general-8.sentence-1)
It is unspecified whether such a variable has an address
distinct from that of any other object in the program[.](#general-8.sentence-2)[81](#footnote-81 "Implementations are permitted to provide additional predefined variables with names that are reserved to the implementation ([lex.name]). If a predefined variable is not odr-used ([term.odr.use]), its string value need not be present in the program image.")
[*Example [2](#general-example-2)*: struct S { S() : s(__func__) { } // OKconst char* s;};void f(const char* s = __func__); // error: __func__ is undeclared — *end example*]
[81)](#footnote-81)[81)](#footnoteref-81)
Implementations are
permitted to provide additional predefined variables with names that are reserved to the
implementation ([[lex.name]](lex.name "5.11Identifiers"))[.](#footnote-81.sentence-1)
If a predefined variable is not
odr-used ([[basic.def.odr]](basic.def.odr#term.odr.use "6.3One-definition rule")), its string value need not be present in the program image[.](#footnote-81.sentence-2)
### [9.6.2](#default) Explicitly-defaulted functions [[dcl.fct.def.default]](dcl.fct.def.default)
[1](#default-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L6967)
A function definition whose[*function-body*](#nt:function-body "9.6.1General[dcl.fct.def.general]") is of the form= default ; is called an [*explicitly-defaulted*](#def:definition,function,explicitly-defaulted "9.6.2Explicitly-defaulted functions[dcl.fct.def.default]") definition[.](#default-1.sentence-1)
A function that is explicitly defaulted shall
- [(1.1)](#default-1.1)
be a special member function ([[special]](special "11.4.4Special member functions")) or
a comparison operator function ([[over.binary]](over.binary "12.4.3Binary operators"), [[class.compare.default]](class.compare.default "11.10.1Defaulted comparison operator functions")), and
- [(1.2)](#default-1.2)
not have default arguments ([[dcl.fct.default]](dcl.fct.default "9.3.4.7Default arguments"))[.](#default-1.sentence-2)
[2](#default-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L6980)
An explicitly defaulted special member function F1 is allowed to differ from
the corresponding special member function F2 that would have been implicitly declared, as follows:
- [(2.1)](#default-2.1)
F1 and F2 may have differing [*ref-qualifier*](dcl.decl.general#nt:ref-qualifier "9.3.1General[dcl.decl.general]")*s*;
- [(2.2)](#default-2.2)
if F2 has an implicit object parameter of
type “reference to C”, F1 may be an explicit object member function whose
explicit object parameter is of (possibly different) type “reference to C”,
in which case the type of F1 would differ from the type of F2 in that the type of F1 has an additional parameter;
- [(2.3)](#default-2.3)
F1 and F2 may have differing exception specifications; and
- [(2.4)](#default-2.4)
if F2 has a non-object parameter of type const C&,
the corresponding non-object parameter of F1 may be of
type C&[.](#default-2.sentence-1)
If the type of F1 differs from the type of F2 in a way
other than as allowed by the preceding rules, then:
- [(2.5)](#default-2.5)
if F1 is an assignment operator, and
the return type of F1 differs from
the return type of F2 or F1's non-object parameter type is not a reference,
the program is ill-formed;
- [(2.6)](#default-2.6)
otherwise, if F1 is explicitly defaulted on its first declaration,
it is defined as deleted;
- [(2.7)](#default-2.7)
otherwise, the program is ill-formed[.](#default-2.sentence-2)
[3](#default-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L7018)
A function explicitly defaulted on its first declaration
is implicitly inline ([[dcl.inline]](dcl.inline "9.2.8The inline specifier")),
and is implicitly constexpr ([[dcl.constexpr]](dcl.constexpr "9.2.6The constexpr and consteval specifiers"))
if it is constexpr-suitable[.](#default-3.sentence-1)
[*Note [1](#default-note-1)*:
Other defaulted functions are not implicitly constexpr[.](#default-3.sentence-2)
— *end note*]
[4](#default-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L7027)
[*Example [1](#default-example-1)*: struct S { S(int a = 0) = default; // error: default argumentvoid operator=(const S&) = default; // error: non-matching return type~S() noexcept(false) = default; // OK, despite mismatched exception specificationprivate:int i;
S(S&); // OK, private copy constructor};
S::S(S&) = default; // OK, defines copy constructorstruct T { T();
T(T &&) noexcept(false);};struct U { T t;
U();
U(U &&) noexcept = default;};
U u1;
U u2 = static_cast<U&&>(u1); // OK, calls std::terminate if T::T(T&&) throws — *end example*]
[5](#default-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L7054)
Explicitly-defaulted functions and implicitly-declared functions are collectively
called [*defaulted*](#def:defaulted "9.6.2Explicitly-defaulted functions[dcl.fct.def.default]") functions, and the implementation
shall provide implicit definitions
for them ([[class.ctor]](class.ctor "11.4.5Constructors"), [[class.dtor]](class.dtor "11.4.7Destructors"), [[class.copy.ctor]](class.copy.ctor "11.4.5.3Copy/move constructors"), [[class.copy.assign]](class.copy.assign "11.4.6Copy/move assignment operator")) as described below,
including possibly defining them as deleted[.](#default-5.sentence-1)
A defaulted prospective destructor ([[class.dtor]](class.dtor "11.4.7Destructors"))
that is not a destructor is defined as deleted[.](#default-5.sentence-2)
A defaulted special member function
that is neither a prospective destructor nor
an eligible special member function ([[special]](special "11.4.4Special member functions"))
is defined as deleted[.](#default-5.sentence-3)
A function is[*user-provided*](#def:user-provided "9.6.2Explicitly-defaulted functions[dcl.fct.def.default]") if it is user-declared and not explicitly
defaulted or deleted on its first declaration[.](#default-5.sentence-4)
A user-provided explicitly-defaulted function
(i.e., explicitly defaulted after its first declaration)
is implicitly defined at the point where it is explicitly defaulted; if such a function is implicitly
defined as deleted, the program is ill-formed[.](#default-5.sentence-5)
[*Note [2](#default-note-2)*:
Declaring a function as defaulted after its first declaration
can provide efficient execution and concise definition
while enabling a stable binary interface to an evolving code base[.](#default-5.sentence-6)
— *end note*]
A non-user-provided defaulted function
(i.e., implicitly declared or explicitly defaulted in the class)
that is not defined as deleted is implicitly defined when it is odr-used ([[basic.def.odr]](basic.def.odr "6.3One-definition rule"))
or needed for constant evaluation ([[expr.const]](expr.const "7.7Constant expressions"))[.](#default-5.sentence-7)
[*Note [3](#default-note-3)*:
The implicit definition of a non-user-provided defaulted function
does not bind any names[.](#default-5.sentence-8)
— *end note*]
[6](#default-6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L7086)
[*Example [2](#default-example-2)*: struct trivial { trivial() = default;
trivial(const trivial&) = default;
trivial(trivial&&) = default;
trivial& operator=(const trivial&) = default;
trivial& operator=(trivial&&) = default; ~trivial() = default;};
struct nontrivial1 { nontrivial1();};
nontrivial1::nontrivial1() = default; // not first declaration — *end example*]
### [9.6.3](#delete) Deleted definitions [[dcl.fct.def.delete]](dcl.fct.def.delete)
[1](#delete-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L7108)
A [*deleted definition*](#def:definition,deleted "9.6.3Deleted definitions[dcl.fct.def.delete]") of a function is a function definition
whose [*function-body*](#nt:function-body "9.6.1General[dcl.fct.def.general]") is a [*deleted-function-body*](#nt:deleted-function-body "9.6.1General[dcl.fct.def.general]") or an explicitly-defaulted definition of the function where the function is
defined as deleted[.](#delete-1.sentence-1)
A [*deleted function*](#def:function,deleted "9.6.3Deleted definitions[dcl.fct.def.delete]") is
a function with a
deleted definition or a function that is implicitly defined as deleted[.](#delete-1.sentence-2)
[2](#delete-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L7117)
A construct that designates a deleted function implicitly or explicitly,
other than to declare it or to appear as the operand of
a [*reflect-expression*](expr.reflect#nt:reflect-expression "7.6.2.10The reflection operator[expr.reflect]") ([[expr.reflect]](expr.reflect "7.6.2.10The reflection operator")),
is ill-formed[.](#delete-2.sentence-1)
*Recommended practice*: The resulting diagnostic message should include
the text of the [*unevaluated-string*](lex.string.uneval#nt:unevaluated-string "5.13.6Unevaluated strings[lex.string.uneval]"),
if one is supplied[.](#delete-2.sentence-2)
[*Note [1](#delete-note-1)*:
This includes calling the function
implicitly or explicitly and forming a pointer or pointer-to-member to the
function[.](#delete-2.sentence-3)
It applies even for references in expressions that are not
potentially-evaluated[.](#delete-2.sentence-4)
For an overload set, only the
function selected by overload resolution is referenced[.](#delete-2.sentence-5)
The implicit
odr-use ([[basic.def.odr]](basic.def.odr#term.odr.use "6.3One-definition rule")) of a virtual function does not, by itself,
constitute a reference[.](#delete-2.sentence-6)
The [*unevaluated-string*](lex.string.uneval#nt:unevaluated-string "5.13.6Unevaluated strings[lex.string.uneval]"), if present,
can be used to explain the rationale for deletion and/or
to suggest an alternative[.](#delete-2.sentence-7)
— *end note*]
[3](#delete-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L7141)
[*Example [1](#delete-example-1)*:
One can prevent default initialization and
initialization by non-doubles withstruct onlydouble { onlydouble() = delete; // OK, but redundanttemplate<class T> onlydouble(T) = delete;
onlydouble(double);};
— *end example*]
[*Example [2](#delete-example-2)*:
One can prevent use of a
class in certain [*new-expression*](expr.new#nt:new-expression "7.6.2.8New[expr.new]")*s* by using deleted definitions
of a user-declared operator new for that class[.](#delete-3.sentence-2)
struct sometype {void* operator new(std::size_t) = delete; void* operator new[](std::size_t) = delete;};
sometype* p = new sometype; // error: deleted class operator new sometype* q = new sometype[3]; // error: deleted class operator new[] — *end example*]
[*Example [3](#delete-example-3)*:
One can make a class uncopyable, i.e., move-only, by using deleted
definitions of the copy constructor and copy assignment operator, and then
providing defaulted definitions of the move constructor and move assignment operator[.](#delete-3.sentence-3)
struct moveonly { moveonly() = default;
moveonly(const moveonly&) = delete;
moveonly(moveonly&&) = default;
moveonly& operator=(const moveonly&) = delete;
moveonly& operator=(moveonly&&) = default; ~moveonly() = default;};
moveonly* p;
moveonly q(*p); // error: deleted copy constructor — *end example*]
[4](#delete-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L7187)
A deleted function is implicitly an inline function ([[dcl.inline]](dcl.inline "9.2.8The inline specifier"))[.](#delete-4.sentence-1)
[*Note [2](#delete-note-2)*:
The
one-definition rule ([[basic.def.odr]](basic.def.odr "6.3One-definition rule")) applies to deleted definitions[.](#delete-4.sentence-2)
— *end note*]
A deleted definition of a function shall be the first declaration of the function or,
for an explicit specialization of a function template, the first declaration of that
specialization[.](#delete-4.sentence-3)
An implicitly declared allocation or deallocation function ([[basic.stc.dynamic]](basic.stc.dynamic "6.8.6.5Dynamic storage duration"))
shall not be defined as deleted[.](#delete-4.sentence-4)
[*Example [4](#delete-example-4)*: struct sometype { sometype();};
sometype::sometype() = delete; // error: not first declaration — *end example*]
### [9.6.4](#coroutine) Coroutine definitions [[dcl.fct.def.coroutine]](dcl.fct.def.coroutine)
[1](#coroutine-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L7211)
A function is a [*coroutine*](#def:coroutine "9.6.4Coroutine definitions[dcl.fct.def.coroutine]") if its [*function-body*](#nt:function-body "9.6.1General[dcl.fct.def.general]") encloses a[*coroutine-return-statement*](stmt.return.coroutine#nt:coroutine-return-statement "8.8.5The co_­return statement[stmt.return.coroutine]") ([[stmt.return.coroutine]](stmt.return.coroutine "8.8.5The co_­return statement")),
an [*await-expression*](expr.await#nt:await-expression "7.6.2.4Await[expr.await]") ([[expr.await]](expr.await "7.6.2.4Await")),
or a [*yield-expression*](expr.yield#nt:yield-expression "7.6.17Yielding a value[expr.yield]") ([[expr.yield]](expr.yield "7.6.17Yielding a value"))[.](#coroutine-1.sentence-1)
The [*parameter-declaration-clause*](dcl.fct#nt:parameter-declaration-clause "9.3.4.6Functions[dcl.fct]") of the coroutine shall not
terminate with an ellipsis that is not part of
a [*parameter-declaration*](dcl.fct#nt:parameter-declaration "9.3.4.6Functions[dcl.fct]")[.](#coroutine-1.sentence-2)
[2](#coroutine-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L7220)
[*Example [1](#coroutine-example-1)*: task<int> f();
task<void> g1() {int i = co_await f();
std::cout << "f() => " << i << std::endl;}template <typename... Args> task<void> g2(Args&&...) { // OK, ellipsis is a pack expansionint i = co_await f();
std::cout << "f() => " << i << std::endl;} task<void> g3(int a, ...) { // error: variable parameter list not allowedint i = co_await f();
std::cout << "f() => " << i << std::endl;} — *end example*]
[3](#coroutine-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L7243)
The [*promise type*](#def:coroutine,promise_type "9.6.4Coroutine definitions[dcl.fct.def.coroutine]") of a coroutine isstd::coroutine_traits<R, P1, …, Pn>::promise_type,
whereR is the return type of the function, andP1…Pn is the sequence of types of the non-object function parameters,
preceded by the type of the object parameter ([[dcl.fct]](dcl.fct "9.3.4.6Functions"))
if the coroutine is a non-static member function[.](#coroutine-3.sentence-1)
The promise type shall be a class type[.](#coroutine-3.sentence-2)
[4](#coroutine-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L7254)
In the following, pi is an lvalue of type Pi,
wherep1 denotes the object parameter andpi+1 denotes the ith non-object function parameter
for an implicit object member function, andpi denotes
the ith function parameter otherwise[.](#coroutine-4.sentence-1)
For an implicit object member function,q1 is an lvalue that denotes *this;
any other qi is an lvalue
that denotes the parameter copy corresponding to pi,
as described below[.](#coroutine-4.sentence-2)
[5](#coroutine-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L7268)
A coroutine behaves as if
the top-level cv-qualifiers in all[*parameter-declaration*](dcl.fct#nt:parameter-declaration "9.3.4.6Functions[dcl.fct]")*s* in the declarator
of its [*function-definition*](#nt:function-definition "9.6.1General[dcl.fct.def.general]") were removed and
its [*function-body*](#nt:function-body "9.6.1General[dcl.fct.def.general]") were replaced by
the following [*replacement body*](#def:body,replacement "9.6.4Coroutine definitions[dcl.fct.def.coroutine]"):
{
*promise-type* *promise* *promise-constructor-arguments* ;
try {
co_await *promise*.initial_suspend() ;
[*function-body*](#nt:function-body "9.6.1General[dcl.fct.def.general]")
} catch ( ... ) {
if (!*initial-await-resume-called*)
throw ;
*promise*.unhandled_exception() ;
}
*final-suspend* :
co_await *promise*.final_suspend() ;
}
where
- [(5.1)](#coroutine-5.1)
the [*await-expression*](expr.await#nt:await-expression "7.6.2.4Await[expr.await]") containing
the call to initial_suspend is the [*initial await expression*](#def:await_expression,initial "9.6.4Coroutine definitions[dcl.fct.def.coroutine]"), and
- [(5.2)](#coroutine-5.2)
the [*await-expression*](expr.await#nt:await-expression "7.6.2.4Await[expr.await]") containing
the call to final_suspend is the [*final await expression*](#def:await_expression,final "9.6.4Coroutine definitions[dcl.fct.def.coroutine]"), and
- [(5.3)](#coroutine-5.3)
*initial-await-resume-called* is initially false and is set to true immediately before the evaluation
of the *await-resume* expression ([[expr.await]](expr.await "7.6.2.4Await"))
of the initial await expression, and
- [(5.4)](#coroutine-5.4)
*promise-type* denotes the promise type, and
- [(5.5)](#coroutine-5.5)
the object denoted by the exposition-only name *promise* is the [*promise object*](#def:promise_object "9.6.4Coroutine definitions[dcl.fct.def.coroutine]") of the coroutine, and
- [(5.6)](#coroutine-5.6)
the label denoted by the name *final-suspend* is defined for exposition only ([[stmt.return.coroutine]](stmt.return.coroutine "8.8.5The co_­return statement")), and
- [(5.7)](#coroutine-5.7)
*promise-constructor-arguments* is determined as follows:
overload resolution is performed on a promise constructor call created by
assembling an argument list q1…qn[.](#coroutine-5.7.sentence-1)
If a viable
constructor is found ([[over.match.viable]](over.match.viable "12.2.3Viable functions")), then*promise-constructor-arguments* is(q1, …, qn), otherwise*promise-constructor-arguments* is empty, and
- [(5.8)](#coroutine-5.8)
a coroutine is suspended at the [*initial suspend point*](#def:suspend_point,initial "9.6.4Coroutine definitions[dcl.fct.def.coroutine]") if
it is suspended at the initial await expression, and
- [(5.9)](#coroutine-5.9)
a coroutine is suspended at a [*final suspend point*](#def:suspend_point,final "9.6.4Coroutine definitions[dcl.fct.def.coroutine]") if
it is suspended
* [(5.9.1)](#coroutine-5.9.1)
at a final await expression or
* [(5.9.2)](#coroutine-5.9.2)
due to an exception exiting from unhandled_exception()[.](#coroutine-5.9.sentence-1)
[6](#coroutine-6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L7340)
[*Note [1](#coroutine-note-1)*:
An odr-use of a non-reference parameter
in a postcondition assertion
of a coroutine is ill-formed ([[dcl.contract.func]](dcl.contract.func "9.4.1General"))[.](#coroutine-6.sentence-1)
— *end note*]
[7](#coroutine-7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L7347)
If searches for the names return_void and return_value in the scope of the promise type each find any declarations,
the program is ill-formed[.](#coroutine-7.sentence-1)
[*Note [2](#coroutine-note-2)*:
If return_void is found, flowing off
the end of a coroutine is equivalent to a co_return with no operand[.](#coroutine-7.sentence-2)
Otherwise, flowing off the end of a coroutine
results in undefined behavior ([[stmt.return.coroutine]](stmt.return.coroutine "8.8.5The co_­return statement"))[.](#coroutine-7.sentence-3)
— *end note*]
[8](#coroutine-8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L7358)
The expression *promise*.get_return_object() is used
to initialize
the returned reference or prvalue result object of a call to a coroutine[.](#coroutine-8.sentence-1)
The call to get_return_object is sequenced before
the call to initial_suspend and is invoked at most once[.](#coroutine-8.sentence-2)
[9](#coroutine-9)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L7367)
A suspended coroutine can be resumed to continue execution by invoking
a resumption member function ([[coroutine.handle.resumption]](coroutine.handle.resumption "17.13.4.6Resumption"))
of a coroutine handle ([[coroutine.handle]](coroutine.handle "17.13.4Class template coroutine_­handle"))
that refers to the coroutine[.](#coroutine-9.sentence-1)
The evaluation that invoked a resumption member function is
called the [*resumer*](#def:coroutine,resumer "9.6.4Coroutine definitions[dcl.fct.def.coroutine]")[.](#coroutine-9.sentence-2)
Invoking a resumption member function for a coroutine
that is not suspended results in undefined behavior[.](#coroutine-9.sentence-3)
[10](#coroutine-10)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L7377)
An implementation may need to allocate additional storage for a coroutine[.](#coroutine-10.sentence-1)
This storage is known as the [*coroutine state*](#def:coroutine_state "9.6.4Coroutine definitions[dcl.fct.def.coroutine]") and is obtained by calling
a non-array allocation function ([[basic.stc.dynamic.allocation]](basic.stc.dynamic.allocation "6.8.6.5.2Allocation functions"))
as part of the replacement body[.](#coroutine-10.sentence-2)
The allocation function's name is looked up by searching for it in the scope of the promise type[.](#coroutine-10.sentence-3)
- [(10.1)](#coroutine-10.1)
If the search finds any declarations,
overload resolution is performed on a function call created by assembling an
argument list[.](#coroutine-10.1.sentence-1)
The first argument is the amount of space requested, and
is a prvalue of type std::size_t[.](#coroutine-10.1.sentence-2)
The lvalues p1…pn with their original types (including cv-qualifiers)
are the successive arguments[.](#coroutine-10.1.sentence-3)
If no viable function is found ([[over.match.viable]](over.match.viable "12.2.3Viable functions")),
overload resolution is performed again
on a function call created by passing just
the amount of space required as a prvalue of type std::size_t[.](#coroutine-10.1.sentence-4)
- [(10.2)](#coroutine-10.2)
If the search finds no declarations, a search is performed in the global scope[.](#coroutine-10.2.sentence-1)
Overload resolution is performed on a function call created by
passing the amount of space required as a prvalue of type std::size_t[.](#coroutine-10.2.sentence-2)
[11](#coroutine-11)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L7402)
If a search for the name get_return_object_on_allocation_failure in the scope of the promise type ([[class.member.lookup]](class.member.lookup "6.5.2Member name lookup")) finds
any declarations, then the result
of a call to an allocation function used to obtain storage for the coroutine
state is assumed to return nullptr if it fails to obtain storage,
and if a global allocation function is selected,
the ::operator new(size_t, nothrow_t) form is used[.](#coroutine-11.sentence-1)
The allocation function used in this case shall have a non-throwing[*noexcept-specifier*](except.spec#nt:noexcept-specifier "14.5Exception specifications[except.spec]")[.](#coroutine-11.sentence-2)
If the allocation function returns nullptr, the coroutine transfers
control to the caller of the coroutine and the return value is obtained by a
call to T::get_return_object_on_allocation_failure(), where T is the promise type[.](#coroutine-11.sentence-3)
[*Example [2](#coroutine-example-2)*: #include <iostream>#include <coroutine>// ::operator new(size_t, nothrow_t) will be used if allocation is neededstruct generator {struct promise_type; using handle = std::coroutine_handle<promise_type>; struct promise_type {int current_value; static auto get_return_object_on_allocation_failure() { return generator{nullptr}; }auto get_return_object() { return generator{handle::from_promise(*this)}; }auto initial_suspend() { return std::suspend_always{}; }auto final_suspend() noexcept { return std::suspend_always{}; }void unhandled_exception() { std::terminate(); }void return_void() {}auto yield_value(int value) { current_value = value; return std::suspend_always{}; }}; bool move_next() { return coro ? (coro.resume(), !coro.done()) : false; }int current_value() { return coro.promise().current_value; } generator(generator const&) = delete;
generator(generator && rhs) : coro(rhs.coro) { rhs.coro = nullptr; }~generator() { if (coro) coro.destroy(); }private: generator(handle h) : coro(h) {} handle coro;};
generator f() { co_yield 1; co_yield 2; }int main() {auto g = f(); while (g.move_next()) std::cout << g.current_value() << std::endl;} — *end example*]
[12](#coroutine-12)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L7456)
The coroutine state is destroyed when control flows off the end of the
coroutine or the destroy member
function ([[coroutine.handle.resumption]](coroutine.handle.resumption "17.13.4.6Resumption"))
of a coroutine handle ([[coroutine.handle]](coroutine.handle "17.13.4Class template coroutine_­handle"))
that refers to the coroutine
is invoked[.](#coroutine-12.sentence-1)
In the latter case,
control in the coroutine is considered
to be transferred out of the function ([[stmt.dcl]](stmt.dcl "8.10Declaration statement"))[.](#coroutine-12.sentence-2)
The storage for the coroutine state is released by calling a
non-array deallocation function ([[basic.stc.dynamic.deallocation]](basic.stc.dynamic.deallocation "6.8.6.5.3Deallocation functions"))[.](#coroutine-12.sentence-3)
If destroy is called for a coroutine that is not suspended, the
program has undefined behavior[.](#coroutine-12.sentence-4)
[13](#coroutine-13)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L7471)
The deallocation function's name is looked up by searching for it in the scope of the promise type[.](#coroutine-13.sentence-1)
If nothing is found, a search is performed in the
global scope[.](#coroutine-13.sentence-2)
If both a usual deallocation
function with only a pointer parameter and a usual deallocation function with
both a pointer parameter and a size parameter are found, then the selected deallocation
function shall be the one with two parameters[.](#coroutine-13.sentence-3)
Otherwise, the selected
deallocation function shall be the function with one parameter[.](#coroutine-13.sentence-4)
If no usual
deallocation function is found, the program is ill-formed[.](#coroutine-13.sentence-5)
The selected deallocation function shall be called with the address of the
block of storage to be reclaimed as its first argument[.](#coroutine-13.sentence-6)
If a deallocation
function with a parameter of type std::size_t is used, the size of
the block is passed as the corresponding argument[.](#coroutine-13.sentence-7)
[14](#coroutine-14)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L7485)
When a coroutine is invoked,
a copy is created for each coroutine parameter
at the beginning of the replacement body[.](#coroutine-14.sentence-1)
For a parameter
whose original declaration specified the type cv T,
- [(14.1)](#coroutine-14.1)
if T is a reference type,
the copy is a reference of typecv T bound to the same object as a parameter;
- [(14.2)](#coroutine-14.2)
otherwise, the copy is a variable
of type cv T with automatic storage duration that is direct-initialized
from an xvalue of type T referring to the parameter[.](#coroutine-14.sentence-2)
[*Note [3](#coroutine-note-3)*:
An identifier in the [*function-body*](#nt:function-body "9.6.1General[dcl.fct.def.general]") that names one of these parameters
refers to the created copy,
not the original parameter ([[expr.prim.id.unqual]](expr.prim.id.unqual "7.5.5.2Unqualified names"))[.](#coroutine-14.sentence-3)
— *end note*]
The initialization and destruction of each parameter copy occurs in the
context of the called coroutine[.](#coroutine-14.sentence-4)
Initializations of parameter copies are sequenced before the call to the
coroutine promise constructor and indeterminately sequenced with respect to
each other[.](#coroutine-14.sentence-5)
The lifetime of parameter copies ends immediately after the lifetime of the
coroutine promise object ends[.](#coroutine-14.sentence-6)
[*Note [4](#coroutine-note-4)*:
If a coroutine has a parameter passed by reference, resuming the coroutine
after the lifetime of the entity referred to by that parameter has ended is
likely to result in undefined behavior[.](#coroutine-14.sentence-7)
— *end note*]
[15](#coroutine-15)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L7523)
If the evaluation of the expression*promise*.unhandled_exception() exits via an exception,
the coroutine is considered suspended at the final suspend point
and the exception propagates to the caller or resumer[.](#coroutine-15.sentence-1)
[16](#coroutine-16)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L7529)
The expression co_await *promise*.final_suspend() shall not be potentially-throwing ([[except.spec]](except.spec "14.5Exception specifications"))[.](#coroutine-16.sentence-1)
### [9.6.5](#replace) Replaceable function definitions [[dcl.fct.def.replace]](dcl.fct.def.replace)
[1](#replace-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L7538)
Certain functions
for which a definition is supplied by the implementation
are [*replaceable*](#def:function,replaceable "9.6.5Replaceable function definitions[dcl.fct.def.replace]")[.](#replace-1.sentence-1)
A C++ program may
provide a definition with the signature of a replaceable function,
called a [*replacement function*](#def:function,replacement "9.6.5Replaceable function definitions[dcl.fct.def.replace]")[.](#replace-1.sentence-2)
The replacement function
is used instead of the default version
supplied by the implementation[.](#replace-1.sentence-3)
Such replacement occurs
prior to program startup ([[basic.def.odr]](basic.def.odr "6.3One-definition rule"), [[basic.start]](basic.start "6.10.3Start and termination"))[.](#replace-1.sentence-4)
A declaration of the replacement function
- [(1.1)](#replace-1.1)
shall not be inline,
- [(1.2)](#replace-1.2)
shall be attached to the global module,
- [(1.3)](#replace-1.3)
shall have C++ language linkage,
- [(1.4)](#replace-1.4)
shall have the same return type as the replaceable function, and
- [(1.5)](#replace-1.5)
if the function is declared in a standard library header,
shall be such that it would be valid as a redeclaration
of the declaration in that header;
no diagnostic is required[.](#replace-1.sentence-5)
[*Note [1](#replace-note-1)*:
The one-definition rule ([[basic.def.odr]](basic.def.odr "6.3One-definition rule"))
applies to the definitions of a replaceable function
provided by the program[.](#replace-1.sentence-6)
The implementation-supplied function definition
is an otherwise-unnamed function with no linkage[.](#replace-1.sentence-7)
— *end note*]

View File

@@ -0,0 +1,352 @@
[dcl.fct.def.coroutine]
# 9 Declarations [[dcl]](./#dcl)
## 9.6 Function definitions [[dcl.fct.def]](dcl.fct.def#coroutine)
### 9.6.4 Coroutine definitions [dcl.fct.def.coroutine]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L7211)
A function is a [*coroutine*](#def:coroutine "9.6.4Coroutine definitions[dcl.fct.def.coroutine]") if its [*function-body*](dcl.fct.def.general#nt:function-body "9.6.1General[dcl.fct.def.general]") encloses a[*coroutine-return-statement*](stmt.return.coroutine#nt:coroutine-return-statement "8.8.5The co_­return statement[stmt.return.coroutine]") ([[stmt.return.coroutine]](stmt.return.coroutine "8.8.5The co_­return statement")),
an [*await-expression*](expr.await#nt:await-expression "7.6.2.4Await[expr.await]") ([[expr.await]](expr.await "7.6.2.4Await")),
or a [*yield-expression*](expr.yield#nt:yield-expression "7.6.17Yielding a value[expr.yield]") ([[expr.yield]](expr.yield "7.6.17Yielding a value"))[.](#1.sentence-1)
The [*parameter-declaration-clause*](dcl.fct#nt:parameter-declaration-clause "9.3.4.6Functions[dcl.fct]") of the coroutine shall not
terminate with an ellipsis that is not part of
a [*parameter-declaration*](dcl.fct#nt:parameter-declaration "9.3.4.6Functions[dcl.fct]")[.](#1.sentence-2)
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L7220)
[*Example [1](#example-1)*: task<int> f();
task<void> g1() {int i = co_await f();
std::cout << "f() => " << i << std::endl;}template <typename... Args> task<void> g2(Args&&...) { // OK, ellipsis is a pack expansionint i = co_await f();
std::cout << "f() => " << i << std::endl;} task<void> g3(int a, ...) { // error: variable parameter list not allowedint i = co_await f();
std::cout << "f() => " << i << std::endl;} — *end example*]
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L7243)
The [*promise type*](#def:coroutine,promise_type "9.6.4Coroutine definitions[dcl.fct.def.coroutine]") of a coroutine isstd::coroutine_traits<R, P1, …, Pn>::promise_type,
whereR is the return type of the function, andP1…Pn is the sequence of types of the non-object function parameters,
preceded by the type of the object parameter ([[dcl.fct]](dcl.fct "9.3.4.6Functions"))
if the coroutine is a non-static member function[.](#3.sentence-1)
The promise type shall be a class type[.](#3.sentence-2)
[4](#4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L7254)
In the following, pi is an lvalue of type Pi,
wherep1 denotes the object parameter andpi+1 denotes the ith non-object function parameter
for an implicit object member function, andpi denotes
the ith function parameter otherwise[.](#4.sentence-1)
For an implicit object member function,q1 is an lvalue that denotes *this;
any other qi is an lvalue
that denotes the parameter copy corresponding to pi,
as described below[.](#4.sentence-2)
[5](#5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L7268)
A coroutine behaves as if
the top-level cv-qualifiers in all[*parameter-declaration*](dcl.fct#nt:parameter-declaration "9.3.4.6Functions[dcl.fct]")*s* in the declarator
of its [*function-definition*](dcl.fct.def.general#nt:function-definition "9.6.1General[dcl.fct.def.general]") were removed and
its [*function-body*](dcl.fct.def.general#nt:function-body "9.6.1General[dcl.fct.def.general]") were replaced by
the following [*replacement body*](#def:body,replacement "9.6.4Coroutine definitions[dcl.fct.def.coroutine]"):
{
*promise-type* *promise* *promise-constructor-arguments* ;
try {
co_await *promise*.initial_suspend() ;
[*function-body*](dcl.fct.def.general#nt:function-body "9.6.1General[dcl.fct.def.general]")
} catch ( ... ) {
if (!*initial-await-resume-called*)
throw ;
*promise*.unhandled_exception() ;
}
*final-suspend* :
co_await *promise*.final_suspend() ;
}
where
- [(5.1)](#5.1)
the [*await-expression*](expr.await#nt:await-expression "7.6.2.4Await[expr.await]") containing
the call to initial_suspend is the [*initial await expression*](#def:await_expression,initial "9.6.4Coroutine definitions[dcl.fct.def.coroutine]"), and
- [(5.2)](#5.2)
the [*await-expression*](expr.await#nt:await-expression "7.6.2.4Await[expr.await]") containing
the call to final_suspend is the [*final await expression*](#def:await_expression,final "9.6.4Coroutine definitions[dcl.fct.def.coroutine]"), and
- [(5.3)](#5.3)
*initial-await-resume-called* is initially false and is set to true immediately before the evaluation
of the *await-resume* expression ([[expr.await]](expr.await "7.6.2.4Await"))
of the initial await expression, and
- [(5.4)](#5.4)
*promise-type* denotes the promise type, and
- [(5.5)](#5.5)
the object denoted by the exposition-only name *promise* is the [*promise object*](#def:promise_object "9.6.4Coroutine definitions[dcl.fct.def.coroutine]") of the coroutine, and
- [(5.6)](#5.6)
the label denoted by the name *final-suspend* is defined for exposition only ([[stmt.return.coroutine]](stmt.return.coroutine "8.8.5The co_­return statement")), and
- [(5.7)](#5.7)
*promise-constructor-arguments* is determined as follows:
overload resolution is performed on a promise constructor call created by
assembling an argument list q1…qn[.](#5.7.sentence-1)
If a viable
constructor is found ([[over.match.viable]](over.match.viable "12.2.3Viable functions")), then*promise-constructor-arguments* is(q1, …, qn), otherwise*promise-constructor-arguments* is empty, and
- [(5.8)](#5.8)
a coroutine is suspended at the [*initial suspend point*](#def:suspend_point,initial "9.6.4Coroutine definitions[dcl.fct.def.coroutine]") if
it is suspended at the initial await expression, and
- [(5.9)](#5.9)
a coroutine is suspended at a [*final suspend point*](#def:suspend_point,final "9.6.4Coroutine definitions[dcl.fct.def.coroutine]") if
it is suspended
* [(5.9.1)](#5.9.1)
at a final await expression or
* [(5.9.2)](#5.9.2)
due to an exception exiting from unhandled_exception()[.](#5.9.sentence-1)
[6](#6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L7340)
[*Note [1](#note-1)*:
An odr-use of a non-reference parameter
in a postcondition assertion
of a coroutine is ill-formed ([[dcl.contract.func]](dcl.contract.func "9.4.1General"))[.](#6.sentence-1)
— *end note*]
[7](#7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L7347)
If searches for the names return_void and return_value in the scope of the promise type each find any declarations,
the program is ill-formed[.](#7.sentence-1)
[*Note [2](#note-2)*:
If return_void is found, flowing off
the end of a coroutine is equivalent to a co_return with no operand[.](#7.sentence-2)
Otherwise, flowing off the end of a coroutine
results in undefined behavior ([[stmt.return.coroutine]](stmt.return.coroutine "8.8.5The co_­return statement"))[.](#7.sentence-3)
— *end note*]
[8](#8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L7358)
The expression *promise*.get_return_object() is used
to initialize
the returned reference or prvalue result object of a call to a coroutine[.](#8.sentence-1)
The call to get_return_object is sequenced before
the call to initial_suspend and is invoked at most once[.](#8.sentence-2)
[9](#9)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L7367)
A suspended coroutine can be resumed to continue execution by invoking
a resumption member function ([[coroutine.handle.resumption]](coroutine.handle.resumption "17.13.4.6Resumption"))
of a coroutine handle ([[coroutine.handle]](coroutine.handle "17.13.4Class template coroutine_­handle"))
that refers to the coroutine[.](#9.sentence-1)
The evaluation that invoked a resumption member function is
called the [*resumer*](#def:coroutine,resumer "9.6.4Coroutine definitions[dcl.fct.def.coroutine]")[.](#9.sentence-2)
Invoking a resumption member function for a coroutine
that is not suspended results in undefined behavior[.](#9.sentence-3)
[10](#10)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L7377)
An implementation may need to allocate additional storage for a coroutine[.](#10.sentence-1)
This storage is known as the [*coroutine state*](#def:coroutine_state "9.6.4Coroutine definitions[dcl.fct.def.coroutine]") and is obtained by calling
a non-array allocation function ([[basic.stc.dynamic.allocation]](basic.stc.dynamic.allocation "6.8.6.5.2Allocation functions"))
as part of the replacement body[.](#10.sentence-2)
The allocation function's name is looked up by searching for it in the scope of the promise type[.](#10.sentence-3)
- [(10.1)](#10.1)
If the search finds any declarations,
overload resolution is performed on a function call created by assembling an
argument list[.](#10.1.sentence-1)
The first argument is the amount of space requested, and
is a prvalue of type std::size_t[.](#10.1.sentence-2)
The lvalues p1…pn with their original types (including cv-qualifiers)
are the successive arguments[.](#10.1.sentence-3)
If no viable function is found ([[over.match.viable]](over.match.viable "12.2.3Viable functions")),
overload resolution is performed again
on a function call created by passing just
the amount of space required as a prvalue of type std::size_t[.](#10.1.sentence-4)
- [(10.2)](#10.2)
If the search finds no declarations, a search is performed in the global scope[.](#10.2.sentence-1)
Overload resolution is performed on a function call created by
passing the amount of space required as a prvalue of type std::size_t[.](#10.2.sentence-2)
[11](#11)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L7402)
If a search for the name get_return_object_on_allocation_failure in the scope of the promise type ([[class.member.lookup]](class.member.lookup "6.5.2Member name lookup")) finds
any declarations, then the result
of a call to an allocation function used to obtain storage for the coroutine
state is assumed to return nullptr if it fails to obtain storage,
and if a global allocation function is selected,
the ::operator new(size_t, nothrow_t) form is used[.](#11.sentence-1)
The allocation function used in this case shall have a non-throwing[*noexcept-specifier*](except.spec#nt:noexcept-specifier "14.5Exception specifications[except.spec]")[.](#11.sentence-2)
If the allocation function returns nullptr, the coroutine transfers
control to the caller of the coroutine and the return value is obtained by a
call to T::get_return_object_on_allocation_failure(), where T is the promise type[.](#11.sentence-3)
[*Example [2](#example-2)*: #include <iostream>#include <coroutine>// ::operator new(size_t, nothrow_t) will be used if allocation is neededstruct generator {struct promise_type; using handle = std::coroutine_handle<promise_type>; struct promise_type {int current_value; static auto get_return_object_on_allocation_failure() { return generator{nullptr}; }auto get_return_object() { return generator{handle::from_promise(*this)}; }auto initial_suspend() { return std::suspend_always{}; }auto final_suspend() noexcept { return std::suspend_always{}; }void unhandled_exception() { std::terminate(); }void return_void() {}auto yield_value(int value) { current_value = value; return std::suspend_always{}; }}; bool move_next() { return coro ? (coro.resume(), !coro.done()) : false; }int current_value() { return coro.promise().current_value; } generator(generator const&) = delete;
generator(generator && rhs) : coro(rhs.coro) { rhs.coro = nullptr; }~generator() { if (coro) coro.destroy(); }private: generator(handle h) : coro(h) {} handle coro;};
generator f() { co_yield 1; co_yield 2; }int main() {auto g = f(); while (g.move_next()) std::cout << g.current_value() << std::endl;} — *end example*]
[12](#12)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L7456)
The coroutine state is destroyed when control flows off the end of the
coroutine or the destroy member
function ([[coroutine.handle.resumption]](coroutine.handle.resumption "17.13.4.6Resumption"))
of a coroutine handle ([[coroutine.handle]](coroutine.handle "17.13.4Class template coroutine_­handle"))
that refers to the coroutine
is invoked[.](#12.sentence-1)
In the latter case,
control in the coroutine is considered
to be transferred out of the function ([[stmt.dcl]](stmt.dcl "8.10Declaration statement"))[.](#12.sentence-2)
The storage for the coroutine state is released by calling a
non-array deallocation function ([[basic.stc.dynamic.deallocation]](basic.stc.dynamic.deallocation "6.8.6.5.3Deallocation functions"))[.](#12.sentence-3)
If destroy is called for a coroutine that is not suspended, the
program has undefined behavior[.](#12.sentence-4)
[13](#13)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L7471)
The deallocation function's name is looked up by searching for it in the scope of the promise type[.](#13.sentence-1)
If nothing is found, a search is performed in the
global scope[.](#13.sentence-2)
If both a usual deallocation
function with only a pointer parameter and a usual deallocation function with
both a pointer parameter and a size parameter are found, then the selected deallocation
function shall be the one with two parameters[.](#13.sentence-3)
Otherwise, the selected
deallocation function shall be the function with one parameter[.](#13.sentence-4)
If no usual
deallocation function is found, the program is ill-formed[.](#13.sentence-5)
The selected deallocation function shall be called with the address of the
block of storage to be reclaimed as its first argument[.](#13.sentence-6)
If a deallocation
function with a parameter of type std::size_t is used, the size of
the block is passed as the corresponding argument[.](#13.sentence-7)
[14](#14)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L7485)
When a coroutine is invoked,
a copy is created for each coroutine parameter
at the beginning of the replacement body[.](#14.sentence-1)
For a parameter
whose original declaration specified the type cv T,
- [(14.1)](#14.1)
if T is a reference type,
the copy is a reference of typecv T bound to the same object as a parameter;
- [(14.2)](#14.2)
otherwise, the copy is a variable
of type cv T with automatic storage duration that is direct-initialized
from an xvalue of type T referring to the parameter[.](#14.sentence-2)
[*Note [3](#note-3)*:
An identifier in the [*function-body*](dcl.fct.def.general#nt:function-body "9.6.1General[dcl.fct.def.general]") that names one of these parameters
refers to the created copy,
not the original parameter ([[expr.prim.id.unqual]](expr.prim.id.unqual "7.5.5.2Unqualified names"))[.](#14.sentence-3)
— *end note*]
The initialization and destruction of each parameter copy occurs in the
context of the called coroutine[.](#14.sentence-4)
Initializations of parameter copies are sequenced before the call to the
coroutine promise constructor and indeterminately sequenced with respect to
each other[.](#14.sentence-5)
The lifetime of parameter copies ends immediately after the lifetime of the
coroutine promise object ends[.](#14.sentence-6)
[*Note [4](#note-4)*:
If a coroutine has a parameter passed by reference, resuming the coroutine
after the lifetime of the entity referred to by that parameter has ended is
likely to result in undefined behavior[.](#14.sentence-7)
— *end note*]
[15](#15)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L7523)
If the evaluation of the expression*promise*.unhandled_exception() exits via an exception,
the coroutine is considered suspended at the final suspend point
and the exception propagates to the caller or resumer[.](#15.sentence-1)
[16](#16)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L7529)
The expression co_await *promise*.final_suspend() shall not be potentially-throwing ([[except.spec]](except.spec "14.5Exception specifications"))[.](#16.sentence-1)

View File

@@ -0,0 +1,158 @@
[dcl.fct.def.default]
# 9 Declarations [[dcl]](./#dcl)
## 9.6 Function definitions [[dcl.fct.def]](dcl.fct.def#default)
### 9.6.2 Explicitly-defaulted functions [dcl.fct.def.default]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L6967)
A function definition whose[*function-body*](dcl.fct.def.general#nt:function-body "9.6.1General[dcl.fct.def.general]") is of the form= default ; is called an [*explicitly-defaulted*](#def:definition,function,explicitly-defaulted "9.6.2Explicitly-defaulted functions[dcl.fct.def.default]") definition[.](#1.sentence-1)
A function that is explicitly defaulted shall
- [(1.1)](#1.1)
be a special member function ([[special]](special "11.4.4Special member functions")) or
a comparison operator function ([[over.binary]](over.binary "12.4.3Binary operators"), [[class.compare.default]](class.compare.default "11.10.1Defaulted comparison operator functions")), and
- [(1.2)](#1.2)
not have default arguments ([[dcl.fct.default]](dcl.fct.default "9.3.4.7Default arguments"))[.](#1.sentence-2)
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L6980)
An explicitly defaulted special member function F1 is allowed to differ from
the corresponding special member function F2 that would have been implicitly declared, as follows:
- [(2.1)](#2.1)
F1 and F2 may have differing [*ref-qualifier*](dcl.decl.general#nt:ref-qualifier "9.3.1General[dcl.decl.general]")*s*;
- [(2.2)](#2.2)
if F2 has an implicit object parameter of
type “reference to C”, F1 may be an explicit object member function whose
explicit object parameter is of (possibly different) type “reference to C”,
in which case the type of F1 would differ from the type of F2 in that the type of F1 has an additional parameter;
- [(2.3)](#2.3)
F1 and F2 may have differing exception specifications; and
- [(2.4)](#2.4)
if F2 has a non-object parameter of type const C&,
the corresponding non-object parameter of F1 may be of
type C&[.](#2.sentence-1)
If the type of F1 differs from the type of F2 in a way
other than as allowed by the preceding rules, then:
- [(2.5)](#2.5)
if F1 is an assignment operator, and
the return type of F1 differs from
the return type of F2 or F1's non-object parameter type is not a reference,
the program is ill-formed;
- [(2.6)](#2.6)
otherwise, if F1 is explicitly defaulted on its first declaration,
it is defined as deleted;
- [(2.7)](#2.7)
otherwise, the program is ill-formed[.](#2.sentence-2)
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L7018)
A function explicitly defaulted on its first declaration
is implicitly inline ([[dcl.inline]](dcl.inline "9.2.8The inline specifier")),
and is implicitly constexpr ([[dcl.constexpr]](dcl.constexpr "9.2.6The constexpr and consteval specifiers"))
if it is constexpr-suitable[.](#3.sentence-1)
[*Note [1](#note-1)*:
Other defaulted functions are not implicitly constexpr[.](#3.sentence-2)
— *end note*]
[4](#4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L7027)
[*Example [1](#example-1)*: struct S { S(int a = 0) = default; // error: default argumentvoid operator=(const S&) = default; // error: non-matching return type~S() noexcept(false) = default; // OK, despite mismatched exception specificationprivate:int i;
S(S&); // OK, private copy constructor};
S::S(S&) = default; // OK, defines copy constructorstruct T { T();
T(T &&) noexcept(false);};struct U { T t;
U();
U(U &&) noexcept = default;};
U u1;
U u2 = static_cast<U&&>(u1); // OK, calls std::terminate if T::T(T&&) throws — *end example*]
[5](#5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L7054)
Explicitly-defaulted functions and implicitly-declared functions are collectively
called [*defaulted*](#def:defaulted "9.6.2Explicitly-defaulted functions[dcl.fct.def.default]") functions, and the implementation
shall provide implicit definitions
for them ([[class.ctor]](class.ctor "11.4.5Constructors"), [[class.dtor]](class.dtor "11.4.7Destructors"), [[class.copy.ctor]](class.copy.ctor "11.4.5.3Copy/move constructors"), [[class.copy.assign]](class.copy.assign "11.4.6Copy/move assignment operator")) as described below,
including possibly defining them as deleted[.](#5.sentence-1)
A defaulted prospective destructor ([[class.dtor]](class.dtor "11.4.7Destructors"))
that is not a destructor is defined as deleted[.](#5.sentence-2)
A defaulted special member function
that is neither a prospective destructor nor
an eligible special member function ([[special]](special "11.4.4Special member functions"))
is defined as deleted[.](#5.sentence-3)
A function is[*user-provided*](#def:user-provided "9.6.2Explicitly-defaulted functions[dcl.fct.def.default]") if it is user-declared and not explicitly
defaulted or deleted on its first declaration[.](#5.sentence-4)
A user-provided explicitly-defaulted function
(i.e., explicitly defaulted after its first declaration)
is implicitly defined at the point where it is explicitly defaulted; if such a function is implicitly
defined as deleted, the program is ill-formed[.](#5.sentence-5)
[*Note [2](#note-2)*:
Declaring a function as defaulted after its first declaration
can provide efficient execution and concise definition
while enabling a stable binary interface to an evolving code base[.](#5.sentence-6)
— *end note*]
A non-user-provided defaulted function
(i.e., implicitly declared or explicitly defaulted in the class)
that is not defined as deleted is implicitly defined when it is odr-used ([[basic.def.odr]](basic.def.odr "6.3One-definition rule"))
or needed for constant evaluation ([[expr.const]](expr.const "7.7Constant expressions"))[.](#5.sentence-7)
[*Note [3](#note-3)*:
The implicit definition of a non-user-provided defaulted function
does not bind any names[.](#5.sentence-8)
— *end note*]
[6](#6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L7086)
[*Example [2](#example-2)*: struct trivial { trivial() = default;
trivial(const trivial&) = default;
trivial(trivial&&) = default;
trivial& operator=(const trivial&) = default;
trivial& operator=(trivial&&) = default; ~trivial() = default;};
struct nontrivial1 { nontrivial1();};
nontrivial1::nontrivial1() = default; // not first declaration — *end example*]

View File

@@ -0,0 +1,112 @@
[dcl.fct.def.delete]
# 9 Declarations [[dcl]](./#dcl)
## 9.6 Function definitions [[dcl.fct.def]](dcl.fct.def#delete)
### 9.6.3 Deleted definitions [dcl.fct.def.delete]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L7108)
A [*deleted definition*](#def:definition,deleted "9.6.3Deleted definitions[dcl.fct.def.delete]") of a function is a function definition
whose [*function-body*](dcl.fct.def.general#nt:function-body "9.6.1General[dcl.fct.def.general]") is a [*deleted-function-body*](dcl.fct.def.general#nt:deleted-function-body "9.6.1General[dcl.fct.def.general]") or an explicitly-defaulted definition of the function where the function is
defined as deleted[.](#1.sentence-1)
A [*deleted function*](#def:function,deleted "9.6.3Deleted definitions[dcl.fct.def.delete]") is
a function with a
deleted definition or a function that is implicitly defined as deleted[.](#1.sentence-2)
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L7117)
A construct that designates a deleted function implicitly or explicitly,
other than to declare it or to appear as the operand of
a [*reflect-expression*](expr.reflect#nt:reflect-expression "7.6.2.10The reflection operator[expr.reflect]") ([[expr.reflect]](expr.reflect "7.6.2.10The reflection operator")),
is ill-formed[.](#2.sentence-1)
*Recommended practice*: The resulting diagnostic message should include
the text of the [*unevaluated-string*](lex.string.uneval#nt:unevaluated-string "5.13.6Unevaluated strings[lex.string.uneval]"),
if one is supplied[.](#2.sentence-2)
[*Note [1](#note-1)*:
This includes calling the function
implicitly or explicitly and forming a pointer or pointer-to-member to the
function[.](#2.sentence-3)
It applies even for references in expressions that are not
potentially-evaluated[.](#2.sentence-4)
For an overload set, only the
function selected by overload resolution is referenced[.](#2.sentence-5)
The implicit
odr-use ([[basic.def.odr]](basic.def.odr#term.odr.use "6.3One-definition rule")) of a virtual function does not, by itself,
constitute a reference[.](#2.sentence-6)
The [*unevaluated-string*](lex.string.uneval#nt:unevaluated-string "5.13.6Unevaluated strings[lex.string.uneval]"), if present,
can be used to explain the rationale for deletion and/or
to suggest an alternative[.](#2.sentence-7)
— *end note*]
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L7141)
[*Example [1](#example-1)*:
One can prevent default initialization and
initialization by non-doubles withstruct onlydouble { onlydouble() = delete; // OK, but redundanttemplate<class T> onlydouble(T) = delete;
onlydouble(double);};
— *end example*]
[*Example [2](#example-2)*:
One can prevent use of a
class in certain [*new-expression*](expr.new#nt:new-expression "7.6.2.8New[expr.new]")*s* by using deleted definitions
of a user-declared operator new for that class[.](#3.sentence-2)
struct sometype {void* operator new(std::size_t) = delete; void* operator new[](std::size_t) = delete;};
sometype* p = new sometype; // error: deleted class operator new sometype* q = new sometype[3]; // error: deleted class operator new[] — *end example*]
[*Example [3](#example-3)*:
One can make a class uncopyable, i.e., move-only, by using deleted
definitions of the copy constructor and copy assignment operator, and then
providing defaulted definitions of the move constructor and move assignment operator[.](#3.sentence-3)
struct moveonly { moveonly() = default;
moveonly(const moveonly&) = delete;
moveonly(moveonly&&) = default;
moveonly& operator=(const moveonly&) = delete;
moveonly& operator=(moveonly&&) = default; ~moveonly() = default;};
moveonly* p;
moveonly q(*p); // error: deleted copy constructor — *end example*]
[4](#4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L7187)
A deleted function is implicitly an inline function ([[dcl.inline]](dcl.inline "9.2.8The inline specifier"))[.](#4.sentence-1)
[*Note [2](#note-2)*:
The
one-definition rule ([[basic.def.odr]](basic.def.odr "6.3One-definition rule")) applies to deleted definitions[.](#4.sentence-2)
— *end note*]
A deleted definition of a function shall be the first declaration of the function or,
for an explicit specialization of a function template, the first declaration of that
specialization[.](#4.sentence-3)
An implicitly declared allocation or deallocation function ([[basic.stc.dynamic]](basic.stc.dynamic "6.8.6.5Dynamic storage duration"))
shall not be defined as deleted[.](#4.sentence-4)
[*Example [4](#example-4)*: struct sometype { sometype();};
sometype::sometype() = delete; // error: not first declaration — *end example*]

View File

@@ -0,0 +1,127 @@
[dcl.fct.def.general]
# 9 Declarations [[dcl]](./#dcl)
## 9.6 Function definitions [[dcl.fct.def]](dcl.fct.def#general)
### 9.6.1 General [dcl.fct.def.general]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L6827)
Function definitions have the form
[function-definition:](#nt:function-definition "9.6.1General[dcl.fct.def.general]")
[*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1Attribute syntax and semantics[dcl.attr.grammar]")opt [*decl-specifier-seq*](dcl.spec.general#nt:decl-specifier-seq "9.2.1General[dcl.spec.general]")opt [*declarator*](dcl.decl.general#nt:declarator "9.3.1General[dcl.decl.general]") [*virt-specifier-seq*](class.mem.general#nt:virt-specifier-seq "11.4.1General[class.mem.general]")opt
[*function-contract-specifier-seq*](dcl.contract.func#nt:function-contract-specifier-seq "9.4.1General[dcl.contract.func]")opt [*function-body*](#nt:function-body "9.6.1General[dcl.fct.def.general]")
[*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1Attribute syntax and semantics[dcl.attr.grammar]")opt [*decl-specifier-seq*](dcl.spec.general#nt:decl-specifier-seq "9.2.1General[dcl.spec.general]")opt [*declarator*](dcl.decl.general#nt:declarator "9.3.1General[dcl.decl.general]") [*requires-clause*](temp.pre#nt:requires-clause "13.1Preamble[temp.pre]")
[*function-contract-specifier-seq*](dcl.contract.func#nt:function-contract-specifier-seq "9.4.1General[dcl.contract.func]")opt [*function-body*](#nt:function-body "9.6.1General[dcl.fct.def.general]")
[function-body:](#nt:function-body "9.6.1General[dcl.fct.def.general]")
[*ctor-initializer*](class.base.init#nt:ctor-initializer "11.9.3Initializing bases and members[class.base.init]")opt [*compound-statement*](stmt.block#nt:compound-statement "8.4Compound statement or block[stmt.block]")
[*function-try-block*](except.pre#nt:function-try-block "14.1Preamble[except.pre]")
= default ;
[*deleted-function-body*](#nt:deleted-function-body "9.6.1General[dcl.fct.def.general]")
[deleted-function-body:](#nt:deleted-function-body "9.6.1General[dcl.fct.def.general]")
= delete ;
= delete ( [*unevaluated-string*](lex.string.uneval#nt:unevaluated-string "5.13.6Unevaluated strings[lex.string.uneval]") ) ;
Any informal reference to the body of a function should be interpreted as a reference to
the non-terminal [*function-body*](#nt:function-body "9.6.1General[dcl.fct.def.general]"),
including, for a constructor,
default member initializers or default initialization
used to initialize
a base or member subobject in the absence of
a [*mem-initializer-id*](class.base.init#nt:mem-initializer-id "11.9.3Initializing bases and members[class.base.init]") ([[class.base.init]](class.base.init "11.9.3Initializing bases and members"))[.](#1.sentence-2)
The optional [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") in a [*function-definition*](#nt:function-definition "9.6.1General[dcl.fct.def.general]") appertains to the function[.](#1.sentence-3)
A [*function-definition*](#nt:function-definition "9.6.1General[dcl.fct.def.general]") with a [*virt-specifier-seq*](class.mem.general#nt:virt-specifier-seq "11.4.1General[class.mem.general]") shall be a [*member-declaration*](class.mem.general#nt:member-declaration "11.4.1General[class.mem.general]") ([[class.mem]](class.mem "11.4Class members"))[.](#1.sentence-4)
A [*function-definition*](#nt:function-definition "9.6.1General[dcl.fct.def.general]") with a [*requires-clause*](temp.pre#nt:requires-clause "13.1Preamble[temp.pre]") shall define a templated function[.](#1.sentence-5)
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L6868)
In a [*function-definition*](#nt:function-definition "9.6.1General[dcl.fct.def.general]"),
either void [*declarator*](dcl.decl.general#nt:declarator "9.3.1General[dcl.decl.general]") ; or [*declarator*](dcl.decl.general#nt:declarator "9.3.1General[dcl.decl.general]") ; shall be a well-formed function declaration
as described in [[dcl.fct]](dcl.fct "9.3.4.6Functions")[.](#2.sentence-1)
A function shall be defined only in namespace or class scope[.](#2.sentence-2)
The type of a parameter or the return type for a function
definition shall not be
a (possibly cv-qualified) class type that is
incomplete or abstract within the function body
unless the function is deleted ([[dcl.fct.def.delete]](dcl.fct.def.delete "9.6.3Deleted definitions"))[.](#2.sentence-3)
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L6881)
[*Example [1](#example-1)*:
A simple example of a complete function definition isint max(int a, int b, int c) {int m = (a > b) ? a : b; return (m > c) ? m : c;}
Hereint is the[*decl-specifier-seq*](dcl.spec.general#nt:decl-specifier-seq "9.2.1General[dcl.spec.general]");max(inta,intb,intc) is the[*declarator*](dcl.decl.general#nt:declarator "9.3.1General[dcl.decl.general]");{ /* ... */ } is the[*function-body*](#nt:function-body "9.6.1General[dcl.fct.def.general]")[.](#3.sentence-2)
— *end example*]
[4](#4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L6908)
A[*ctor-initializer*](class.base.init#nt:ctor-initializer "11.9.3Initializing bases and members[class.base.init]") is used only in a constructor; see [[class.ctor]](class.ctor "11.4.5Constructors") and [[class.init]](class.init "11.9Initialization")[.](#4.sentence-1)
[5](#5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L6916)
[*Note [1](#note-1)*:
A [*cv-qualifier-seq*](dcl.decl.general#nt:cv-qualifier-seq "9.3.1General[dcl.decl.general]") affects the type of this in the body of a member function; see [[expr.prim.this]](expr.prim.this "7.5.3This")[.](#5.sentence-1)
— *end note*]
[6](#6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L6922)
[*Note [2](#note-2)*:
Unused parameters need not be named[.](#6.sentence-1)
For example,
void print(int a, int) { std::printf("a = %d\n",a);} — *end note*]
[7](#7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L6934)
A [*function-local predefined variable*](#def:variable,function-local_predefined "9.6.1General[dcl.fct.def.general]") is a variable with static
storage duration that is implicitly defined in a function parameter scope[.](#7.sentence-1)
[8](#8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L6938)
The function-local predefined variable __func__ is
defined as if a definition of the formstatic const char __func__[] = "*function-name*"; had been provided, where *function-name* is an implementation-defined string[.](#8.sentence-1)
It is unspecified whether such a variable has an address
distinct from that of any other object in the program[.](#8.sentence-2)[81](#footnote-81 "Implementations are permitted to provide additional predefined variables with names that are reserved to the implementation ([lex.name]). If a predefined variable is not odr-used ([term.odr.use]), its string value need not be present in the program image.")
[*Example [2](#example-2)*: struct S { S() : s(__func__) { } // OKconst char* s;};void f(const char* s = __func__); // error: __func__ is undeclared — *end example*]
[81)](#footnote-81)[81)](#footnoteref-81)
Implementations are
permitted to provide additional predefined variables with names that are reserved to the
implementation ([[lex.name]](lex.name "5.11Identifiers"))[.](#footnote-81.sentence-1)
If a predefined variable is not
odr-used ([[basic.def.odr]](basic.def.odr#term.odr.use "6.3One-definition rule")), its string value need not be present in the program image[.](#footnote-81.sentence-2)

View File

@@ -0,0 +1,63 @@
[dcl.fct.def.replace]
# 9 Declarations [[dcl]](./#dcl)
## 9.6 Function definitions [[dcl.fct.def]](dcl.fct.def#replace)
### 9.6.5 Replaceable function definitions [dcl.fct.def.replace]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L7538)
Certain functions
for which a definition is supplied by the implementation
are [*replaceable*](#def:function,replaceable "9.6.5Replaceable function definitions[dcl.fct.def.replace]")[.](#1.sentence-1)
A C++ program may
provide a definition with the signature of a replaceable function,
called a [*replacement function*](#def:function,replacement "9.6.5Replaceable function definitions[dcl.fct.def.replace]")[.](#1.sentence-2)
The replacement function
is used instead of the default version
supplied by the implementation[.](#1.sentence-3)
Such replacement occurs
prior to program startup ([[basic.def.odr]](basic.def.odr "6.3One-definition rule"), [[basic.start]](basic.start "6.10.3Start and termination"))[.](#1.sentence-4)
A declaration of the replacement function
- [(1.1)](#1.1)
shall not be inline,
- [(1.2)](#1.2)
shall be attached to the global module,
- [(1.3)](#1.3)
shall have C++ language linkage,
- [(1.4)](#1.4)
shall have the same return type as the replaceable function, and
- [(1.5)](#1.5)
if the function is declared in a standard library header,
shall be such that it would be valid as a redeclaration
of the declaration in that header;
no diagnostic is required[.](#1.sentence-5)
[*Note [1](#note-1)*:
The one-definition rule ([[basic.def.odr]](basic.def.odr "6.3One-definition rule"))
applies to the definitions of a replaceable function
provided by the program[.](#1.sentence-6)
The implementation-supplied function definition
is an otherwise-unnamed function with no linkage[.](#1.sentence-7)
— *end note*]

272
cppdraft/dcl/fct/default.md Normal file
View File

@@ -0,0 +1,272 @@
[dcl.fct.default]
# 9 Declarations [[dcl]](./#dcl)
## 9.3 Declarators [[dcl.decl]](dcl.decl#dcl.fct.default)
### 9.3.4 Meaning of declarators [[dcl.meaning]](dcl.meaning#dcl.fct.default)
#### 9.3.4.7 Default arguments [dcl.fct.default]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L4263)
If an [*initializer-clause*](dcl.init.general#nt:initializer-clause "9.5.1General[dcl.init.general]") is specified in a[*parameter-declaration*](dcl.fct#nt:parameter-declaration "9.3.4.6Functions[dcl.fct]") this[*initializer-clause*](dcl.init.general#nt:initializer-clause "9.5.1General[dcl.init.general]") is used as a default argument[.](#1.sentence-1)
[*Note [1](#note-1)*:
Default arguments will be used in calls
where trailing arguments are missing ([[expr.call]](expr.call "7.6.1.3Function call"))[.](#1.sentence-2)
— *end note*]
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L4273)
[*Example [1](#example-1)*:
The declarationvoid point(int = 3, int = 4); declares a function that can be called with zero, one, or two arguments of typeint[.](#2.sentence-1)
It can be called in any of these ways:point(1,2); point(1); point();
The last two calls are equivalent topoint(1,4) andpoint(3,4),
respectively[.](#2.sentence-3)
— *end example*]
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L4294)
A default argument shall be specified only in the[*parameter-declaration-clause*](dcl.fct#nt:parameter-declaration-clause "9.3.4.6Functions[dcl.fct]") of a function declaration
or [*lambda-declarator*](expr.prim.lambda.general#nt:lambda-declarator "7.5.6.1General[expr.prim.lambda.general]") or in a[*template-parameter*](temp.param#nt:template-parameter "13.2Template parameters[temp.param]") ([[temp.param]](temp.param "13.2Template parameters"))[.](#3.sentence-1)
A default argument shall not be specified for
a template parameter pack or
a function parameter pack[.](#3.sentence-2)
If it is specified in a[*parameter-declaration-clause*](dcl.fct#nt:parameter-declaration-clause "9.3.4.6Functions[dcl.fct]"),
it shall not occur within a[*declarator*](dcl.decl.general#nt:declarator "9.3.1General[dcl.decl.general]") or[*abstract-declarator*](dcl.name#nt:abstract-declarator "9.3.2Type names[dcl.name]") of a[*parameter-declaration*](dcl.fct#nt:parameter-declaration "9.3.4.6Functions[dcl.fct]")[.](#3.sentence-3)[77](#footnote-77 "This means that default arguments cannot appear, for example, in declarations of pointers to functions, references to functions, or typedef declarations.")
[4](#4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L4321)
For non-template functions, default arguments can be added in later
declarations of a
function that have the same host scope[.](#4.sentence-1)
Declarations that have different
host scopes have completely distinct sets of default arguments[.](#4.sentence-2)
That
is, declarations in inner scopes do not acquire default
arguments from declarations in outer scopes, and vice versa[.](#4.sentence-3)
In
a given function declaration, each parameter subsequent to a
parameter with a default argument shall have a default argument
supplied in this or a previous declaration,
unless the parameter was expanded from a parameter pack,
or shall be a function parameter pack[.](#4.sentence-4)
[*Note [2](#note-2)*:
A default argument
cannot be redefined by a later declaration
(not even to the same value) ([[basic.def.odr]](basic.def.odr "6.3One-definition rule"))[.](#4.sentence-5)
— *end note*]
[*Example [2](#example-2)*: void g(int = 0, ...); // OK, ellipsis is not a parameter so it can follow// a parameter with a default argumentvoid f(int, int);void f(int, int = 7);void h() { f(3); // OK, calls f(3, 7)void f(int = 1, int); // error: does not use default from surrounding scope}void m() {void f(int, int); // has no defaults f(4); // error: wrong number of argumentsvoid f(int, int = 5); // OK f(4); // OK, calls f(4, 5);void f(int, int = 5); // error: cannot redefine, even to same value}void n() { f(6); // OK, calls f(6, 7)}template<class ... T> struct C {void f(int n = 0, T...);};
C<int> c; // OK, instantiates declaration void C::f(int n = 0, int) — *end example*]
For a given inline function defined in different translation units,
the accumulated sets of default arguments at the end of the
translation units shall be the same; no diagnostic is required[.](#4.sentence-6)
If a friend declaration D specifies a default argument expression,
that declaration shall be a definition and there shall be no other
declaration of the function or function template
which is reachable from D or from which D is reachable[.](#4.sentence-7)
[5](#5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L4375)
The default argument has the
same semantic constraints as the initializer in a
declaration of a variable of the parameter type, using the
copy-initialization semantics ([[dcl.init]](dcl.init "9.5Initializers"))[.](#5.sentence-1)
The names in the
default argument are looked up, and the semantic constraints are checked,
at the point where the default argument appears, except that
an immediate invocation ([[expr.const]](expr.const "7.7Constant expressions")) that
is a potentially-evaluated subexpression ([[intro.execution]](intro.execution "6.10.1Sequential execution")) of
the [*initializer-clause*](dcl.init.general#nt:initializer-clause "9.5.1General[dcl.init.general]") in a [*parameter-declaration*](dcl.fct#nt:parameter-declaration "9.3.4.6Functions[dcl.fct]") is
neither evaluated
nor checked for whether it is a constant expression at that point[.](#5.sentence-2)
Name lookup and checking of semantic constraints for default
arguments of templated functions are performed as described in [[temp.inst]](temp.inst "13.9.2Implicit instantiation")[.](#5.sentence-3)
[*Example [3](#example-3)*:
In the following code,g will be called with the valuef(2):int a = 1;int f(int);int g(int x = f(a)); // default argument: f(::a)void h() { a = 2; {int a = 3;
g(); // g(f(::a))}}
— *end example*]
[*Note [3](#note-3)*:
A default argument is a complete-class context ([[class.mem]](class.mem "11.4Class members"))[.](#5.sentence-5)
Access checking applies to names in default arguments as
described in [[class.access]](class.access "11.8Member access control")[.](#5.sentence-6)
— *end note*]
[6](#6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L4419)
Except for member functions of templated classes, the
default arguments in a member function definition that appears
outside of the class definition
are added to the set of default arguments provided by the
member function declaration in the class definition;
the program is ill-formed if a default constructor ([[class.default.ctor]](class.default.ctor "11.4.5.2Default constructors")),
copy or move constructor ([[class.copy.ctor]](class.copy.ctor "11.4.5.3Copy/move constructors")), or
copy or move assignment operator ([[class.copy.assign]](class.copy.assign "11.4.6Copy/move assignment operator"))
is so declared[.](#6.sentence-1)
Default arguments for a member function of a templated class
shall be specified on the initial declaration of the member
function within the templated class[.](#6.sentence-2)
[*Example [4](#example-4)*: class C {void f(int i = 3); void g(int i, int j = 99);};
void C::f(int i = 3) {} // error: default argument already specified in class scopevoid C::g(int i = 88, int j) {} // in this translation unit, C::g can be called with no arguments — *end example*]
[7](#7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L4444)
[*Note [4](#note-4)*:
A local variable cannot be odr-used ([[basic.def.odr]](basic.def.odr#term.odr.use "6.3One-definition rule"))
in a default argument[.](#7.sentence-1)
— *end note*]
[*Example [5](#example-5)*: void f() {int i; extern void g(int x = i); // errorextern void h(int x = sizeof(i)); // OK// ...} — *end example*]
[8](#8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L4460)
[*Note [5](#note-5)*:
The keywordthis cannot appear in a default argument of a member function;
see [[expr.prim.this]](expr.prim.this "7.5.3This")[.](#8.sentence-1)
[*Example [6](#example-6)*: class A {void f(A* p = this) { } // error}; — *end example*]
— *end note*]
[9](#9)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L4475)
A default argument is evaluated each time the function is called
with no argument for the corresponding parameter[.](#9.sentence-1)
A parameter shall not appear as a potentially-evaluated expression
in a default argument[.](#9.sentence-2)
[*Note [6](#note-6)*:
Parameters of a function declared before a default argument
are in scope and can hide namespace and class member names[.](#9.sentence-3)
— *end note*]
[*Example [7](#example-7)*: int a;int f(int a, int b = a); // error: parameter a used as default argumenttypedef int I;int g(float I, int b = I(2)); // error: parameter I foundint h(int a, int b = sizeof(a)); // OK, [unevaluated operand](expr.context#def:unevaluated_operand "7.2.3Context dependence[expr.context]") — *end example*]
A non-static member shall not be designated in a default argument unless
- [(9.1)](#9.1)
it is designated by
the [*id-expression*](expr.prim.id.general#nt:id-expression "7.5.5.1General[expr.prim.id.general]") or [*splice-expression*](expr.prim.splice#nt:splice-expression "7.5.9Expression splicing[expr.prim.splice]") of a class member access expression ([[expr.ref]](expr.ref "7.6.1.5Class member access")),
- [(9.2)](#9.2)
it is designated by an expression
used to form a pointer to member ([[expr.unary.op]](expr.unary.op "7.6.2.2Unary operators")), or
- [(9.3)](#9.3)
it appears as the operand of
a [*reflect-expression*](expr.reflect#nt:reflect-expression "7.6.2.10The reflection operator[expr.reflect]") ([[expr.reflect]](expr.reflect "7.6.2.10The reflection operator"))[.](#9.sentence-4)
[*Example [8](#example-8)*:
The declaration ofX::mem1() in the following example is ill-formed because no object is supplied for the
non-static memberX::a used as an initializer[.](#9.sentence-5)
int b;class X {int a; int mem1(int i = a); // error: non-static member a used as default argumentint mem2(int i = b); // OK, use X::bconsteval void mem3(std::meta::info r = ^^a) {} // OKint mem4(int i = [:^^a:]); // error: non-static member a designated in default argumentstatic int b;};
The declaration ofX::mem2() is meaningful, however, since no object is needed to access the static memberX::b[.](#9.sentence-6)
Classes, objects, and members are described in [[class]](class "11Classes")[.](#9.sentence-7)
— *end example*]
A default argument is not part of the
type of a function[.](#9.sentence-8)
[*Example [9](#example-9)*: int f(int = 0);
void h() {int j = f(1); int k = f(); // OK, means f(0)}int (*p1)(int) = &f;int (*p2)() = &f; // error: type mismatch — *end example*]
[*Note [7](#note-7)*:
When an overload set contains a declaration of a function
whose host scope is S,
any default argument associated with any reachable declaration
whose host scope is S is available to the call ([[over.match.viable]](over.match.viable "12.2.3Viable functions"))[.](#9.sentence-9)
— *end note*]
[*Note [8](#note-8)*:
The candidate might have been found through a [*using-declarator*](namespace.udecl#nt:using-declarator "9.10The using declaration[namespace.udecl]") from which the declaration that provides the default argument is not reachable[.](#9.sentence-10)
— *end note*]
[10](#10)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L4560)
A virtual function call ([[class.virtual]](class.virtual "11.7.3Virtual functions")) uses the default
arguments in the declaration of the virtual function determined
by the static type of the pointer or reference denoting the
object[.](#10.sentence-1)
An overriding function in a derived class does not
acquire default arguments from the function it overrides[.](#10.sentence-2)
[*Example [10](#example-10)*: struct A {virtual void f(int a = 7);};struct B : public A {void f(int a);};void m() { B* pb = new B;
A* pa = pb;
pa->f(); // OK, calls pa->B::f(7) pb->f(); // error: wrong number of arguments for B::f()} — *end example*]
[77)](#footnote-77)[77)](#footnoteref-77)
This means that default
arguments cannot appear,
for example, in declarations of pointers to functions,
references to functions, ortypedef declarations[.](#footnote-77.sentence-1)

61
cppdraft/dcl/fct/spec.md Normal file
View File

@@ -0,0 +1,61 @@
[dcl.fct.spec]
# 9 Declarations [[dcl]](./#dcl)
## 9.2 Specifiers [[dcl.spec]](dcl.spec#dcl.fct.spec)
### 9.2.3 Function specifiers [dcl.fct.spec]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L689)
A[*function-specifier*](#nt:function-specifier "9.2.3Function specifiers[dcl.fct.spec]") can be used only in a function declaration[.](#1.sentence-1)
At most one [*explicit-specifier*](#nt:explicit-specifier "9.2.3Function specifiers[dcl.fct.spec]") and
at most one virtual keyword shall appear in
a [*decl-specifier-seq*](dcl.spec.general#nt:decl-specifier-seq "9.2.1General[dcl.spec.general]")[.](#1.sentence-2)
[function-specifier:](#nt:function-specifier "9.2.3Function specifiers[dcl.fct.spec]")
virtual
[*explicit-specifier*](#nt:explicit-specifier "9.2.3Function specifiers[dcl.fct.spec]")
[explicit-specifier:](#nt:explicit-specifier "9.2.3Function specifiers[dcl.fct.spec]")
explicit ( [*constant-expression*](expr.const#nt:constant-expression "7.7Constant expressions[expr.const]") )
explicit
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L709)
The virtual specifier shall be used only in the initial
declaration of a non-static member function; see [[class.virtual]](class.virtual "11.7.3Virtual functions")[.](#2.sentence-1)
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L714)
An [*explicit-specifier*](#nt:explicit-specifier "9.2.3Function specifiers[dcl.fct.spec]") shall be used only in the declaration of
a constructor or conversion function within its class definition;
see [[class.conv.ctor]](class.conv.ctor "11.4.8.2Conversion by constructor") and [[class.conv.fct]](class.conv.fct "11.4.8.3Conversion functions")[.](#3.sentence-1)
[4](#4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L720)
In an [*explicit-specifier*](#nt:explicit-specifier "9.2.3Function specifiers[dcl.fct.spec]"),
the [*constant-expression*](expr.const#nt:constant-expression "7.7Constant expressions[expr.const]"), if supplied, shall be a
contextually converted constant expression of type bool ([[expr.const]](expr.const "7.7Constant expressions"))[.](#4.sentence-1)
The [*explicit-specifier*](#nt:explicit-specifier "9.2.3Function specifiers[dcl.fct.spec]") explicit without a [*constant-expression*](expr.const#nt:constant-expression "7.7Constant expressions[expr.const]") is equivalent to
the [*explicit-specifier*](#nt:explicit-specifier "9.2.3Function specifiers[dcl.fct.spec]") explicit(true)[.](#4.sentence-2)
If the constant expression evaluates to true,
the function is explicit[.](#4.sentence-3)
Otherwise, the function is not explicit[.](#4.sentence-4)
A ( token that follows explicit is parsed as
part of the [*explicit-specifier*](#nt:explicit-specifier "9.2.3Function specifiers[dcl.fct.spec]")[.](#4.sentence-5)
[*Example [1](#example-1)*: struct S {explicit(sizeof(char[2])) S(char); // error: narrowing conversion of value 2 to type boolexplicit(sizeof(char)) S(bool); // OK, conversion of value 1 to type bool is non-narrowing}; — *end example*]

14
cppdraft/dcl/friend.md Normal file
View File

@@ -0,0 +1,14 @@
[dcl.friend]
# 9 Declarations [[dcl]](./#dcl)
## 9.2 Specifiers [[dcl.spec]](dcl.spec#dcl.friend)
### 9.2.5 The friend specifier [dcl.friend]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L879)
The friend specifier is used to specify access to class members;
see [[class.friend]](class.friend "11.8.4Friends")[.](#1.sentence-1)

1693
cppdraft/dcl/init.md Normal file

File diff suppressed because it is too large Load Diff

503
cppdraft/dcl/init/aggr.md Normal file
View File

@@ -0,0 +1,503 @@
[dcl.init.aggr]
# 9 Declarations [[dcl]](./#dcl)
## 9.5 Initializers [[dcl.init]](dcl.init#aggr)
### 9.5.2 Aggregates [dcl.init.aggr]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L5475)
An [*aggregate*](#def:aggregate "9.5.2Aggregates[dcl.init.aggr]") is an array or a class ([[class]](class "11Classes")) with
- [(1.1)](#1.1)
no user-declared or inherited constructors ([[class.ctor]](class.ctor "11.4.5Constructors")),
- [(1.2)](#1.2)
no private or protected direct non-static data members ([[class.access]](class.access "11.8Member access control")),
- [(1.3)](#1.3)
no private or protected direct base classes ([[class.access.base]](class.access.base "11.8.3Accessibility of base classes and base class members")), and
- [(1.4)](#1.4)
no virtual functions ([[class.virtual]](class.virtual "11.7.3Virtual functions")) or virtual base classes ([[class.mi]](class.mi "11.7.2Multiple base classes"))[.](#1.sentence-1)
[*Note [1](#note-1)*:
Aggregate initialization does not allow accessing
protected and private base class' members or constructors[.](#1.sentence-2)
— *end note*]
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L5492)
The [*elements*](#def:aggregate,elements "9.5.2Aggregates[dcl.init.aggr]") of an aggregate are:
- [(2.1)](#2.1)
for an array, the array elements in increasing subscript order, or
- [(2.2)](#2.2)
for a class, the direct base classes in declaration order,
followed by the direct non-static data members ([[class.mem]](class.mem "11.4Class members"))
that are not members of an anonymous union, in declaration order[.](#2.sentence-1)
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L5503)
When an aggregate is initialized by an initializer list
as specified in [[dcl.init.list]](dcl.init.list "9.5.5List-initialization"),
the elements of the initializer list are taken as initializers
for the elements of the aggregate[.](#3.sentence-1)
The [*explicitly initialized elements*](#def:explicitly_initialized_elements,aggregate "9.5.2Aggregates[dcl.init.aggr]") of the aggregate are determined as follows:
- [(3.1)](#3.1)
If the initializer list is
a brace-enclosed [*designated-initializer-list*](dcl.init.general#nt:designated-initializer-list "9.5.1General[dcl.init.general]"),
the aggregate shall be of class type,
the [*identifier*](lex.name#nt:identifier "5.11Identifiers[lex.name]") in each [*designator*](dcl.init.general#nt:designator "9.5.1General[dcl.init.general]") shall name a direct non-static data member of the class, and
the explicitly initialized elements of the aggregate
are the elements that are, or contain, those members[.](#3.1.sentence-1)
- [(3.2)](#3.2)
If the initializer list is a brace-enclosed [*initializer-list*](dcl.init.general#nt:initializer-list "9.5.1General[dcl.init.general]"),
the explicitly initialized elements of the aggregate
are those for which an element of the initializer list
appertains to the aggregate element or to a subobject thereof (see below)[.](#3.2.sentence-1)
- [(3.3)](#3.3)
Otherwise, the initializer list must be {},
and there are no explicitly initialized elements[.](#3.3.sentence-1)
[4](#4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L5529)
For each explicitly initialized element:
- [(4.1)](#4.1)
If the element is an anonymous union member and
the initializer list is
a brace-enclosed [*designated-initializer-list*](dcl.init.general#nt:designated-initializer-list "9.5.1General[dcl.init.general]"),
the element is initialized by the[*braced-init-list*](dcl.init.general#nt:braced-init-list "9.5.1General[dcl.init.general]") { *D* },
where *D* is the [*designated-initializer-clause*](dcl.init.general#nt:designated-initializer-clause "9.5.1General[dcl.init.general]") naming a member of the anonymous union member[.](#4.1.sentence-1)
There shall be only one such [*designated-initializer-clause*](dcl.init.general#nt:designated-initializer-clause "9.5.1General[dcl.init.general]")[.](#4.1.sentence-2)
[*Example [1](#example-1)*:
struct C {union {int a; const char* p; }; int x;} c = { .a = 1, .x = 3 }; initializes c.a with 1 and c.x with 3[.](#4.1.sentence-3)
— *end example*]
- [(4.2)](#4.2)
Otherwise, if the initializer list is
a brace-enclosed [*designated-initializer-list*](dcl.init.general#nt:designated-initializer-list "9.5.1General[dcl.init.general]"),
the element is initialized with the [*brace-or-equal-initializer*](dcl.init.general#nt:brace-or-equal-initializer "9.5.1General[dcl.init.general]") of the corresponding [*designated-initializer-clause*](dcl.init.general#nt:designated-initializer-clause "9.5.1General[dcl.init.general]")[.](#4.2.sentence-1)
If that initializer is of the form= [*assignment-expression*](expr.assign#nt:assignment-expression "7.6.19Assignment and compound assignment operators[expr.assign]") and
a narrowing conversion ([[dcl.init.list]](dcl.init.list "9.5.5List-initialization")) is required
to convert the expression, the program is ill-formed[.](#4.2.sentence-2)
[*Note [2](#note-2)*:
The form of the initializer determines
whether copy-initialization or direct-initialization is performed[.](#4.2.sentence-3)
— *end note*]
- [(4.3)](#4.3)
Otherwise,
the initializer list is a brace-enclosed [*initializer-list*](dcl.init.general#nt:initializer-list "9.5.1General[dcl.init.general]")[.](#4.3.sentence-1)
If an [*initializer-clause*](dcl.init.general#nt:initializer-clause "9.5.1General[dcl.init.general]") appertains to the aggregate element,
then the aggregate element is copy-initialized from the [*initializer-clause*](dcl.init.general#nt:initializer-clause "9.5.1General[dcl.init.general]")[.](#4.3.sentence-2)
Otherwise,
the aggregate element is copy-initialized
from a brace-enclosed [*initializer-list*](dcl.init.general#nt:initializer-list "9.5.1General[dcl.init.general]") consisting of all of the [*initializer-clause*](dcl.init.general#nt:initializer-clause "9.5.1General[dcl.init.general]")*s* that appertain to subobjects of the aggregate element,
in the order of appearance[.](#4.3.sentence-3)
[*Note [3](#note-3)*:
If an initializer is itself an initializer list,
the element is list-initialized, which will result in a recursive application
of the rules in this subclause if the element is an aggregate[.](#4.3.sentence-4)
— *end note*]
[*Example [2](#example-2)*:
struct A {int x; struct B {int i; int j; } b;} a = { 1, { 2, 3 } }; initializesa.x with 1,a.b.i with 2,a.b.j with 3[.](#4.3.sentence-5)
struct base1 { int b1, b2 = 42; };struct base2 { base2() { b3 = 42; }int b3;};struct derived : base1, base2 {int d;};
derived d1{{1, 2}, {}, 4};
derived d2{{}, {}, 4}; initializesd1.b1 with 1,d1.b2 with 2,d1.b3 with 42,d1.d with 4, andd2.b1 with 0,d2.b2 with 42,d2.b3 with 42,d2.d with 4[.](#4.3.sentence-6)
— *end example*]
[5](#5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L5628)
For a non-union aggregate,
each element that is not an explicitly initialized element
is initialized as follows:
- [(5.1)](#5.1)
If the element has a default member initializer ([[class.mem]](class.mem "11.4Class members")),
the element is initialized from that initializer[.](#5.1.sentence-1)
- [(5.2)](#5.2)
Otherwise, if the element is not a reference, the element
is copy-initialized from an empty initializer list ([[dcl.init.list]](dcl.init.list "9.5.5List-initialization"))[.](#5.2.sentence-1)
- [(5.3)](#5.3)
Otherwise, the program is ill-formed[.](#5.3.sentence-1)
If the aggregate is a union and the initializer list is empty, then
- [(5.4)](#5.4)
if any variant member has a default member initializer,
that member is initialized from its default member initializer;
- [(5.5)](#5.5)
otherwise, the first member of the union (if any)
is copy-initialized from an empty initializer list[.](#5.sentence-2)
[6](#6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L5652)
[*Example [3](#example-3)*:
struct S { int a; const char* b; int c; int d = b[a]; };
S ss = { 1, "asdf" }; initializesss.a with 1,ss.b with "asdf",ss.c with the value of an expression of the formint{} (that is, 0), and ss.d with the value of ss.b[ss.a] (that is, 's')[.](#6.sentence-1)
struct A { string a; int b = 42; int c = -1;};
A{.c=21} has the following steps:
- [(6.1)](#6.1)
Initialize a with {}
- [(6.2)](#6.2)
Initialize b with = 42
- [(6.3)](#6.3)
Initialize c with = 21
— *end example*]
[7](#7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L5685)
The initializations of the elements of the aggregate
are evaluated in the element order[.](#7.sentence-1)
That is,
all value computations and side effects associated with a given element
are sequenced before
those of any element that follows it in order[.](#7.sentence-2)
[8](#8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L5693)
An aggregate that is a class can also be initialized with a single
expression not enclosed in braces, as described in [[dcl.init]](dcl.init "9.5Initializers")[.](#8.sentence-1)
[9](#9)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L5697)
The destructor for each element of class type
other than an anonymous union member
is potentially invoked ([[class.dtor]](class.dtor "11.4.7Destructors"))
from the context where the aggregate initialization occurs[.](#9.sentence-1)
[*Note [4](#note-4)*:
This provision ensures that destructors can be called
for fully-constructed subobjects
in case an exception is thrown ([[except.ctor]](except.ctor "14.3Stack unwinding"))[.](#9.sentence-2)
— *end note*]
[10](#10)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L5708)
The number of elements ([[dcl.array]](dcl.array "9.3.4.5Arrays")) in an array of unknown bound
initialized with a brace-enclosed [*initializer-list*](dcl.init.general#nt:initializer-list "9.5.1General[dcl.init.general]") is the number of explicitly initialized elements of the array[.](#10.sentence-1)
[*Example [4](#example-4)*:
int x[] = { 1, 3, 5 }; declares and initializesx as a one-dimensional array that has three elements
since no size was specified and there are three initializers[.](#10.sentence-2)
— *end example*]
[*Example [5](#example-5)*:
Instruct X { int i, j, k; };
X a[] = { 1, 2, 3, 4, 5, 6 };
X b[2] = { { 1, 2, 3 }, { 4, 5, 6 } };a and b have the same value[.](#10.sentence-3)
— *end example*]
An array of unknown bound shall not be initialized with
an empty [*braced-init-list*](dcl.init.general#nt:braced-init-list "9.5.1General[dcl.init.general]") {}[.](#10.sentence-4)[79](#footnote-79 "The syntax provides for empty braced-init-lists, but nonetheless C++ does not have zero length arrays.")
[*Note [5](#note-5)*:
A default member initializer does not determine the bound for a member
array of unknown bound[.](#10.sentence-5)
Since the default member initializer is
ignored if a suitable [*mem-initializer*](class.base.init#nt:mem-initializer "11.9.3Initializing bases and members[class.base.init]") is present ([[class.base.init]](class.base.init "11.9.3Initializing bases and members")),
the default member initializer is not
considered to initialize the array of unknown bound[.](#10.sentence-6)
[*Example [6](#example-6)*: struct S {int y[] = { 0 }; // error: non-static data member of incomplete type}; — *end example*]
— *end note*]
[11](#11)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L5751)
[*Note [6](#note-6)*:
Static data members,
non-static data members of anonymous union members,
and
unnamed bit-fields
are not considered elements of the aggregate[.](#11.sentence-1)
[*Example [7](#example-7)*: struct A {int i; static int s; int j; int :17; int k;} a = { 1, 2, 3 };
Here, the second initializer 2 initializesa.j and not the static data memberA::s, and the third initializer 3 initializes a.k and not the unnamed bit-field before it[.](#11.sentence-2)
— *end example*]
— *end note*]
[12](#12)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L5777)
If a member has a default member initializer
and a potentially-evaluated subexpression thereof is an aggregate
initialization that would use that default member initializer,
the program is ill-formed[.](#12.sentence-1)
[*Example [8](#example-8)*: struct A;extern A a;struct A {const A& a1 { A{a,a} }; // OKconst A& a2 { A{} }; // error};
A a{a,a}; // OKstruct B {int n = B{}.n; // error}; — *end example*]
[13](#13)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L5798)
When initializing a multidimensional array,
the[*initializer-clause*](dcl.init.general#nt:initializer-clause "9.5.1General[dcl.init.general]")*s* initialize the elements with the last (rightmost) index of the array
varying the fastest ([[dcl.array]](dcl.array "9.3.4.5Arrays"))[.](#13.sentence-1)
[*Example [9](#example-9)*:
int x[2][2] = { 3, 1, 4, 2 }; initializesx[0][0] to3,x[0][1] to1,x[1][0] to4,
andx[1][1] to2[.](#13.sentence-2)
On the other hand,float y[4][3] = {{ 1 }, { 2 }, { 3 }, { 4 }}; initializes the first column ofy (regarded as a two-dimensional array)
and leaves the rest zero[.](#13.sentence-3)
— *end example*]
[14](#14)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L5834)
Each [*initializer-clause*](dcl.init.general#nt:initializer-clause "9.5.1General[dcl.init.general]") in
a brace-enclosed [*initializer-list*](dcl.init.general#nt:initializer-list "9.5.1General[dcl.init.general]") is said to [*appertain*](dcl.attr.grammar#def:appertain "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") to an element of the aggregate being initialized or
to an element of one of its subaggregates[.](#14.sentence-1)
Considering the sequence of [*initializer-clause*](dcl.init.general#nt:initializer-clause "9.5.1General[dcl.init.general]")*s*,
and the sequence of aggregate elements
initially formed as the sequence of elements of the aggregate being initialized
and potentially modified as described below,
each [*initializer-clause*](dcl.init.general#nt:initializer-clause "9.5.1General[dcl.init.general]") appertains to
the corresponding aggregate element if
- [(14.1)](#14.1)
the aggregate element is not an aggregate, or
- [(14.2)](#14.2)
the [*initializer-clause*](dcl.init.general#nt:initializer-clause "9.5.1General[dcl.init.general]") begins with a left brace, or
- [(14.3)](#14.3)
the [*initializer-clause*](dcl.init.general#nt:initializer-clause "9.5.1General[dcl.init.general]") is an expression and
an implicit conversion sequence can be formed
that converts the expression to the type of the aggregate element, or
- [(14.4)](#14.4)
the aggregate element is an aggregate that itself has no aggregate elements[.](#14.sentence-2)
Otherwise,
the aggregate element is an aggregate and
that subaggregate is replaced in the list of aggregate elements by
the sequence of its own aggregate elements, and
the appertainment analysis resumes with
the first such element and the same [*initializer-clause*](dcl.init.general#nt:initializer-clause "9.5.1General[dcl.init.general]")[.](#14.sentence-3)
[*Note [7](#note-7)*:
These rules apply recursively to the aggregate's subaggregates[.](#14.sentence-4)
[*Example [10](#example-10)*:
Instruct S1 { int a, b; };struct S2 { S1 s, t; };
S2 x[2] = { 1, 2, 3, 4, 5, 6, 7, 8 };
S2 y[2] = {{{ 1, 2 }, { 3, 4 }}, {{ 5, 6 }, { 7, 8 }}};x and y have the same value[.](#14.sentence-5)
— *end example*]
— *end note*]
This process continues
until all [*initializer-clause*](dcl.init.general#nt:initializer-clause "9.5.1General[dcl.init.general]")*s* have been exhausted[.](#14.sentence-6)
If any [*initializer-clause*](dcl.init.general#nt:initializer-clause "9.5.1General[dcl.init.general]") remains
that does not appertain to
an element of the aggregate or one of its subaggregates,
the program is ill-formed[.](#14.sentence-7)
[*Example [11](#example-11)*: char cv[4] = { 'a', 's', 'd', 'f', 0 }; // error: too many initializers — *end example*]
[15](#15)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L5899)
[*Example [12](#example-12)*:
float y[4][3] = {{ 1, 3, 5 }, { 2, 4, 6 }, { 3, 5, 7 },}; is a completely-braced initialization:
1, 3, and 5 initialize the first row of the arrayy[0],
namelyy[0][0],y[0][1],
andy[0][2][.](#15.sentence-1)
Likewise the next two lines initializey[1] andy[2][.](#15.sentence-2)
The initializer ends early and thereforey[3]'s
elements are initialized as if explicitly initialized with an
expression of the formfloat(),
that is, are initialized with0.0[.](#15.sentence-3)
In the following example, braces in the[*initializer-list*](dcl.init.general#nt:initializer-list "9.5.1General[dcl.init.general]") are elided;
however the[*initializer-list*](dcl.init.general#nt:initializer-list "9.5.1General[dcl.init.general]") has the same effect as the completely-braced[*initializer-list*](dcl.init.general#nt:initializer-list "9.5.1General[dcl.init.general]") of the above example,float y[4][3] = {1, 3, 5, 2, 4, 6, 3, 5, 7};
The initializer fory begins with a left brace, but the one fory[0] does not,
therefore three elements from the list are used[.](#15.sentence-5)
Likewise the next three are taken successively fory[1] andy[2][.](#15.sentence-6)
— *end example*]
[16](#16)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L5953)
[*Note [8](#note-8)*:
The initializer for an empty subaggregate is needed
if any initializers are provided for subsequent elements[.](#16.sentence-1)
[*Example [13](#example-13)*: struct S { } s;struct A { S s1; int i1;
S s2; int i2;
S s3; int i3;} a = {{ }, // Required initialization0,
s, // Required initialization0}; // Initialization not required for A::s3 because A::i3 is also not initialized — *end example*]
— *end note*]
[17](#17)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L5977)
[*Example [14](#example-14)*: struct A {int i; operator int();};struct B { A a1, a2; int z;};
A a;
B b = { 4, a, a };
Braces are elided around the[*initializer-clause*](dcl.init.general#nt:initializer-clause "9.5.1General[dcl.init.general]") forb.a1.i[.](#17.sentence-1)
b.a1.i is initialized with 4,b.a2 is initialized witha,b.z is initialized with whatevera.operator int() returns[.](#17.sentence-2)
— *end example*]
[18](#18)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L6006)
[*Note [9](#note-9)*:
An aggregate array or an aggregate class can contain elements of a
class type with a user-declared constructor ([[class.ctor]](class.ctor "11.4.5Constructors"))[.](#18.sentence-1)
Initialization of these aggregate objects is described in [[class.expl.init]](class.expl.init "11.9.2Explicit initialization")[.](#18.sentence-2)
— *end note*]
[19](#19)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L6014)
[*Note [10](#note-10)*:
Whether the initialization of aggregates with static storage duration
is static or dynamic is specified
in [[basic.start.static]](basic.start.static "6.10.3.2Static initialization"), [[basic.start.dynamic]](basic.start.dynamic "6.10.3.3Dynamic initialization of non-block variables"), and [[stmt.dcl]](stmt.dcl "8.10Declaration statement")[.](#19.sentence-1)
— *end note*]
[20](#20)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L6021)
When a union is initialized with an initializer list,
there shall not be more than one
explicitly initialized element[.](#20.sentence-1)
[*Example [15](#example-15)*: union u { int a; const char* b; };
u a = { 1 };
u b = a;
u c = 1; // error u d = { 0, "asdf" }; // error u e = { "asdf" }; // error u f = { .b = "asdf" };
u g = { .a = 1, .b = "asdf" }; // error — *end example*]
[21](#21)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L6039)
[*Note [11](#note-11)*:
As described above,
the braces around the[*initializer-clause*](dcl.init.general#nt:initializer-clause "9.5.1General[dcl.init.general]") for a union member can be omitted if the
union is a member of another aggregate[.](#21.sentence-1)
— *end note*]
[79)](#footnote-79)[79)](#footnoteref-79)
The syntax provides for empty [*braced-init-list*](dcl.init.general#nt:braced-init-list "9.5.1General[dcl.init.general]")*s*,
but nonetheless C++ does not have zero length arrays[.](#footnote-79.sentence-1)

View File

@@ -0,0 +1,593 @@
[dcl.init.general]
# 9 Declarations [[dcl]](./#dcl)
## 9.5 Initializers [[dcl.init]](dcl.init#general)
### 9.5.1 General [dcl.init.general]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L4912)
The process of initialization described in [[dcl.init]](dcl.init "9.5Initializers") applies to
all initializations regardless of syntactic context, including the
initialization of a function parameter ([[expr.call]](expr.call "7.6.1.3Function call")), the
initialization of a return value ([[stmt.return]](stmt.return "8.8.4The return statement")), or when an
initializer follows a declarator[.](#1.sentence-1)
[initializer:](#nt:initializer "9.5.1General[dcl.init.general]")
[*brace-or-equal-initializer*](#nt:brace-or-equal-initializer "9.5.1General[dcl.init.general]")
( [*expression-list*](expr.post.general#nt:expression-list "7.6.1.1General[expr.post.general]") )
[brace-or-equal-initializer:](#nt:brace-or-equal-initializer "9.5.1General[dcl.init.general]")
= [*initializer-clause*](#nt:initializer-clause "9.5.1General[dcl.init.general]")
[*braced-init-list*](#nt:braced-init-list "9.5.1General[dcl.init.general]")
[initializer-clause:](#nt:initializer-clause "9.5.1General[dcl.init.general]")
[*assignment-expression*](expr.assign#nt:assignment-expression "7.6.19Assignment and compound assignment operators[expr.assign]")
[*braced-init-list*](#nt:braced-init-list "9.5.1General[dcl.init.general]")
[braced-init-list:](#nt:braced-init-list "9.5.1General[dcl.init.general]")
{ [*initializer-list*](#nt:initializer-list "9.5.1General[dcl.init.general]") ,opt }
{ [*designated-initializer-list*](#nt:designated-initializer-list "9.5.1General[dcl.init.general]") ,opt }
{ }
[initializer-list:](#nt:initializer-list "9.5.1General[dcl.init.general]")
[*initializer-clause*](#nt:initializer-clause "9.5.1General[dcl.init.general]") ...opt
[*initializer-list*](#nt:initializer-list "9.5.1General[dcl.init.general]") , [*initializer-clause*](#nt:initializer-clause "9.5.1General[dcl.init.general]") ...opt
[designated-initializer-list:](#nt:designated-initializer-list "9.5.1General[dcl.init.general]")
[*designated-initializer-clause*](#nt:designated-initializer-clause "9.5.1General[dcl.init.general]")
[*designated-initializer-list*](#nt:designated-initializer-list "9.5.1General[dcl.init.general]") , [*designated-initializer-clause*](#nt:designated-initializer-clause "9.5.1General[dcl.init.general]")
[designated-initializer-clause:](#nt:designated-initializer-clause "9.5.1General[dcl.init.general]")
[*designator*](#nt:designator "9.5.1General[dcl.init.general]") [*brace-or-equal-initializer*](#nt:brace-or-equal-initializer "9.5.1General[dcl.init.general]")
[designator:](#nt:designator "9.5.1General[dcl.init.general]")
. [*identifier*](lex.name#nt:identifier "5.11Identifiers[lex.name]")
[expr-or-braced-init-list:](#nt:expr-or-braced-init-list "9.5.1General[dcl.init.general]")
[*expression*](expr.comma#nt:expression "7.6.20Comma operator[expr.comma]")
[*braced-init-list*](#nt:braced-init-list "9.5.1General[dcl.init.general]")
[*Note [1](#note-1)*:
The rules in [[dcl.init]](dcl.init "9.5Initializers") apply even if the grammar permits only
the [*brace-or-equal-initializer*](#nt:brace-or-equal-initializer "9.5.1General[dcl.init.general]") form
of [*initializer*](#nt:initializer "9.5.1General[dcl.init.general]") in a given context[.](#1.sentence-2)
— *end note*]
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L4978)
Except for objects declared with the constexpr specifier, for which see [[dcl.constexpr]](dcl.constexpr "9.2.6The constexpr and consteval specifiers"),
an [*initializer*](#nt:initializer "9.5.1General[dcl.init.general]") in the definition of a variable can consist of
arbitrary expressions involving literals and previously declared
variables and functions,
regardless of the variable's storage duration[.](#2.sentence-1)
[*Example [1](#example-1)*: int f(int);int a = 2;int b = f(a);int c(b); — *end example*]
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L4993)
[*Note [2](#note-2)*:
Default arguments are more restricted; see [[dcl.fct.default]](dcl.fct.default "9.3.4.7Default arguments")[.](#3.sentence-1)
— *end note*]
[4](#4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L4998)
[*Note [3](#note-3)*:
The order of initialization of variables with static storage duration is described in [[basic.start]](basic.start "6.10.3Start and termination") and [[stmt.dcl]](stmt.dcl "8.10Declaration statement")[.](#4.sentence-1)
— *end note*]
[5](#5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L5004)
A declaration D of a variable with linkage
shall not have an [*initializer*](#nt:initializer "9.5.1General[dcl.init.general]") if D inhabits a block scope[.](#5.sentence-1)
[6](#6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L5009)
To [*zero-initialize*](#def:zero-initialization "9.5.1General[dcl.init.general]") an object or reference of type T means:
- [(6.1)](#6.1)
if T is std::meta::info,
the object is initialized to a null reflection value;
- [(6.2)](#6.2)
if T is any other scalar type ([[basic.types.general]](basic.types.general#term.scalar.type "6.9.1General")),
the object is initialized to the value
obtained by converting the integer literal 0 (zero) to T;[78](#footnote-78 "As specified in [conv.ptr], converting an integer literal whose value is 0 to a pointer type results in a null pointer value.")
- [(6.3)](#6.3)
ifT is a (possibly cv-qualified) non-union class type,
its padding bits ([[basic.types.general]](basic.types.general#term.padding.bits "6.9.1General")) are initialized to zero bits and
each non-static data member,
each non-virtual base class subobject, and,
if the object is not a base class subobject,
each virtual base class subobject
is zero-initialized;
- [(6.4)](#6.4)
ifT is a (possibly cv-qualified) union type,
its padding bits ([[basic.types.general]](basic.types.general#term.padding.bits "6.9.1General")) are initialized to zero bits and
the
object's first non-static named
data member
is zero-initialized;
- [(6.5)](#6.5)
ifT is an array type,
each element is zero-initialized;
- [(6.6)](#6.6)
ifT is a reference type, no initialization is performed[.](#6.sentence-1)
[7](#7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L5062)
To[*default-initialize*](#def:default-initialization "9.5.1General[dcl.init.general]") an object of typeT means:
- [(7.1)](#7.1)
IfT is a (possibly cv-qualified) class type ([[class]](class "11Classes")),
constructors are considered[.](#7.1.sentence-1)
The applicable constructors are
enumerated ([[over.match.ctor]](over.match.ctor "12.2.2.4Initialization by constructor")), and the best one for the[*initializer*](#nt:initializer "9.5.1General[dcl.init.general]") () is chosen through
overload resolution ([[over.match]](over.match "12.2Overload resolution"))[.](#7.1.sentence-2)
The constructor thus selected
is called, with an empty argument list, to initialize the object[.](#7.1.sentence-3)
- [(7.2)](#7.2)
IfT is an array type,
the semantic constraints of default-initializing a hypothetical element
shall be met and
each element is default-initialized[.](#7.2.sentence-1)
- [(7.3)](#7.3)
If T is std::meta::info, the object is zero-initialized[.](#7.3.sentence-1)
- [(7.4)](#7.4)
Otherwise,
no initialization is performed[.](#7.4.sentence-1)
[8](#8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L5095)
A class type T is [*const-default-constructible*](#def:const-default-constructible "9.5.1General[dcl.init.general]") if
default-initialization of T would invoke
a user-provided constructor of T (not inherited from a base class)
or if
- [(8.1)](#8.1)
each direct non-variant non-static data member M of T has a default member initializer
or, if M is of class type X (or array thereof),X is const-default-constructible,
- [(8.2)](#8.2)
if T is a union with at least one non-static data member,
exactly one variant member has a default member initializer,
- [(8.3)](#8.3)
if T is not a union,
for each anonymous union member with at least one non-static data member (if any),
exactly one non-static data member has a default member initializer, and
- [(8.4)](#8.4)
each potentially constructed base class of T is const-default-constructible[.](#8.sentence-1)
If a program calls for the default-initialization of an object of a
const-qualified type T,T shall be std::meta::
info or a const-default-constructible class type,
or array thereof[.](#8.sentence-2)
[9](#9)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L5123)
To[*value-initialize*](#def:value-initialization "9.5.1General[dcl.init.general]") an object of typeT means:
- [(9.1)](#9.1)
IfT is a (possibly cv-qualified) class type ([[class]](class "11Classes")), then
let C be the constructor selected to
default-initialize the object, if any[.](#9.1.sentence-1)
If C is not user-provided, the object is first zero-initialized[.](#9.1.sentence-2)
In all cases, the object is then default-initialized[.](#9.1.sentence-3)
- [(9.2)](#9.2)
IfT is an array type,
the semantic constraints of value-initializing a hypothetical element
shall be met and
each element is value-initialized[.](#9.2.sentence-1)
- [(9.3)](#9.3)
Otherwise, the object is zero-initialized[.](#9.3.sentence-1)
[10](#10)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L5152)
A program that calls for default-initialization
or value-initialization
of an entity
of reference type is ill-formed[.](#10.sentence-1)
[11](#11)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L5158)
[*Note [4](#note-4)*:
For every object with static storage duration,
static initialization ([[basic.start.static]](basic.start.static "6.10.3.2Static initialization")) is performed
at program startup before any other initialization takes place[.](#11.sentence-1)
In some cases, additional initialization is done later[.](#11.sentence-2)
— *end note*]
[12](#12)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L5166)
If no initializer is specified for an object, the object is default-initialized[.](#12.sentence-1)
[13](#13)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L5169)
If the entity being initialized does not have class or array type, the[*expression-list*](expr.post.general#nt:expression-list "7.6.1.1General[expr.post.general]") in a
parenthesized initializer shall be a single expression[.](#13.sentence-1)
[14](#14)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L5174)
The initialization that occurs in the = form of a[*brace-or-equal-initializer*](#nt:brace-or-equal-initializer "9.5.1General[dcl.init.general]") or[*condition*](stmt.pre#nt:condition "8.1Preamble[stmt.pre]") ([[stmt.select]](stmt.select "8.5Selection statements")),
as well as in argument passing, function return,
throwing an exception ([[except.throw]](except.throw "14.2Throwing an exception")),
handling an exception ([[except.handle]](except.handle "14.4Handling an exception")),
and aggregate member initialization other than by a[*designated-initializer-clause*](#nt:designated-initializer-clause "9.5.1General[dcl.init.general]") ([[dcl.init.aggr]](dcl.init.aggr "9.5.2Aggregates")),
is called[*copy-initialization*](#def:copy-initialization "9.5.1General[dcl.init.general]")[.](#14.sentence-1)
[*Note [5](#note-5)*:
Copy-initialization can invoke a move ([[class.copy.ctor]](class.copy.ctor "11.4.5.3Copy/move constructors"))[.](#14.sentence-2)
— *end note*]
[15](#15)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L5191)
The initialization that occurs
- [(15.1)](#15.1)
for an [*initializer*](#nt:initializer "9.5.1General[dcl.init.general]") that is a
parenthesized [*expression-list*](expr.post.general#nt:expression-list "7.6.1.1General[expr.post.general]") or a [*braced-init-list*](#nt:braced-init-list "9.5.1General[dcl.init.general]"),
- [(15.2)](#15.2)
for a [*new-initializer*](expr.new#nt:new-initializer "7.6.2.8New[expr.new]") ([[expr.new]](expr.new "7.6.2.8New")),
- [(15.3)](#15.3)
in a static_cast expression ([[expr.static.cast]](expr.static.cast "7.6.1.9Static cast")),
- [(15.4)](#15.4)
in a functional notation type conversion ([[expr.type.conv]](expr.type.conv "7.6.1.4Explicit type conversion (functional notation)")), and
- [(15.5)](#15.5)
in the [*braced-init-list*](#nt:braced-init-list "9.5.1General[dcl.init.general]") form of a [*condition*](stmt.pre#nt:condition "8.1Preamble[stmt.pre]")
is called[*direct-initialization*](#def:direct-initialization "9.5.1General[dcl.init.general]")[.](#15.sentence-1)
[16](#16)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L5204)
The semantics of initializers are as follows[.](#16.sentence-1)
The[*destination type*](#def:destination_type) is the cv-unqualified type of the object or reference being initialized and the[*source type*](#def:source_type) is the type of the initializer expression[.](#16.sentence-2)
If the initializer is not a single (possibly parenthesized) expression, the
source type is not defined[.](#16.sentence-3)
- [(16.1)](#16.1)
If the initializer is a (non-parenthesized) [*braced-init-list*](#nt:braced-init-list "9.5.1General[dcl.init.general]") or is = [*braced-init-list*](#nt:braced-init-list "9.5.1General[dcl.init.general]"), the object or reference
is list-initialized ([[dcl.init.list]](dcl.init.list "9.5.5List-initialization"))[.](#16.1.sentence-1)
- [(16.2)](#16.2)
If the destination type is a reference type, see [[dcl.init.ref]](dcl.init.ref "9.5.4References")[.](#16.2.sentence-1)
- [(16.3)](#16.3)
If the destination type is an array of characters,
an array of char8_t,
an array of char16_t,
an array of char32_t,
or an array ofwchar_t,
and the initializer is a [*string-literal*](lex.string#nt:string-literal "5.13.5String literals[lex.string]"), see [[dcl.init.string]](dcl.init.string "9.5.3Character arrays")[.](#16.3.sentence-1)
- [(16.4)](#16.4)
If the initializer is (), the object is value-initialized[.](#16.4.sentence-1)
[*Note [6](#note-6)*:
Since() is not permitted by the syntax for[*initializer*](#nt:initializer "9.5.1General[dcl.init.general]"),X a(); is not the declaration of an object of classX,
but the declaration of a function taking no arguments and returning anX[.](#16.4.sentence-2)
The form() can appear in certain other initialization contexts ([[expr.new]](expr.new "7.6.2.8New"), [[expr.type.conv]](expr.type.conv "7.6.1.4Explicit type conversion (functional notation)"), [[class.base.init]](class.base.init "11.9.3Initializing bases and members"))[.](#16.4.sentence-3)
— *end note*]
- [(16.5)](#16.5)
Otherwise, if the destination type is an array,
the object is initialized as follows[.](#16.5.sentence-1)
The [*initializer*](#nt:initializer "9.5.1General[dcl.init.general]") shall be of the form( [*expression-list*](expr.post.general#nt:expression-list "7.6.1.1General[expr.post.general]") )[.](#16.5.sentence-2)
Let x1, …, xk be
the elements of the [*expression-list*](expr.post.general#nt:expression-list "7.6.1.1General[expr.post.general]")[.](#16.5.sentence-3)
If the destination type is an array of unknown bound,
it is defined as having k elements[.](#16.5.sentence-4)
Let n denote the array size after this potential adjustment[.](#16.5.sentence-5)
If k is greater than n,
the program is ill-formed[.](#16.5.sentence-6)
Otherwise, the ith array element is copy-initialized withxi for each 1 ≤ i ≤ k, and
value-initialized for each k<‰¤n[.](#16.5.sentence-7)
For each ‰¤i<‰¤n,
every value computation and side effect associated with
the initialization of the ith element of the array
is sequenced before those associated with
the initialization of the jth element[.](#16.5.sentence-8)
- [(16.6)](#16.6)
Otherwise, if the destination type is a class type:
* [(16.6.1)](#16.6.1)
If the initializer expression is a prvalue
and the cv-unqualified version of the source type
is the same as the destination type,
the initializer expression is used to initialize the destination object[.](#16.6.1.sentence-1)
[*Example [2](#example-2)*:
T x = T(T(T())); value-initializes x[.](#16.6.1.sentence-2)
— *end example*]
* [(16.6.2)](#16.6.2)
Otherwise, if the initialization is direct-initialization,
or if it is copy-initialization where the cv-unqualified version of the source
type is the same as or is derived from the class of the destination type,
constructors are considered[.](#16.6.2.sentence-1)
The applicable constructors
are enumerated ([[over.match.ctor]](over.match.ctor "12.2.2.4Initialization by constructor")), and the best one is chosen
through overload resolution ([[over.match]](over.match "12.2Overload resolution"))[.](#16.6.2.sentence-2)
Then:
+
[(16.6.2.1)](#16.6.2.1)
If overload resolution is successful,
the selected constructor
is called to initialize the object, with the initializer
expression or [*expression-list*](expr.post.general#nt:expression-list "7.6.1.1General[expr.post.general]") as its argument(s)[.](#16.6.2.1.sentence-1)
+
[(16.6.2.2)](#16.6.2.2)
Otherwise, if no constructor is viable,
the destination type is
an aggregate class, and
the initializer is a parenthesized [*expression-list*](expr.post.general#nt:expression-list "7.6.1.1General[expr.post.general]"),
the object is initialized as follows[.](#16.6.2.2.sentence-1)
Let e1, …, en be the elements of the aggregate ([[dcl.init.aggr]](dcl.init.aggr "9.5.2Aggregates"))[.](#16.6.2.2.sentence-2)
Let x1, …, xk be the elements of the [*expression-list*](expr.post.general#nt:expression-list "7.6.1.1General[expr.post.general]")[.](#16.6.2.2.sentence-3)
If k is greater than n, the program is ill-formed[.](#16.6.2.2.sentence-4)
The element ei is copy-initialized withxi for 1 ≤ i ≤ k[.](#16.6.2.2.sentence-5)
The remaining elements are initialized with
their default member initializers, if any, and
otherwise are value-initialized[.](#16.6.2.2.sentence-6)
For each ‰¤i<‰¤n,
every value computation and side effect
associated with the initialization of ei is sequenced before those associated with the initialization of ej[.](#16.6.2.2.sentence-7)
[*Note [7](#note-7)*:
By contrast with direct-list-initialization,
narrowing conversions ([[dcl.init.list]](dcl.init.list "9.5.5List-initialization")) can appear,
designators are not permitted,
a temporary object bound to a reference
does not have its lifetime extended ([[class.temporary]](class.temporary "6.8.7Temporary objects")), and
there is no brace elision[.](#16.6.2.2.sentence-8)
[*Example [3](#example-3)*: struct A {int a; int&& r;};
int f();int n = 10;
A a1{1, f()}; // OK, lifetime is extended A a2(1, f()); // well-formed, but dangling reference A a3{1.0, 1}; // error: narrowing conversion A a4(1.0, 1); // well-formed, but dangling reference A a5(1.0, std::move(n)); // OK — *end example*]
— *end note*]
+
[(16.6.2.3)](#16.6.2.3)
Otherwise, the initialization is ill-formed[.](#16.6.2.3.sentence-1)
* [(16.6.3)](#16.6.3)
Otherwise (i.e., for the remaining copy-initialization cases),
user-defined conversions that can convert from the
source type to the destination type or (when a conversion function
is used) to a derived class thereof are enumerated as described in [[over.match.copy]](over.match.copy "12.2.2.5Copy-initialization of class by user-defined conversion"),
and the best one is chosen through overload resolution ([[over.match]](over.match "12.2Overload resolution"))[.](#16.6.3.sentence-1)
If the conversion cannot be done or
is ambiguous, the initialization is ill-formed[.](#16.6.3.sentence-2)
The function
selected is called with the initializer expression as its
argument; if the function is a constructor, the call is a prvalue
of the cv-unqualified version of the
destination type whose result object is initialized by the constructor[.](#16.6.3.sentence-3)
The call is used
to direct-initialize, according to the rules above, the object
that is the destination of the copy-initialization[.](#16.6.3.sentence-4)
- [(16.7)](#16.7)
Otherwise, if the source type
is a (possibly cv-qualified) class type, conversion functions are
considered[.](#16.7.sentence-1)
The applicable conversion functions are enumerated ([[over.match.conv]](over.match.conv "12.2.2.6Initialization by conversion function")),
and the best one is chosen through overload
resolution ([[over.match]](over.match "12.2Overload resolution"))[.](#16.7.sentence-2)
The user-defined conversion so selected
is called to convert the initializer expression into the
object being initialized[.](#16.7.sentence-3)
If the conversion cannot be done or is
ambiguous, the initialization is ill-formed[.](#16.7.sentence-4)
- [(16.8)](#16.8)
Otherwise, if the initialization is direct-initialization,
the source type is std::nullptr_t, and
the destination type is bool,
the initial value of the object being initialized is false[.](#16.8.sentence-1)
- [(16.9)](#16.9)
Otherwise, the initial value of the object being initialized is
the (possibly converted) value of the initializer expression[.](#16.9.sentence-1)
A standard conversion sequence ([[conv]](conv "7.3Standard conversions")) is used
to convert the initializer expression to
a prvalue of
the destination type;
no user-defined conversions are considered[.](#16.9.sentence-2)
If the conversion cannot
be done, the initialization is ill-formed[.](#16.9.sentence-3)
When initializing a bit-field with a value that it cannot represent, the
resulting value of the bit-field isimplementation-defined[.](#16.9.sentence-4)
[*Note [8](#note-8)*:
An expression of type
“*cv1* €
can initialize an object of type
“*cv2* €
independently of
the cv-qualifiers*cv1* and *cv2*[.](#16.9.sentence-5)
int a;const int b = a;int c = b; — *end note*]
[17](#17)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L5407)
An immediate invocation ([[expr.const]](expr.const "7.7Constant expressions")) that is not evaluated where
it appears ([[dcl.fct.default]](dcl.fct.default "9.3.4.7Default arguments"), [[class.mem.general]](class.mem.general "11.4.1General"))
is evaluated and checked for whether it is
a constant expression at the point where
the enclosing [*initializer*](#nt:initializer "9.5.1General[dcl.init.general]") is used in
a function call, a constructor definition, or an aggregate initialization[.](#17.sentence-1)
[18](#18)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L5415)
An [*initializer-clause*](#nt:initializer-clause "9.5.1General[dcl.init.general]") followed by an ellipsis is a
pack expansion ([[temp.variadic]](temp.variadic "13.7.4Variadic templates"))[.](#18.sentence-1)
[19](#19)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L5419)
Initialization includes
the evaluation of all subexpressions of
each [*initializer-clause*](#nt:initializer-clause "9.5.1General[dcl.init.general]") of
the initializer (possibly nested within [*braced-init-list*](#nt:braced-init-list "9.5.1General[dcl.init.general]")*s*) and
the creation of any temporary objects for
function arguments or return values ([[class.temporary]](class.temporary "6.8.7Temporary objects"))[.](#19.sentence-1)
[20](#20)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L5427)
If the initializer is a parenthesized [*expression-list*](expr.post.general#nt:expression-list "7.6.1.1General[expr.post.general]"),
the expressions are evaluated in the order
specified for function calls ([[expr.call]](expr.call "7.6.1.3Function call"))[.](#20.sentence-1)
[21](#21)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L5432)
The same [*identifier*](lex.name#nt:identifier "5.11Identifiers[lex.name]") shall not appear in multiple [*designator*](#nt:designator "9.5.1General[dcl.init.general]")*s* of a[*designated-initializer-list*](#nt:designated-initializer-list "9.5.1General[dcl.init.general]")[.](#21.sentence-1)
[22](#22)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L5437)
An object whose initialization has completed
is deemed to be constructed,
even if the object is of non-class type or
no constructor of the object's class
is invoked for the initialization[.](#22.sentence-1)
[*Note [9](#note-9)*:
Such an object might have been value-initialized
or initialized by aggregate initialization ([[dcl.init.aggr]](dcl.init.aggr "9.5.2Aggregates"))
or by an inherited constructor ([[class.inhctor.init]](class.inhctor.init "11.9.4Initialization by inherited constructor"))[.](#22.sentence-2)
— *end note*]
Destroying an object of class type invokes the destructor of the class[.](#22.sentence-3)
Destroying a scalar type has no effect other than
ending the lifetime of the object ([[basic.life]](basic.life "6.8.4Lifetime"))[.](#22.sentence-4)
Destroying an array destroys each element in reverse subscript order[.](#22.sentence-5)
[23](#23)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L5453)
A declaration that specifies the initialization of a variable,
whether from an explicit initializer or by default-initialization,
is called the [*initializing declaration*](#def:initializing_declaration "9.5.1General[dcl.init.general]") of that variable[.](#23.sentence-1)
[*Note [10](#note-10)*:
In most cases
this is the defining declaration ([[basic.def]](basic.def "6.2Declarations and definitions")) of the variable,
but the initializing declaration
of a non-inline static data member ([[class.static.data]](class.static.data "11.4.9.3Static data members"))
can be the declaration within the class definition
and not the definition (if any) outside it[.](#23.sentence-2)
— *end note*]
[78)](#footnote-78)[78)](#footnoteref-78)
As specified in [[conv.ptr]](conv.ptr "7.3.12Pointer conversions"), converting an integer
literal whose value is0 to a pointer type results in a null pointer value[.](#footnote-78.sentence-1)

368
cppdraft/dcl/init/list.md Normal file
View File

@@ -0,0 +1,368 @@
[dcl.init.list]
# 9 Declarations [[dcl]](./#dcl)
## 9.5 Initializers [[dcl.init]](dcl.init#list)
### 9.5.5 List-initialization [dcl.init.list]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L6366)
[*List-initialization*](#def:list-initialization "9.5.5List-initialization[dcl.init.list]") is initialization of an object or reference from a[*braced-init-list*](dcl.init.general#nt:braced-init-list "9.5.1General[dcl.init.general]")[.](#1.sentence-1)
Such an initializer is called an [*initializer list*](#def:initializer_list), and
the comma-separated[*initializer-clause*](dcl.init.general#nt:initializer-clause "9.5.1General[dcl.init.general]")*s* of the [*initializer-list*](dcl.init.general#nt:initializer-list "9.5.1General[dcl.init.general]") or[*designated-initializer-clause*](dcl.init.general#nt:designated-initializer-clause "9.5.1General[dcl.init.general]")*s* of the [*designated-initializer-list*](dcl.init.general#nt:designated-initializer-list "9.5.1General[dcl.init.general]") are called the [*elements*](#def:elements) of the initializer list[.](#1.sentence-2)
An initializer list may be empty[.](#1.sentence-3)
List-initialization can occur in direct-initialization or copy-initialization contexts;
list-initialization in a direct-initialization context is called[*direct-list-initialization*](#def:direct-list-initialization "9.5.5List-initialization[dcl.init.list]") and list-initialization in a
copy-initialization context is called [*copy-list-initialization*](#def:copy-list-initialization "9.5.5List-initialization[dcl.init.list]")[.](#1.sentence-4)
Direct-initialization that is not list-initialization is called[*direct-non-list-initialization*](#def:direct-non-list-initialization "9.5.5List-initialization[dcl.init.list]")[.](#1.sentence-5)
[*Note [1](#note-1)*:
List-initialization can be used
- [(1.1)](#1.1)
as the initializer in a variable definition ([[dcl.init]](dcl.init "9.5Initializers")),
- [(1.2)](#1.2)
as the initializer in a [*new-expression*](expr.new#nt:new-expression "7.6.2.8New[expr.new]") ([[expr.new]](expr.new "7.6.2.8New")),
- [(1.3)](#1.3)
in a return statement ([[stmt.return]](stmt.return "8.8.4The return statement")),
- [(1.4)](#1.4)
as a [*for-range-initializer*](stmt.pre#nt:for-range-initializer "8.1Preamble[stmt.pre]") ([[stmt.iter]](stmt.iter "8.6Iteration statements")),
- [(1.5)](#1.5)
as a function argument ([[expr.call]](expr.call "7.6.1.3Function call")),
- [(1.6)](#1.6)
as a template argument ([[temp.arg.nontype]](temp.arg.nontype "13.4.3Constant template arguments")),
- [(1.7)](#1.7)
as a subscript ([[expr.sub]](expr.sub "7.6.1.2Subscripting")),
- [(1.8)](#1.8)
as an argument to a constructor invocation ([[dcl.init]](dcl.init "9.5Initializers"), [[expr.type.conv]](expr.type.conv "7.6.1.4Explicit type conversion (functional notation)")),
- [(1.9)](#1.9)
as an initializer for a non-static data member ([[class.mem]](class.mem "11.4Class members")),
- [(1.10)](#1.10)
in a [*mem-initializer*](class.base.init#nt:mem-initializer "11.9.3Initializing bases and members[class.base.init]") ([[class.base.init]](class.base.init "11.9.3Initializing bases and members")), or
- [(1.11)](#1.11)
on the right-hand side of an assignment ([[expr.assign]](expr.assign "7.6.19Assignment and compound assignment operators"))[.](#1.sentence-6)
[*Example [1](#example-1)*: int a = {1};
std::complex<double> z{1,2};new std::vector<std::string>{"once", "upon", "a", "time"}; // 4 string elements f( {"Nicholas","Annemarie"} ); // pass list of two elementsreturn { "Norah" }; // return list of one elementint* e {}; // initialization to zero / null pointer x = double{1}; // explicitly construct a double std::map<std::string,int> anim = { {"bear",4}, {"cassowary",2}, {"tiger",7} }; — *end example*]
— *end note*]
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L6413)
A constructor is an [*initializer-list constructor*](#def:initializer-list_constructor "9.5.5List-initialization[dcl.init.list]") if its first parameter is
of type std::initializer_list<E> or reference tocv std::initializer_list<E> for some type E, and either there are no other
parameters or else all other parameters have default arguments ([[dcl.fct.default]](dcl.fct.default "9.3.4.7Default arguments"))[.](#2.sentence-1)
[*Note [2](#note-2)*:
Initializer-list constructors are favored over other constructors in
list-initialization ([[over.match.list]](over.match.list "12.2.2.8Initialization by list-initialization"))[.](#2.sentence-2)
Passing an initializer list as the argument
to the constructor template template<class T> C(T) of a class C does not
create an initializer-list constructor, because an initializer list argument causes the
corresponding parameter to be a non-deduced context ([[temp.deduct.call]](temp.deduct.call "13.10.3.2Deducing template arguments from a function call"))[.](#2.sentence-3)
— *end note*]
The templatestd::initializer_list is not predefined;
if a standard library declaration ([[initializer.list.syn]](initializer.list.syn "17.11.2Header <initializer_­list> synopsis"), [[std.modules]](std.modules "16.4.2.4Modules"))
of std::initializer_list is not reachable from ([[module.reach]](module.reach "10.7Reachability"))
a use of std::initializer_list —
even an implicit use in which the type is not named ([[dcl.spec.auto]](dcl.spec.auto "9.2.9.7Placeholder type specifiers")) —
the program is ill-formed[.](#2.sentence-4)
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L6433)
List-initialization of an object or reference of type *cv* T is defined as follows:
- [(3.1)](#3.1)
If the [*braced-init-list*](dcl.init.general#nt:braced-init-list "9.5.1General[dcl.init.general]") contains a [*designated-initializer-list*](dcl.init.general#nt:designated-initializer-list "9.5.1General[dcl.init.general]") andT is not a reference type,T shall be an aggregate class[.](#3.1.sentence-1)
The ordered [*identifier*](lex.name#nt:identifier "5.11Identifiers[lex.name]")*s* in the [*designator*](dcl.init.general#nt:designator "9.5.1General[dcl.init.general]")*s* of the [*designated-initializer-list*](dcl.init.general#nt:designated-initializer-list "9.5.1General[dcl.init.general]") shall form a subsequence
of the ordered [*identifier*](lex.name#nt:identifier "5.11Identifiers[lex.name]")*s* in the direct non-static data members of T[.](#3.1.sentence-2)
Aggregate initialization is performed ([[dcl.init.aggr]](dcl.init.aggr "9.5.2Aggregates"))[.](#3.1.sentence-3)
[*Example [2](#example-2)*: struct A { int x; int y; int z; };
A a{.y = 2, .x = 1}; // error: designator order does not match declaration order A b{.x = 1, .z = 2}; // OK, b.y initialized to 0 — *end example*]
- [(3.2)](#3.2)
If T is an aggregate class and the initializer list has a single element
of type *cv1* U,
where U is T or a class derived from T,
the object is initialized from that element (by copy-initialization for
copy-list-initialization, or by direct-initialization for
direct-list-initialization)[.](#3.2.sentence-1)
- [(3.3)](#3.3)
Otherwise, if T is a character array and the initializer list has a
single element that is an appropriately-typed [*string-literal*](lex.string#nt:string-literal "5.13.5String literals[lex.string]") ([[dcl.init.string]](dcl.init.string "9.5.3Character arrays")),
initialization is performed as described in that subclause[.](#3.3.sentence-1)
- [(3.4)](#3.4)
Otherwise, if T is an aggregate, aggregate initialization is
performed ([[dcl.init.aggr]](dcl.init.aggr "9.5.2Aggregates"))[.](#3.4.sentence-1)
[*Example [3](#example-3)*: double ad[] = { 1, 2.0 }; // OKint ai[] = { 1, 2.0 }; // error: narrowingstruct S2 {int m1; double m2, m3;};
S2 s21 = { 1, 2, 3.0 }; // OK S2 s22 { 1.0, 2, 3 }; // error: narrowing S2 s23 { }; // OK, default to 0,0,0 — *end example*]
- [(3.5)](#3.5)
Otherwise, if the initializer list has no elements and T is a class type with a
default constructor, the object is value-initialized[.](#3.5.sentence-1)
- [(3.6)](#3.6)
Otherwise, if T is a specialization of std::initializer_list,
the object is constructed as described below[.](#3.6.sentence-1)
- [(3.7)](#3.7)
Otherwise, if T is a class type, constructors are considered[.](#3.7.sentence-1)
The applicable constructors are enumerated and
the best one is chosen through overload resolution ([[over.match]](over.match "12.2Overload resolution"), [[over.match.list]](over.match.list "12.2.2.8Initialization by list-initialization"))[.](#3.7.sentence-2)
If a narrowing
conversion (see below) is required to convert any of the arguments, the program is
ill-formed[.](#3.7.sentence-3)
[*Example [4](#example-4)*: struct S { S(std::initializer_list<double>); // #1 S(std::initializer_list<int>); // #2 S(std::initializer_list<S>); // #3 S(); // #4// ...};
S s1 = { 1.0, 2.0, 3.0 }; // invoke #1 S s2 = { 1, 2, 3 }; // invoke #2 S s3{s2}; // invoke #3 (not the copy constructor) S s4 = { }; // invoke #4 — *end example*]
[*Example [5](#example-5)*: struct Map { Map(std::initializer_list<std::pair<std::string,int>>);};
Map ship = {{"Sophie",14}, {"Surprise",28}}; — *end example*]
[*Example [6](#example-6)*: struct S {// no initializer-list constructors S(int, double, double); // #1 S(); // #2// ...};
S s1 = { 1, 2, 3.0 }; // OK, invoke #1 S s2 { 1.0, 2, 3 }; // error: narrowing S s3 { }; // OK, invoke #2 — *end example*]
- [(3.8)](#3.8)
Otherwise, if T is an enumeration
with a fixed underlying type ([[dcl.enum]](dcl.enum "9.8.1Enumeration declarations")) U,
the [*initializer-list*](dcl.init.general#nt:initializer-list "9.5.1General[dcl.init.general]") has a single element v of scalar type,v can be implicitly converted to U, and
the initialization is direct-list-initialization,
the object is initialized with the value T(v) ([[expr.type.conv]](expr.type.conv "7.6.1.4Explicit type conversion (functional notation)"));
if a narrowing conversion is required to convert v to U, the program is ill-formed[.](#3.8.sentence-1)
[*Example [7](#example-7)*: enum byte : unsigned char { };
byte b { 42 }; // OK byte c = { 42 }; // error byte d = byte{ 42 }; // OK; same value as b byte e { -1 }; // errorstruct A { byte b; };
A a1 = { { 42 } }; // error A a2 = { byte{ 42 } }; // OKvoid f(byte);
f({ 42 }); // errorenum class Handle : uint32_t { Invalid = 0 };
Handle h { 42 }; // OK — *end example*]
- [(3.9)](#3.9)
Otherwise, if
the initializer list
is not a [*designated-initializer-list*](dcl.init.general#nt:designated-initializer-list "9.5.1General[dcl.init.general]") and
has a single element of type E and eitherT is not a reference type or its referenced type is
reference-related to E, the object or reference is initialized
from that element (by copy-initialization for copy-list-initialization,
or by direct-initialization for direct-list-initialization);
if a narrowing conversion (see below) is required
to convert the element to T, the program is ill-formed[.](#3.9.sentence-1)
[*Example [8](#example-8)*: int x1 {2}; // OKint x2 {2.0}; // error: narrowing — *end example*]
- [(3.10)](#3.10)
Otherwise, if T is a reference type, a prvalue is generated[.](#3.10.sentence-1)
The prvalue initializes its result object by copy-list-initialization from the initializer list[.](#3.10.sentence-2)
The prvalue is then used to direct-initialize the reference[.](#3.10.sentence-3)
The type of the prvalue is the type referenced by T,
unless T is “reference to array of unknown bound of U”,
in which case the type of the prvalue is
the type of x in the declaration U x[] H,
where H is the initializer list[.](#3.10.sentence-4)
[*Note [3](#note-3)*:
As usual, the binding will fail and the program is ill-formed if
the reference type is an lvalue reference to a non-const type[.](#3.10.sentence-5)
— *end note*]
[*Example [9](#example-9)*: struct S { S(std::initializer_list<double>); // #1 S(const std::string&); // #2// ...};const S& r1 = { 1, 2, 3.0 }; // OK, invoke #1const S& r2 { "Spinach" }; // OK, invoke #2 S& r3 = { 1, 2, 3 }; // error: initializer is not an lvalueconst int& i1 = { 1 }; // OKconst int& i2 = { 1.1 }; // error: narrowingconst int (&iar)[2] = { 1, 2 }; // OK, iar is bound to temporary arraystruct A { } a;struct B { explicit B(const A&); };const B& b2{a}; // error: cannot copy-list-initialize B temporary from Astruct C { int x; };
C&& c = { .x = 1 }; // OK — *end example*]
- [(3.11)](#3.11)
Otherwise, if the initializer list has no elements, the object is
value-initialized[.](#3.11.sentence-1)
[*Example [10](#example-10)*: int** pp {}; // initialized to null pointer — *end example*]
- [(3.12)](#3.12)
Otherwise, the program is ill-formed[.](#3.12.sentence-1)
[*Example [11](#example-11)*: struct A { int i; int j; };
A a1 { 1, 2 }; // aggregate initialization A a2 { 1.2 }; // error: narrowingstruct B { B(std::initializer_list<int>);};
B b1 { 1, 2 }; // creates initializer_list<int> and calls constructor B b2 { 1, 2.0 }; // error: narrowingstruct C { C(int i, double j);};
C c1 = { 1, 2.2 }; // calls constructor with arguments (1, 2.2) C c2 = { 1.1, 2 }; // error: narrowingint j { 1 }; // initialize to 1int k { }; // initialize to 0 — *end example*]
[4](#4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L6651)
Within the [*initializer-list*](dcl.init.general#nt:initializer-list "9.5.1General[dcl.init.general]") of a [*braced-init-list*](dcl.init.general#nt:braced-init-list "9.5.1General[dcl.init.general]"),
the [*initializer-clause*](dcl.init.general#nt:initializer-clause "9.5.1General[dcl.init.general]")*s*, including any that result from pack
expansions ([[temp.variadic]](temp.variadic "13.7.4Variadic templates")), are evaluated in the order in which they
appear[.](#4.sentence-1)
That is, every value computation and side effect associated with a
given [*initializer-clause*](dcl.init.general#nt:initializer-clause "9.5.1General[dcl.init.general]") is sequenced before every value
computation and side effect associated with any [*initializer-clause*](dcl.init.general#nt:initializer-clause "9.5.1General[dcl.init.general]") that follows it in the comma-separated list of the [*initializer-list*](dcl.init.general#nt:initializer-list "9.5.1General[dcl.init.general]")[.](#4.sentence-2)
[*Note [4](#note-4)*:
This evaluation ordering holds regardless of the semantics of the
initialization; for example, it applies when the elements of the[*initializer-list*](dcl.init.general#nt:initializer-list "9.5.1General[dcl.init.general]") are interpreted as arguments of a constructor
call, even though ordinarily there are no sequencing constraints on the
arguments of a call[.](#4.sentence-3)
— *end note*]
[5](#5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L6667)
An object of type std::initializer_list<E> is constructed from
an initializer list as if
the implementation generated and materialized ([[conv.rval]](conv.rval "7.3.5Temporary materialization conversion"))
a prvalue of type “array of N const E”,
where N is the number of elements in the initializer list;
this is called the initializer list's [*backing array*](#def:array,backing "9.5.5List-initialization[dcl.init.list]")[.](#5.sentence-1)
Each element of the backing array is copy-initialized with the
corresponding element of the initializer list, and thestd::initializer_list<E> object is constructed to refer to that array[.](#5.sentence-2)
[*Note [5](#note-5)*:
A constructor or conversion function selected for the copy needs to be
accessible ([[class.access]](class.access "11.8Member access control")) in the context of the initializer list[.](#5.sentence-3)
— *end note*]
If a narrowing conversion is required to initialize any of the elements,
the program is ill-formed[.](#5.sentence-4)
[*Note [6](#note-6)*:
Backing arrays are potentially non-unique objects ([[intro.object]](intro.object "6.8.2Object model"))[.](#5.sentence-5)
— *end note*]
[6](#6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L6687)
The backing array has the same lifetime as any other temporary
object ([[class.temporary]](class.temporary "6.8.7Temporary objects")), except that initializing aninitializer_list object from the array extends the lifetime of
the array exactly like binding a reference to a temporary[.](#6.sentence-1)
[*Example [12](#example-12)*: void f(std::initializer_list<double> il);void g(float x) { f({1, x, 3});}void h() { f({1, 2, 3});}struct A {mutable int i;};void q(std::initializer_list<A>);void r() { q({A{1}, A{2}, A{3}});}
The initialization will be implemented in a way roughly equivalent to this:void g(float x) {const double __a[3] = {double{1}, double{x}, double{3}}; // backing array f(std::initializer_list<double>(__a, __a+3));}void h() {static constexpr double __b[3] = {double{1}, double{2}, double{3}}; // backing array f(std::initializer_list<double>(__b, __b+3));}void r() {const A __c[3] = {A{1}, A{2}, A{3}}; // backing array q(std::initializer_list<A>(__c, __c+3));} assuming that the implementation
can construct an initializer_list object with a pair of pointers, and
with the understanding that __b does not outlive the call to f[.](#6.sentence-2)
— *end example*]
[*Example [13](#example-13)*: typedef std::complex<double> cmplx;
std::vector<cmplx> v1 = { 1, 2, 3 };
void f() { std::vector<cmplx> v2{ 1, 2, 3 };
std::initializer_list<int> i3 = { 1, 2, 3 };}struct A { std::initializer_list<int> i4;
A() : i4{ 1, 2, 3 } {} // ill-formed, would create a dangling reference};
For v1 and v2, the initializer_list object
is a parameter in a function call, so the array created for{ 1, 2, 3 } has full-expression lifetime[.](#6.sentence-3)
For i3, the initializer_list object is a variable,
so the array persists for the lifetime of the variable[.](#6.sentence-4)
For i4, the initializer_list object is initialized in
the constructor's [*ctor-initializer*](class.base.init#nt:ctor-initializer "11.9.3Initializing bases and members[class.base.init]") as if by binding
a temporary array to a reference member, so the program is
ill-formed ([[class.base.init]](class.base.init "11.9.3Initializing bases and members"))[.](#6.sentence-5)
— *end example*]
[7](#7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L6758)
A [*narrowing conversion*](#def:conversion,narrowing "9.5.5List-initialization[dcl.init.list]") is an implicit conversion
- [(7.1)](#7.1)
from a floating-point type to an integer type, or
- [(7.2)](#7.2)
from a floating-point type T to another floating-point type
whose floating-point conversion rank is neither greater than nor equal to
that of T,
except where the result of the conversion is a constant expression and
either its value is finite and the conversion did not overflow, or
the values before and after the conversion are not finite, or
- [(7.3)](#7.3)
from an integer type or unscoped enumeration type to a floating-point type, except
where the source is a constant expression and the actual value after conversion will fit
into the target type and will produce the original value when converted back to the
original type, or
- [(7.4)](#7.4)
from an integer type or unscoped enumeration type to an integer type that cannot
represent all the values of the original type, except where
* [(7.4.1)](#7.4.1)
the source is a bit-field whose width w is less than that of its type
(or, for an enumeration type, its underlying type) and
the target type can represent all the values
of a hypothetical extended integer type
with width w and with the same signedness as the original type or
* [(7.4.2)](#7.4.2)
the source is a constant
expression whose value after integral promotions will fit into the target type, or
- [(7.5)](#7.5)
from a pointer type or a pointer-to-member type to bool[.](#7.sentence-1)
[*Note [7](#note-7)*:
As indicated above, such conversions are not allowed at the top level in
list-initializations[.](#7.sentence-2)
— *end note*]
[*Example [14](#example-14)*: int x = 999; // x is not a constant expressionconst int y = 999;const int z = 99;char c1 = x; // OK, though it potentially narrows (in this case, it does narrow)char c2{x}; // error: potentially narrowschar c3{y}; // error: narrows (assuming char is 8 bits)char c4{z}; // OK, no narrowing neededunsigned char uc1 = {5}; // OK, no narrowing neededunsigned char uc2 = {-1}; // error: narrowsunsigned int ui1 = {-1}; // error: narrowssigned int si1 ={ (unsigned int)-1 }; // error: narrowsint ii = {2.0}; // error: narrowsfloat f1 { x }; // error: potentially narrowsfloat f2 { 7 }; // OK, 7 can be exactly represented as a floatbool b = {"meow"}; // error: narrowsint f(int);int a[] = { 2, f(2), f(2.0) }; // OK, the double-to-int conversion is not at the top level — *end example*]

188
cppdraft/dcl/init/ref.md Normal file
View File

@@ -0,0 +1,188 @@
[dcl.init.ref]
# 9 Declarations [[dcl]](./#dcl)
## 9.5 Initializers [[dcl.init]](dcl.init#ref)
### 9.5.4 References [dcl.init.ref]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L6115)
A variable whose declared type is
“reference to T” ([[dcl.ref]](dcl.ref "9.3.4.3References"))
shall be initialized[.](#1.sentence-1)
[*Example [1](#example-1)*: int g(int) noexcept;void f() {int i; int& r = i; // r refers to i r = 1; // the value of i becomes 1int* p = &r; // p points to iint& rr = r; // rr refers to what r refers to, that is, to iint (&rg)(int) = g; // rg refers to the function g rg(i); // calls function gint a[3]; int (&ra)[3] = a; // ra refers to the array a ra[1] = i; // modifies a[1]} — *end example*]
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L6137)
A reference cannot be changed to refer to another object after initialization[.](#2.sentence-1)
[*Note [1](#note-1)*:
Assignment to a reference assigns to the object referred to by the reference ([[expr.assign]](expr.assign "7.6.19Assignment and compound assignment operators"))[.](#2.sentence-2)
— *end note*]
Argument passing ([[expr.call]](expr.call "7.6.1.3Function call"))and function value return ([[stmt.return]](stmt.return "8.8.4The return statement")) are initializations[.](#2.sentence-3)
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L6148)
The initializer can be omitted for a reference only in a parameter declaration ([[dcl.fct]](dcl.fct "9.3.4.6Functions")),
in the declaration of a function return type, in the declaration of
a class member within its class definition ([[class.mem]](class.mem "11.4Class members")), and where theextern specifier is explicitly used[.](#3.sentence-1)
[*Example [2](#example-2)*: int& r1; // error: initializer missingextern int& r2; // OK — *end example*]
[4](#4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L6162)
Given types “*cv1* T1” and “*cv2* T2”,
“*cv1* T1” is [*reference-related*](#def:reference-related "9.5.4References[dcl.init.ref]") to
“*cv2* T2” ifT1 is similar ([[conv.qual]](conv.qual "7.3.6Qualification conversions")) to T2, orT1 is a base class of T2[.](#4.sentence-1)
“*cv1* T1” is [*reference-compatible*](#def:reference-compatible "9.5.4References[dcl.init.ref]") with “*cv2* T2” if
a prvalue of type “pointer to *cv2* T2” can be converted to
the type “pointer to *cv1* T1”
via a standard conversion sequence ([[conv]](conv "7.3Standard conversions"))[.](#4.sentence-2)
In all cases where the reference-compatible relationship
of two types is used to establish the validity of a reference binding and
the standard conversion sequence would be ill-formed,
a program that necessitates such a binding is ill-formed[.](#4.sentence-3)
[5](#5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L6178)
A reference to type “*cv1* T1” is initialized by
an expression of type “*cv2* T2” as follows:
- [(5.1)](#5.1)
If the reference is an lvalue reference and the initializer expression
* [(5.1.1)](#5.1.1)
is an lvalue (but is not a
bit-field), and
“*cv1* T1” is reference-compatible with
“*cv2* T2”, or
* [(5.1.2)](#5.1.2)
has a class type (i.e.,T2 is a class type), where T1 is not reference-related to T2, and can be converted
to an lvalue of type “*cv3* T3”, where
“*cv1* T1” is reference-compatible with
“*cv3* T3”[80](#footnote-80 "This requires a conversion function ([class.conv.fct]) returning a reference type.") (this conversion is selected by enumerating the applicable conversion
functions ([[over.match.ref]](over.match.ref "12.2.2.7Initialization by conversion function for direct reference binding")) and choosing the best one through [overload
resolution](over.match "12.2Overload resolution[over.match]")),
then the reference binds to the initializer expression lvalue in the
first case and to the lvalue result of the conversion
in the second case (or, in either case, to the appropriate base class subobject of the object)[.](#5.1.sentence-1)
[*Note [2](#note-2)*:
The usual [lvalue-to-rvalue](conv.lval "7.3.2Lvalue-to-rvalue conversion[conv.lval]"), [array-to-pointer](conv.array "7.3.3Array-to-pointer conversion[conv.array]"),
and [function-to-pointer](conv.func "7.3.4Function-to-pointer conversion[conv.func]") standard
conversions are not needed, and therefore are suppressed, when such
direct bindings to lvalues are done[.](#5.1.sentence-2)
— *end note*]
[*Example [3](#example-3)*: double d = 2.0;double& rd = d; // rd refers to dconst double& rcd = d; // rcd refers to dstruct A { };struct B : A { operator int&(); } b;
A& ra = b; // ra refers to A subobject in bconst A& rca = b; // rca refers to A subobject in bint& ir = B(); // ir refers to the result of B::operator int& — *end example*]
- [(5.2)](#5.2)
Otherwise,
if the reference is an lvalue reference to a
type that is not const-qualified or is volatile-qualified,
the program is ill-formed[.](#5.2.sentence-1)
[*Example [4](#example-4)*: double& rd2 = 2.0; // error: not an lvalue and reference not constint i = 2;double& rd3 = i; // error: type mismatch and reference not const — *end example*]
- [(5.3)](#5.3)
Otherwise, if the initializer expression
* [(5.3.1)](#5.3.1)
is an rvalue (but not a bit-field) or an lvalue of function type and
“*cv1* T1” is
reference-compatible with “*cv2* T2”, or
* [(5.3.2)](#5.3.2)
has a class type (i.e., T2 is a class type), where T1 is not reference-related to T2, and can be converted to
an rvalue of type “*cv3* T3” or
an lvalue of function type “*cv3* T3”,
where “*cv1* T1” is
reference-compatible with “*cv3* T3” (see [[over.match.ref]](over.match.ref "12.2.2.7Initialization by conversion function for direct reference binding")),
then
the initializer expression in the first case and
the converted expression in the second case
is called the converted initializer[.](#5.3.sentence-1)
If the converted initializer is a prvalue,
let its type be denoted by T4;
the temporary materialization conversion ([[conv.rval]](conv.rval "7.3.5Temporary materialization conversion")) is applied,
considering the type of the prvalue to be
“*cv1* T4” ([[conv.qual]](conv.qual "7.3.6Qualification conversions"))[.](#5.3.sentence-2)
In any case,
the reference binds to the resulting glvalue
(or to an appropriate base class subobject)[.](#5.3.sentence-3)
[*Example [5](#example-5)*: struct A { };struct B : A { } b;extern B f();const A& rca2 = f(); // binds to the A subobject of the B rvalue. A&& rra = f(); // same as abovestruct X {operator B(); operator int&();} x;const A& r = x; // binds to the A subobject of the result of the conversionint i2 = 42;int&& rri = static_cast<int&&>(i2); // binds directly to i2 B&& rrb = x; // binds directly to the result of operator Bconstexpr int f() {const int &x = 42; const_cast<int &>(x) = 1; // undefined behaviorreturn x;}constexpr int z = f(); // error: not a constant expressiontypedef int *AP[3]; // array of 3 pointer to inttypedef const int *const ACPC[3]; // array of 3 const pointer to const int ACPC &&r = AP{}; // binds directly — *end example*]
- [(5.4)](#5.4)
Otherwise, T1 shall not be reference-related to T2[.](#5.4.sentence-1)
* [(5.4.1)](#5.4.1)
If T1 or T2 is a class type,
user-defined conversions are considered
using the rules for copy-initialization of an object of type
“*cv1* T1” by
user-defined conversion ([[dcl.init]](dcl.init "9.5Initializers"), [[over.match.copy]](over.match.copy "12.2.2.5Copy-initialization of class by user-defined conversion"), [[over.match.conv]](over.match.conv "12.2.2.6Initialization by conversion function"));
the program is ill-formed if the corresponding non-reference
copy-initialization would be ill-formed[.](#5.4.1.sentence-1)
The result E of the call to the
conversion function, as described for the non-reference
copy-initialization, is then used to direct-initialize the reference
using the form (E)[.](#5.4.1.sentence-2)
For this direct-initialization, user-defined conversions are not considered[.](#5.4.1.sentence-3)
* [(5.4.2)](#5.4.2)
Otherwise,
the initializer expression is implicitly converted to a prvalue
of type “T1”[.](#5.4.2.sentence-1)
The temporary materialization conversion is applied,
considering the type of the prvalue to be “*cv1* T1”,
and the reference is bound to the result[.](#5.4.2.sentence-2)
[*Example [6](#example-6)*: struct Banana { };struct Enigma { operator const Banana(); };struct Alaska { operator Banana&(); };void enigmatic() {typedef const Banana ConstBanana;
Banana &&banana1 = ConstBanana(); // error Banana &&banana2 = Enigma(); // error Banana &&banana3 = Alaska(); // error}const double& rcd2 = 2; // rcd2 refers to temporary with type const double and value 2.0double&& rrd = 2; // rrd refers to temporary with value 2.0const volatile int cvi = 1;const int& r2 = cvi; // error: cv-qualifier droppedstruct A { operator volatile int&(); } a;const int& r3 = a; // error: cv-qualifier dropped// from result of conversion functiondouble d2 = 1.0;double&& rrd2 = d2; // error: initializer is lvalue of reference-related typestruct X { operator int&(); };int&& rri2 = X(); // error: result of conversion function is// lvalue of reference-related typeint i3 = 2;double&& rrd3 = i3; // rrd3 refers to temporary with value 2.0 — *end example*]
In all cases except the last
(i.e., implicitly converting the initializer expression
to the referenced type),
the reference is said to [*bind directly*](#def:bind_directly "9.5.4References[dcl.init.ref]") to the
initializer expression[.](#5.sentence-2)
[6](#6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L6358)
[*Note [3](#note-3)*:
[[class.temporary]](class.temporary "6.8.7Temporary objects") describes the lifetime of temporaries bound to references[.](#6.sentence-1)
— *end note*]
[80)](#footnote-80)[80)](#footnoteref-80)
This requires a conversion
function ([[class.conv.fct]](class.conv.fct "11.4.8.3Conversion functions")) returning a reference type[.](#footnote-80.sentence-1)

View File

@@ -0,0 +1,61 @@
[dcl.init.string]
# 9 Declarations [[dcl]](./#dcl)
## 9.5 Initializers [[dcl.init]](dcl.init#string)
### 9.5.3 Character arrays [dcl.init.string]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L6051)
An array of ordinary character type ([[basic.fundamental]](basic.fundamental "6.9.2Fundamental types")),char8_t array,char16_t array,char32_t array,
or wchar_t array
may be initialized by
an ordinary string literal,
UTF-8 string literal,
UTF-16 string literal,
UTF-32 string literal, or
wide string literal,
respectively, or by an appropriately-typed [*string-literal*](lex.string#nt:string-literal "5.13.5String literals[lex.string]") enclosed in
braces ([[lex.string]](lex.string "5.13.5String literals"))[.](#1.sentence-1)
Additionally, an array of char orunsigned char may be initialized by
a UTF-8 string literal, or by
such a string literal enclosed in braces[.](#1.sentence-2)
Successive
characters of the
value of the [*string-literal*](lex.string#nt:string-literal "5.13.5String literals[lex.string]") initialize the elements of the array,
with an integral conversion ([[conv.integral]](conv.integral "7.3.9Integral conversions"))
if necessary for the source and destination value[.](#1.sentence-3)
[*Example [1](#example-1)*:
char msg[] = "Syntax error on line %s\n"; shows a character array whose members are initialized
with a[*string-literal*](lex.string#nt:string-literal "5.13.5String literals[lex.string]")[.](#1.sentence-4)
Note that because'\n' is a single character and
because a trailing'\0' is appended,sizeof(msg) is25[.](#1.sentence-5)
— *end example*]
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L6098)
There shall not be more initializers than there are array elements[.](#2.sentence-1)
[*Example [2](#example-2)*:
char cv[4] = "asdf"; // error is ill-formed since there is no space for the implied trailing'\0'[.](#2.sentence-2)
— *end example*]
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L6108)
If there are fewer initializers than there are array elements, each element not
explicitly initialized shall be zero-initialized ([[dcl.init]](dcl.init "9.5Initializers"))[.](#3.sentence-1)

112
cppdraft/dcl/inline.md Normal file
View File

@@ -0,0 +1,112 @@
[dcl.inline]
# 9 Declarations [[dcl]](./#dcl)
## 9.2 Specifiers [[dcl.spec]](dcl.spec#dcl.inline)
### 9.2.8 The inline specifier [dcl.inline]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L1092)
The inline specifier shall be applied only to the declaration
of a variable or function[.](#1.sentence-1)
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L1096)
A function declaration ([[dcl.fct]](dcl.fct "9.3.4.6Functions"), [[class.mfct]](class.mfct "11.4.2Member functions"), [[class.friend]](class.friend "11.8.4Friends"))
with an inline specifier declares an[*inline function*](#def:function,inline "9.2.8The inline specifier[dcl.inline]")[.](#2.sentence-1)
The inline specifier indicates to
the implementation that inline substitution of the function body at the
point of call is to be preferred to the usual function call mechanism[.](#2.sentence-2)
An implementation is not required to perform this inline substitution at
the point of call; however, even if this inline substitution is omitted,
the other rules for inline functions specified in this subclause shall
still be respected[.](#2.sentence-3)
[*Note [1](#note-1)*:
The inline keyword has no effect on the linkage of a function[.](#2.sentence-4)
In certain cases, an inline function cannot use names with internal linkage;
see [[basic.link]](basic.link "6.7Program and linkage")[.](#2.sentence-5)
— *end note*]
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L1114)
A variable declaration with an inline specifier declares an[*inline variable*](#def:variable,inline "9.2.8The inline specifier[dcl.inline]")[.](#3.sentence-1)
[4](#4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L1118)
The inline specifier shall not appear on a block scope declaration or
on the declaration of a function parameter[.](#4.sentence-1)
If the inline specifier is used in a friend function declaration, that
declaration shall be a definition or the function shall have previously
been declared inline[.](#4.sentence-2)
[5](#5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L1125)
If a definition of a function or variable is reachable
at the point of its
first declaration as inline, the program is ill-formed[.](#5.sentence-1)
If a function or variable
with external or module linkage
is declared inline in one definition domain,
an inline declaration of it shall be reachable
from the end of every definition domain in which it is declared;
no diagnostic is required[.](#5.sentence-2)
[*Note [2](#note-2)*:
A call to an inline function or a use of an inline variable can be encountered
before its definition becomes reachable in a translation unit[.](#5.sentence-3)
— *end note*]
[6](#6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L1139)
[*Note [3](#note-3)*:
An inline function or variable
with external or module linkage
can be defined in multiple translation units ([[basic.def.odr]](basic.def.odr "6.3One-definition rule")),
but is one entity with one address[.](#6.sentence-1)
A type or static variable
defined in the body of such a function
is therefore a single entity[.](#6.sentence-2)
— *end note*]
[7](#7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L1150)
If an inline function or variable that is attached to a named module
is declared in a definition domain,
it shall be defined in that domain[.](#7.sentence-1)
[*Note [4](#note-4)*:
A [constexpr function](dcl.constexpr#def:specifier,constexpr,function "9.2.6The constexpr and consteval specifiers[dcl.constexpr]") is implicitly inline[.](#7.sentence-2)
In the global module, a function defined within a class definition
is implicitly inline ([[class.mfct]](class.mfct "11.4.2Member functions"), [[class.friend]](class.friend "11.8.4Friends"))[.](#7.sentence-3)
— *end note*]

180
cppdraft/dcl/link.md Normal file
View File

@@ -0,0 +1,180 @@
[dcl.link]
# 9 Declarations [[dcl]](./#dcl)
## 9.12 Linkage specifications [dcl.link]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L9126)
All functions and variables whose names have external linkage
and all function types
have a [*language linkage*](#def:language_linkage "9.12Linkage specifications[dcl.link]")[.](#1.sentence-1)
[*Note [1](#note-1)*:
Some of the properties associated with an entity with language linkage
are specific to each implementation and are not described here[.](#1.sentence-2)
For
example, a particular language linkage might be associated with a
particular form of representing names of objects and functions with
external linkage, or with a particular calling convention, etc[.](#1.sentence-3)
— *end note*]
The default language linkage of all function types, functions, and
variables is C++ language linkage[.](#1.sentence-4)
Two function types with
different language linkages are distinct types even if they are
otherwise identical[.](#1.sentence-5)
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L9142)
[Linkage](basic.link "6.7Program and linkage[basic.link]") between C++ and non-C++ code fragments can
be achieved using a [*linkage-specification*](#nt:linkage-specification "9.12Linkage specifications[dcl.link]"):
[linkage-specification:](#nt:linkage-specification "9.12Linkage specifications[dcl.link]")
extern [*unevaluated-string*](lex.string.uneval#nt:unevaluated-string "5.13.6Unevaluated strings[lex.string.uneval]") { [*declaration-seq*](dcl.pre#nt:declaration-seq "9.1Preamble[dcl.pre]")opt }
extern [*unevaluated-string*](lex.string.uneval#nt:unevaluated-string "5.13.6Unevaluated strings[lex.string.uneval]") [*name-declaration*](dcl.pre#nt:name-declaration "9.1Preamble[dcl.pre]")
The [*unevaluated-string*](lex.string.uneval#nt:unevaluated-string "5.13.6Unevaluated strings[lex.string.uneval]") indicates the required language linkage[.](#2.sentence-2)
[*Note [2](#note-2)*:
Escape sequences and [*universal-character-name*](lex.universal.char#nt:universal-character-name "5.3.2Universal character names[lex.universal.char]")*s* have been replaced ([[lex.string.uneval]](lex.string.uneval "5.13.6Unevaluated strings"))[.](#2.sentence-3)
— *end note*]
This document specifies the semantics for the[*unevaluated-string*](lex.string.uneval#nt:unevaluated-string "5.13.6Unevaluated strings[lex.string.uneval]")*s* "C" and "C++"[.](#2.sentence-4)
Use of an [*unevaluated-string*](lex.string.uneval#nt:unevaluated-string "5.13.6Unevaluated strings[lex.string.uneval]") other than "C" or "C++" is conditionally-supported,
with implementation-defined semantics[.](#2.sentence-5)
[*Note [3](#note-3)*:
Therefore, a [*linkage-specification*](#nt:linkage-specification "9.12Linkage specifications[dcl.link]") with a language linkage
that is unknown to the implementation requires a diagnostic[.](#2.sentence-6)
— *end note*]
*Recommended practice*: The spelling of the language linkage should be taken
from the document defining that language[.](#2.sentence-7)
For example, Ada (not ADA) andFortran or FORTRAN, depending on the vintage[.](#2.sentence-8)
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L9175)
Every implementation shall provide for linkage to the C programming language,"C", and C++, "C++"[.](#3.sentence-1)
[*Example [1](#example-1)*: complex sqrt(complex); // C++ language linkage by defaultextern "C" {double sqrt(double); // C language linkage} — *end example*]
[4](#4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L9189)
A [*module-import-declaration*](module.import#nt:module-import-declaration "10.3Import declaration[module.import]") appearing in
a linkage specification with other than C++ language linkage
is conditionally-supported withimplementation-defined semantics[.](#4.sentence-1)
[5](#5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L9196)
Linkage specifications nest[.](#5.sentence-1)
When linkage specifications nest, the
innermost one determines the language linkage[.](#5.sentence-2)
[*Note [4](#note-4)*:
A linkage specification does not establish a scope[.](#5.sentence-3)
— *end note*]
A [*linkage-specification*](#nt:linkage-specification "9.12Linkage specifications[dcl.link]") shall inhabit a namespace scope[.](#5.sentence-4)
In a [*linkage-specification*](#nt:linkage-specification "9.12Linkage specifications[dcl.link]"),
the specified language linkage applies
to the function types of all function declarators and
to all functions and variables whose names have external linkage[.](#5.sentence-5)
[*Example [2](#example-2)*: extern "C" // f1 and its function type have C language linkage;void f1(void(*pf)(int)); // pf is a pointer to a C functionextern "C" typedef void FUNC();
FUNC f2; // f2 has C++ language linkage and// its type has C language linkageextern "C" FUNC f3; // f3 and its type have C language linkagevoid (*pf2)(FUNC*); // the variable pf2 has C++ language linkage; its type// is “pointer to C++ function that takes one parameter of type// pointer to C function''extern "C" {static void f4(); // the name of the function f4 has internal linkage,// so f4 has no language linkage; its type has C language linkage}extern "C" void f5() {extern void f4(); // OK, name linkage (internal) and function type linkage (C language linkage)// obtained from previous declaration.}extern void f4(); // OK, name linkage (internal) and function type linkage (C language linkage)// obtained from previous declaration.void f6() {extern void f4(); // OK, name linkage (internal) and function type linkage (C language linkage)// obtained from previous declaration.} — *end example*]
A C language linkage is ignored
in determining the language linkage of
class members,
friend functions with a trailing [*requires-clause*](temp.pre#nt:requires-clause "13.1Preamble[temp.pre]"), and the
function type of non-static class member functions[.](#5.sentence-6)
[*Example [3](#example-3)*: extern "C" typedef void FUNC_c();
class C {void mf1(FUNC_c*); // the function mf1 and its type have C++ language linkage;// the parameter has type “pointer to C function'' FUNC_c mf2; // the function mf2 and its type have C++ language linkagestatic FUNC_c* q; // the data member q has C++ language linkage;// its type is “pointer to C function''};
extern "C" {class X {void mf(); // the function mf and its type have C++ language linkagevoid mf2(void(*)()); // the function mf2 has C++ language linkage;// the parameter has type “pointer to C function''};} — *end example*]
[6](#6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L9271)
If two declarations of an entity give it different language linkages, the
program is ill-formed; no diagnostic is required if neither declaration
is reachable from the other[.](#6.sentence-1)
A redeclaration of an entity without a linkage specification
inherits the language linkage of the entity and (if applicable) its type[.](#6.sentence-2)
[7](#7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L9279)
Two declarations declare the same entity
if they (re)introduce the same name,
one declares a function or variable with C language linkage,
and the other declares such an entity or declares a variable
that belongs to the global scope[.](#7.sentence-1)
[*Example [4](#example-4)*: int x;namespace A {extern "C" int f(); extern "C" int g() { return 1; }extern "C" int h(); extern "C" int x(); // error: same name as global-space object x}namespace B {extern "C" int f(); // A::f and B::f refer to the same functionextern "C" int g() { return 1; } // error: the function g with C language linkage has two definitions}int A::f() { return 98; } // definition for the function f with C language linkageextern "C" int h() { return 97; } // definition for the function h with C language linkage// A::h and ::h refer to the same function — *end example*]
[8](#8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L9307)
A declaration directly contained in a[*linkage-specification*](#nt:linkage-specification "9.12Linkage specifications[dcl.link]") is treated as if it contains theextern specifier ([[dcl.stc]](dcl.stc "9.2.2Storage class specifiers")) for the purpose of determining the linkage of the
declared name and whether it is a definition[.](#8.sentence-1)
Such a declaration shall
not have a [*storage-class-specifier*](dcl.stc#nt:storage-class-specifier "9.2.2Storage class specifiers[dcl.stc]")[.](#8.sentence-2)
[*Example [5](#example-5)*: extern "C" double f();static double f(); // errorextern "C" int i; // declarationextern "C" {int i; // definition}extern "C" static void g(); // error — *end example*]
[9](#9)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L9327)
[*Note [5](#note-5)*:
Because the language linkage is part of a function type, when
indirecting through a pointer to C function, the function to
which the resulting lvalue refers is considered a C function[.](#9.sentence-1)
— *end note*]
[10](#10)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L9334)
Linkage from C++ to entities defined in other languages and to entities
defined in C++ from other languages is implementation-defined and
language-dependent[.](#10.sentence-1)
Only where the object layout strategies of two
language implementations are similar enough can such linkage be
achieved[.](#10.sentence-2)

1520
cppdraft/dcl/meaning.md Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,185 @@
[dcl.meaning.general]
# 9 Declarations [[dcl]](./#dcl)
## 9.3 Declarators [[dcl.decl]](dcl.decl#dcl.meaning.general)
### 9.3.4 Meaning of declarators [[dcl.meaning]](dcl.meaning#general)
#### 9.3.4.1 General [dcl.meaning.general]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L2782)
A declarator contains exactly one [*declarator-id*](dcl.decl.general#nt:declarator-id "9.3.1General[dcl.decl.general]");
it names the entity that is declared[.](#1.sentence-1)
If the [*unqualified-id*](expr.prim.id.unqual#nt:unqualified-id "7.5.5.2Unqualified names[expr.prim.id.unqual]") occurring in a [*declarator-id*](dcl.decl.general#nt:declarator-id "9.3.1General[dcl.decl.general]") is a [*template-id*](temp.names#nt:template-id "13.3Names of template specializations[temp.names]"),
the declarator shall appear in the [*declaration*](dcl.pre#nt:declaration "9.1Preamble[dcl.pre]") of a[*template-declaration*](temp.pre#nt:template-declaration "13.1Preamble[temp.pre]") ([[temp.decls]](temp.decls "13.7Template declarations")),[*explicit-specialization*](temp.expl.spec#nt:explicit-specialization "13.9.4Explicit specialization[temp.expl.spec]") ([[temp.expl.spec]](temp.expl.spec "13.9.4Explicit specialization")), or[*explicit-instantiation*](temp.explicit#nt:explicit-instantiation "13.9.3Explicit instantiation[temp.explicit]") ([[temp.explicit]](temp.explicit "13.9.3Explicit instantiation"))[.](#1.sentence-2)
[*Note [1](#note-1)*:
An [*unqualified-id*](expr.prim.id.unqual#nt:unqualified-id "7.5.5.2Unqualified names[expr.prim.id.unqual]") that is not an [*identifier*](lex.name#nt:identifier "5.11Identifiers[lex.name]") is used to declare
certain functions ([[class.conv.fct]](class.conv.fct "11.4.8.3Conversion functions"), [[class.dtor]](class.dtor "11.4.7Destructors"), [[over.oper]](over.oper "12.4Overloaded operators"), [[over.literal]](over.literal "12.6User-defined literals"))[.](#1.sentence-3)
— *end note*]
The optional [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") following a [*declarator-id*](dcl.decl.general#nt:declarator-id "9.3.1General[dcl.decl.general]") appertains to the entity that is declared[.](#1.sentence-4)
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L2799)
If the declaration is a friend declaration:
- [(2.1)](#2.1)
The [*declarator*](dcl.decl.general#nt:declarator "9.3.1General[dcl.decl.general]") does not bind a name[.](#2.1.sentence-1)
- [(2.2)](#2.2)
If the [*id-expression*](expr.prim.id.general#nt:id-expression "7.5.5.1General[expr.prim.id.general]") E in
the [*declarator-id*](dcl.decl.general#nt:declarator-id "9.3.1General[dcl.decl.general]") of the [*declarator*](dcl.decl.general#nt:declarator "9.3.1General[dcl.decl.general]") is
a [*qualified-id*](expr.prim.id.qual#nt:qualified-id "7.5.5.3Qualified names[expr.prim.id.qual]") or a [*template-id*](temp.names#nt:template-id "13.3Names of template specializations[temp.names]"):
* [(2.2.1)](#2.2.1)
If the friend declaration is not a template declaration,
then in the lookup for the terminal name of E:
+
[(2.2.1.1)](#2.2.1.1)
if the [*unqualified-id*](expr.prim.id.unqual#nt:unqualified-id "7.5.5.2Unqualified names[expr.prim.id.unqual]") in E is a [*template-id*](temp.names#nt:template-id "13.3Names of template specializations[temp.names]"),
all function declarations are discarded;
+
[(2.2.1.2)](#2.2.1.2)
otherwise,
if the [*declarator*](dcl.decl.general#nt:declarator "9.3.1General[dcl.decl.general]") corresponds ([[basic.scope.scope]](basic.scope.scope "6.4.1General")) to
any declaration found of a non-template function,
all function template declarations are discarded;
+
[(2.2.1.3)](#2.2.1.3)
each remaining function template is replaced with the specialization chosen by
deduction from the friend declaration ([[temp.deduct.decl]](temp.deduct.decl "13.10.3.7Deducing template arguments from a function declaration")) or
discarded if deduction fails[.](#2.2.1.sentence-1)
* [(2.2.2)](#2.2.2)
The [*declarator*](dcl.decl.general#nt:declarator "9.3.1General[dcl.decl.general]") shall correspond to
one or more declarations found by the lookup;
they shall all have the same target scope, and
the target scope of the [*declarator*](dcl.decl.general#nt:declarator "9.3.1General[dcl.decl.general]") is that scope[.](#2.2.2.sentence-1)
- [(2.3)](#2.3)
Otherwise, the terminal name of E is not looked up[.](#2.3.sentence-1)
The declaration's target scope is the innermost enclosing namespace scope;
if the declaration is contained by a block scope,
the declaration shall correspond to a reachable ([[module.reach]](module.reach "10.7Reachability")) declaration
that inhabits the innermost block scope[.](#2.3.sentence-2)
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L2840)
Otherwise:
- [(3.1)](#3.1)
If the [*id-expression*](expr.prim.id.general#nt:id-expression "7.5.5.1General[expr.prim.id.general]") in
the [*declarator-id*](dcl.decl.general#nt:declarator-id "9.3.1General[dcl.decl.general]") of the [*declarator*](dcl.decl.general#nt:declarator "9.3.1General[dcl.decl.general]") is
a [*qualified-id*](expr.prim.id.qual#nt:qualified-id "7.5.5.3Qualified names[expr.prim.id.qual]") Q,
let S be its lookup context ([[basic.lookup.qual]](basic.lookup.qual "6.5.5Qualified name lookup"));
the declaration shall inhabit a namespace scope[.](#3.1.sentence-1)
- [(3.2)](#3.2)
Otherwise, let S be the entity associated with the scope inhabited by
the [*declarator*](dcl.decl.general#nt:declarator "9.3.1General[dcl.decl.general]")[.](#3.2.sentence-1)
- [(3.3)](#3.3)
If the [*declarator*](dcl.decl.general#nt:declarator "9.3.1General[dcl.decl.general]") declares
an explicit instantiation or a partial or explicit specialization,
the [*declarator*](dcl.decl.general#nt:declarator "9.3.1General[dcl.decl.general]") does not bind a name[.](#3.3.sentence-1)
If it declares a class member,
the terminal name of the [*declarator-id*](dcl.decl.general#nt:declarator-id "9.3.1General[dcl.decl.general]") is not looked up;
otherwise, only those lookup results that are nominable in S are considered when identifying
any function template specialization being declared ([[temp.deduct.decl]](temp.deduct.decl "13.10.3.7Deducing template arguments from a function declaration"))[.](#3.3.sentence-2)
[*Example [1](#example-1)*: namespace N {inline namespace O {template<class T> void f(T); // #1template<class T> void g(T) {}}namespace P {template<class T> void f(T*); // #2, more specialized than #1template<class> int g; }using P::f,P::g;}template<> void N::f(int*) {} // OK, #2 is not nominabletemplate void N::g(int); // error: lookup is ambiguous — *end example*]
- [(3.4)](#3.4)
Otherwise,
the terminal name of the [*declarator-id*](dcl.decl.general#nt:declarator-id "9.3.1General[dcl.decl.general]") is not looked up[.](#3.4.sentence-1)
If it is a qualified name,
the [*declarator*](dcl.decl.general#nt:declarator "9.3.1General[dcl.decl.general]") shall correspond to
one or more declarations nominable in S;
all the declarations shall have the same target scope and
the target scope of the [*declarator*](dcl.decl.general#nt:declarator "9.3.1General[dcl.decl.general]") is that scope[.](#3.4.sentence-2)
[*Example [2](#example-2)*: namespace Q {namespace V {void f(); }void V::f() { /* ... */ } // OKvoid V::g() { /* ... */ } // error: g() is not yet a member of Vnamespace V {void g(); }}namespace R {void Q::V::g() { /* ... */ } // error: R doesn't enclose Q} — *end example*]
- [(3.5)](#3.5)
If the declaration inhabits a block scope S and
declares a function ([[dcl.fct]](dcl.fct "9.3.4.6Functions")) or uses the extern specifier,
the declaration shall not be attached to a named module ([[module.unit]](module.unit "10.1Module units and purviews"));
its target scope is the innermost enclosing namespace scope,
but the name is bound in S[.](#3.5.sentence-1)
[*Example [3](#example-3)*: namespace X {void p() { q(); // error: q not yet declaredextern void q(); // q is a member of namespace Xextern void r(); // r is a member of namespace X}void middle() { q(); // error: q not found}void q() { /* ... */ } // definition of X::q}void q() { /* ... */ } // some other, unrelated qvoid X::r() { /* ... */ } // error: r cannot be declared by [*qualified-id*](expr.prim.id.qual#nt:qualified-id "7.5.5.3Qualified names[expr.prim.id.qual]") — *end example*]
[4](#4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L2932)
Astatic,thread_local,extern,mutable,friend,inline,virtual,constexpr,consteval,constinit,
ortypedef specifier
or an [*explicit-specifier*](dcl.fct.spec#nt:explicit-specifier "9.2.3Function specifiers[dcl.fct.spec]") applies directly to each [*declarator-id*](dcl.decl.general#nt:declarator-id "9.3.1General[dcl.decl.general]") in a declaration;
the type specified for each [*declarator-id*](dcl.decl.general#nt:declarator-id "9.3.1General[dcl.decl.general]") depends on
both the [*decl-specifier-seq*](dcl.spec.general#nt:decl-specifier-seq "9.2.1General[dcl.spec.general]") and its [*declarator*](dcl.decl.general#nt:declarator "9.3.1General[dcl.decl.general]")[.](#4.sentence-1)
[5](#5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L2953)
Thus, (for each [*declarator*](dcl.decl.general#nt:declarator "9.3.1General[dcl.decl.general]")) a declaration has the formT D whereT is of the form [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1Attribute syntax and semantics[dcl.attr.grammar]")opt[*decl-specifier-seq*](dcl.spec.general#nt:decl-specifier-seq "9.2.1General[dcl.spec.general]") andD is a declarator[.](#5.sentence-1)
Following is a recursive procedure for determining
the type specified for the contained[*declarator-id*](dcl.decl.general#nt:declarator-id "9.3.1General[dcl.decl.general]") by such a declaration[.](#5.sentence-2)
[6](#6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L2970)
First, the[*decl-specifier-seq*](dcl.spec.general#nt:decl-specifier-seq "9.2.1General[dcl.spec.general]") determines a type[.](#6.sentence-1)
In a declarationT D the[*decl-specifier-seq*](dcl.spec.general#nt:decl-specifier-seq "9.2.1General[dcl.spec.general]")T determines the typeT[.](#6.sentence-2)
[*Example [4](#example-4)*:
In the declarationint unsigned i; the type specifiersintunsigned determine the type
“unsigned int” ([[dcl.type.simple]](dcl.type.simple "9.2.9.3Simple type specifiers"))[.](#6.sentence-3)
— *end example*]
[7](#7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L2995)
In a declaration[*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1Attribute syntax and semantics[dcl.attr.grammar]")optTD whereD is an unadorned [*declarator-id*](dcl.decl.general#nt:declarator-id "9.3.1General[dcl.decl.general]"),
the type of the declared entity is
“€[.](#7.sentence-1)
[8](#8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L3006)
In a declarationTD whereD has the form
( D1 )
the type of the contained[*declarator-id*](dcl.decl.general#nt:declarator-id "9.3.1General[dcl.decl.general]") is the same as that of the contained[*declarator-id*](dcl.decl.general#nt:declarator-id "9.3.1General[dcl.decl.general]") in the declarationT D1
Parentheses do not alter the type of the embedded[*declarator-id*](dcl.decl.general#nt:declarator-id "9.3.1General[dcl.decl.general]"),
but they can alter the binding of complex declarators[.](#8.sentence-2)

79
cppdraft/dcl/mptr.md Normal file
View File

@@ -0,0 +1,79 @@
[dcl.mptr]
# 9 Declarations [[dcl]](./#dcl)
## 9.3 Declarators [[dcl.decl]](dcl.decl#dcl.mptr)
### 9.3.4 Meaning of declarators [[dcl.meaning]](dcl.meaning#dcl.mptr)
#### 9.3.4.4 Pointers to members [dcl.mptr]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L3354)
The component names of a [*ptr-operator*](dcl.decl.general#nt:ptr-operator "9.3.1General[dcl.decl.general]") are
those of its [*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3Qualified names[expr.prim.id.qual]"), if any[.](#1.sentence-1)
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L3359)
In a declarationTD whereD has the form
[*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3Qualified names[expr.prim.id.qual]") * [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1Attribute syntax and semantics[dcl.attr.grammar]")opt [*cv-qualifier-seq*](dcl.decl.general#nt:cv-qualifier-seq "9.3.1General[dcl.decl.general]")opt D1
and the[*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3Qualified names[expr.prim.id.qual]") designates a class,
and the type of the contained [*declarator-id*](dcl.decl.general#nt:declarator-id "9.3.1General[dcl.decl.general]") in the declarationTD1 is “*derived-declarator-type-list*T”,
the type of the [*declarator-id*](dcl.decl.general#nt:declarator-id "9.3.1General[dcl.decl.general]") inD is “*derived-declarator-type-list* [*cv-qualifier-seq*](dcl.decl.general#nt:cv-qualifier-seq "9.3.1General[dcl.decl.general]") pointer to member of class[*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3Qualified names[expr.prim.id.qual]") of typeT”[.](#2.sentence-1)
The optional [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") ([[dcl.attr.grammar]](dcl.attr.grammar "9.13.1Attribute syntax and semantics")) appertains to the
pointer-to-member[.](#2.sentence-2)
The [*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3Qualified names[expr.prim.id.qual]") shall not designate an anonymous union[.](#2.sentence-3)
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L3386)
[*Example [1](#example-1)*:
struct X {void f(int); int a;};struct Y;
int X::* pmi = &X::a;void (X::* pmf)(int) = &X::f;double X::* pmd;char Y::* pmc; declarespmi,pmf,pmd andpmc to be a pointer to a member ofX of typeint,
a pointer to a member ofX of typevoid(int),
a pointer to a member ofX of typedouble and a pointer to a member ofY of typechar respectively[.](#3.sentence-1)
The declaration ofpmd is well-formed even thoughX has no members of typedouble[.](#3.sentence-2)
Similarly, the declaration ofpmc is well-formed even thoughY is an incomplete type[.](#3.sentence-3)
pmi andpmf can be used like this:X obj;// ... obj.*pmi = 7; // assign 7 to an integer member of obj(obj.*pmf)(7); // call a function member of obj with the argument 7
— *end example*]
[4](#4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L3446)
A pointer to member shall not point to a static member
of a class ([[class.static]](class.static "11.4.9Static members")),
a member with reference type,
or
“cv void”[.](#4.sentence-1)
[5](#5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L3453)
[*Note [1](#note-1)*:
See also [[expr.unary]](expr.unary "7.6.2Unary expressions") and [[expr.mptr.oper]](expr.mptr.oper "7.6.4Pointer-to-member operators")[.](#5.sentence-1)
The type “pointer to member” is distinct from the type “pointer”,
that is, a pointer to member is declared only by the pointer-to-member
declarator syntax, and never by the pointer declarator syntax[.](#5.sentence-2)
There is no “reference-to-member” type in C++[.](#5.sentence-3)
— *end note*]

79
cppdraft/dcl/name.md Normal file
View File

@@ -0,0 +1,79 @@
[dcl.name]
# 9 Declarations [[dcl]](./#dcl)
## 9.3 Declarators [[dcl.decl]](dcl.decl#dcl.name)
### 9.3.2 Type names [dcl.name]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L2557)
To specify type conversions explicitly,and as an argument ofsizeof,alignof,new,
ortypeid,
the name of a type shall be specified[.](#1.sentence-1)
This can be done with a[*type-id*](#nt:type-id "9.3.2Type names[dcl.name]") or [*new-type-id*](expr.new#nt:new-type-id "7.6.2.8New[expr.new]") ([[expr.new]](expr.new "7.6.2.8New")),
which is syntactically a declaration for a variable or function
of that type that omits the name of the entity[.](#1.sentence-2)
[type-id:](#nt:type-id "9.3.2Type names[dcl.name]")
[*type-specifier-seq*](dcl.type.general#nt:type-specifier-seq "9.2.9.1General[dcl.type.general]") [*abstract-declarator*](#nt:abstract-declarator "9.3.2Type names[dcl.name]")opt
[defining-type-id:](#nt:defining-type-id "9.3.2Type names[dcl.name]")
[*defining-type-specifier-seq*](dcl.type.general#nt:defining-type-specifier-seq "9.2.9.1General[dcl.type.general]") [*abstract-declarator*](#nt:abstract-declarator "9.3.2Type names[dcl.name]")opt
[abstract-declarator:](#nt:abstract-declarator "9.3.2Type names[dcl.name]")
[*ptr-abstract-declarator*](#nt:ptr-abstract-declarator "9.3.2Type names[dcl.name]")
[*noptr-abstract-declarator*](#nt:noptr-abstract-declarator "9.3.2Type names[dcl.name]")opt [*parameters-and-qualifiers*](dcl.decl.general#nt:parameters-and-qualifiers "9.3.1General[dcl.decl.general]") [*trailing-return-type*](dcl.decl.general#nt:trailing-return-type "9.3.1General[dcl.decl.general]")
[*abstract-pack-declarator*](#nt:abstract-pack-declarator "9.3.2Type names[dcl.name]")
[ptr-abstract-declarator:](#nt:ptr-abstract-declarator "9.3.2Type names[dcl.name]")
[*noptr-abstract-declarator*](#nt:noptr-abstract-declarator "9.3.2Type names[dcl.name]")
[*ptr-operator*](dcl.decl.general#nt:ptr-operator "9.3.1General[dcl.decl.general]") [*ptr-abstract-declarator*](#nt:ptr-abstract-declarator "9.3.2Type names[dcl.name]")opt
[noptr-abstract-declarator:](#nt:noptr-abstract-declarator "9.3.2Type names[dcl.name]")
[*noptr-abstract-declarator*](#nt:noptr-abstract-declarator "9.3.2Type names[dcl.name]")opt [*parameters-and-qualifiers*](dcl.decl.general#nt:parameters-and-qualifiers "9.3.1General[dcl.decl.general]")
[*noptr-abstract-declarator*](#nt:noptr-abstract-declarator "9.3.2Type names[dcl.name]")opt [ [*constant-expression*](expr.const#nt:constant-expression "7.7Constant expressions[expr.const]")opt ] [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1Attribute syntax and semantics[dcl.attr.grammar]")opt
( [*ptr-abstract-declarator*](#nt:ptr-abstract-declarator "9.3.2Type names[dcl.name]") )
[abstract-pack-declarator:](#nt:abstract-pack-declarator "9.3.2Type names[dcl.name]")
[*noptr-abstract-pack-declarator*](#nt:noptr-abstract-pack-declarator "9.3.2Type names[dcl.name]")
[*ptr-operator*](dcl.decl.general#nt:ptr-operator "9.3.1General[dcl.decl.general]") [*abstract-pack-declarator*](#nt:abstract-pack-declarator "9.3.2Type names[dcl.name]")
[noptr-abstract-pack-declarator:](#nt:noptr-abstract-pack-declarator "9.3.2Type names[dcl.name]")
[*noptr-abstract-pack-declarator*](#nt:noptr-abstract-pack-declarator "9.3.2Type names[dcl.name]") [*parameters-and-qualifiers*](dcl.decl.general#nt:parameters-and-qualifiers "9.3.1General[dcl.decl.general]")
...
It is possible to identify uniquely the location in the[*abstract-declarator*](#nt:abstract-declarator "9.3.2Type names[dcl.name]") where the identifier would appear if the construction were a declarator
in a declaration[.](#1.sentence-3)
The named type is then the same as the type of the
hypothetical identifier[.](#1.sentence-4)
[*Example [1](#example-1)*:
int // int iint * // int *piint *[3] // int *p[3]int (*)[3] // int (*p3i)[3]int *() // int *f()int (*)(double) // int (*pf)(double) name respectively the types
“int”,
“pointer toint”,
“array of 3 pointers toint”,
“pointer to array of 3int”,
“function of (no parameters) returning pointer toint”,
and “pointer to a function of
(double)
returningint”[.](#1.sentence-5)
— *end example*]
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L2646)
[*Note [1](#note-1)*:
A type can also be named by a [*typedef-name*](dcl.typedef#nt:typedef-name "9.2.4The typedef specifier[dcl.typedef]"),
which is introduced by a typedef declaration
or [*alias-declaration*](dcl.pre#nt:alias-declaration "9.1Preamble[dcl.pre]") ([[dcl.typedef]](dcl.typedef "9.2.4The typedef specifier"))[.](#2.sentence-1)
— *end note*]

390
cppdraft/dcl/pre.md Normal file
View File

@@ -0,0 +1,390 @@
[dcl.pre]
# 9 Declarations [[dcl]](./#dcl)
## 9.1 Preamble [dcl.pre]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L11)
Declarations generally specify how names are to be interpreted[.](#1.sentence-1)
Declarations have
the form
[declaration-seq:](#nt:declaration-seq "9.1Preamble[dcl.pre]")
[*declaration*](#nt:declaration "9.1Preamble[dcl.pre]") [*declaration-seq*](#nt:declaration-seq "9.1Preamble[dcl.pre]")opt
[declaration:](#nt:declaration "9.1Preamble[dcl.pre]")
[*name-declaration*](#nt:name-declaration "9.1Preamble[dcl.pre]")
[*special-declaration*](#nt:special-declaration "9.1Preamble[dcl.pre]")
[name-declaration:](#nt:name-declaration "9.1Preamble[dcl.pre]")
[*block-declaration*](#nt:block-declaration "9.1Preamble[dcl.pre]")
[*nodeclspec-function-declaration*](#nt:nodeclspec-function-declaration "9.1Preamble[dcl.pre]")
[*function-definition*](dcl.fct.def.general#nt:function-definition "9.6.1General[dcl.fct.def.general]")
[*friend-type-declaration*](class.mem.general#nt:friend-type-declaration "11.4.1General[class.mem.general]")
[*template-declaration*](temp.pre#nt:template-declaration "13.1Preamble[temp.pre]")
[*deduction-guide*](temp.deduct.guide#nt:deduction-guide "13.7.2.3Deduction guides[temp.deduct.guide]")
[*linkage-specification*](dcl.link#nt:linkage-specification "9.12Linkage specifications[dcl.link]")
[*namespace-definition*](namespace.def.general#nt:namespace-definition "9.9.2.1General[namespace.def.general]")
[*empty-declaration*](#nt:empty-declaration "9.1Preamble[dcl.pre]")
[*attribute-declaration*](#nt:attribute-declaration "9.1Preamble[dcl.pre]")
[*module-import-declaration*](module.import#nt:module-import-declaration "10.3Import declaration[module.import]")
[special-declaration:](#nt:special-declaration "9.1Preamble[dcl.pre]")
[*explicit-instantiation*](temp.explicit#nt:explicit-instantiation "13.9.3Explicit instantiation[temp.explicit]")
[*explicit-specialization*](temp.expl.spec#nt:explicit-specialization "13.9.4Explicit specialization[temp.expl.spec]")
[*export-declaration*](module.interface#nt:export-declaration "10.2Export declaration[module.interface]")
[block-declaration:](#nt:block-declaration "9.1Preamble[dcl.pre]")
[*simple-declaration*](#nt:simple-declaration "9.1Preamble[dcl.pre]")
[*asm-declaration*](dcl.asm#nt:asm-declaration "9.11The asm declaration[dcl.asm]")
[*namespace-alias-definition*](namespace.alias#nt:namespace-alias-definition "9.9.3Namespace alias[namespace.alias]")
[*using-declaration*](namespace.udecl#nt:using-declaration "9.10The using declaration[namespace.udecl]")
[*using-enum-declaration*](enum.udecl#nt:using-enum-declaration "9.8.2The using enum declaration[enum.udecl]")
[*using-directive*](namespace.udir#nt:using-directive "9.9.4Using namespace directive[namespace.udir]")
[*static_assert-declaration*](#nt:static_assert-declaration "9.1Preamble[dcl.pre]")
[*consteval-block-declaration*](#nt:consteval-block-declaration "9.1Preamble[dcl.pre]")
[*alias-declaration*](#nt:alias-declaration "9.1Preamble[dcl.pre]")
[*opaque-enum-declaration*](dcl.enum#nt:opaque-enum-declaration "9.8.1Enumeration declarations[dcl.enum]")
[nodeclspec-function-declaration:](#nt:nodeclspec-function-declaration "9.1Preamble[dcl.pre]")
[*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1Attribute syntax and semantics[dcl.attr.grammar]")opt [*declarator*](dcl.decl.general#nt:declarator "9.3.1General[dcl.decl.general]") ;
[alias-declaration:](#nt:alias-declaration "9.1Preamble[dcl.pre]")
using [*identifier*](lex.name#nt:identifier "5.11Identifiers[lex.name]") [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1Attribute syntax and semantics[dcl.attr.grammar]")opt = [*defining-type-id*](dcl.name#nt:defining-type-id "9.3.2Type names[dcl.name]") ;
[sb-identifier:](#nt:sb-identifier "9.1Preamble[dcl.pre]")
...opt [*identifier*](lex.name#nt:identifier "5.11Identifiers[lex.name]") [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1Attribute syntax and semantics[dcl.attr.grammar]")opt
[sb-identifier-list:](#nt:sb-identifier-list "9.1Preamble[dcl.pre]")
[*sb-identifier*](#nt:sb-identifier "9.1Preamble[dcl.pre]")
[*sb-identifier-list*](#nt:sb-identifier-list "9.1Preamble[dcl.pre]") , [*sb-identifier*](#nt:sb-identifier "9.1Preamble[dcl.pre]")
[structured-binding-declaration:](#nt:structured-binding-declaration "9.1Preamble[dcl.pre]")
[*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1Attribute syntax and semantics[dcl.attr.grammar]")opt [*decl-specifier-seq*](dcl.spec.general#nt:decl-specifier-seq "9.2.1General[dcl.spec.general]") [*ref-qualifier*](dcl.decl.general#nt:ref-qualifier "9.3.1General[dcl.decl.general]")opt [ [*sb-identifier-list*](#nt:sb-identifier-list "9.1Preamble[dcl.pre]") ]
[simple-declaration:](#nt:simple-declaration "9.1Preamble[dcl.pre]")
[*decl-specifier-seq*](dcl.spec.general#nt:decl-specifier-seq "9.2.1General[dcl.spec.general]") [*init-declarator-list*](dcl.decl.general#nt:init-declarator-list "9.3.1General[dcl.decl.general]")opt ;
[*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") [*decl-specifier-seq*](dcl.spec.general#nt:decl-specifier-seq "9.2.1General[dcl.spec.general]") [*init-declarator-list*](dcl.decl.general#nt:init-declarator-list "9.3.1General[dcl.decl.general]") ;
[*structured-binding-declaration*](#nt:structured-binding-declaration "9.1Preamble[dcl.pre]") [*initializer*](dcl.init.general#nt:initializer "9.5.1General[dcl.init.general]") ;
[static_assert-message:](#nt:static_assert-message "9.1Preamble[dcl.pre]")
[*unevaluated-string*](lex.string.uneval#nt:unevaluated-string "5.13.6Unevaluated strings[lex.string.uneval]")
[*constant-expression*](expr.const#nt:constant-expression "7.7Constant expressions[expr.const]")
[static_assert-declaration:](#nt:static_assert-declaration "9.1Preamble[dcl.pre]")
static_assert ( [*constant-expression*](expr.const#nt:constant-expression "7.7Constant expressions[expr.const]") ) ;
static_assert ( [*constant-expression*](expr.const#nt:constant-expression "7.7Constant expressions[expr.const]") , [*static_assert-message*](#nt:static_assert-message "9.1Preamble[dcl.pre]") ) ;
[consteval-block-declaration:](#nt:consteval-block-declaration "9.1Preamble[dcl.pre]")
consteval [*compound-statement*](stmt.block#nt:compound-statement "8.4Compound statement or block[stmt.block]")
[empty-declaration:](#nt:empty-declaration "9.1Preamble[dcl.pre]")
;
[attribute-declaration:](#nt:attribute-declaration "9.1Preamble[dcl.pre]")
[*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") ;
[*Note [1](#note-1)*:
[*asm-declaration*](dcl.asm#nt:asm-declaration "9.11The asm declaration[dcl.asm]")*s* are described in [[dcl.asm]](dcl.asm "9.11The asm declaration"), and[*linkage-specification*](dcl.link#nt:linkage-specification "9.12Linkage specifications[dcl.link]")*s* are described in [[dcl.link]](dcl.link "9.12Linkage specifications");[*function-definition*](dcl.fct.def.general#nt:function-definition "9.6.1General[dcl.fct.def.general]")*s* are described in [[dcl.fct.def]](dcl.fct.def "9.6Function definitions") and[*template-declaration*](temp.pre#nt:template-declaration "13.1Preamble[temp.pre]")*s* and[*deduction-guide*](temp.deduct.guide#nt:deduction-guide "13.7.2.3Deduction guides[temp.deduct.guide]")*s* are described in [[temp.deduct.guide]](temp.deduct.guide "13.7.2.3Deduction guides");[*namespace-definition*](namespace.def.general#nt:namespace-definition "9.9.2.1General[namespace.def.general]")*s* are described in [[namespace.def]](namespace.def "9.9.2Namespace definition"),[*using-declaration*](namespace.udecl#nt:using-declaration "9.10The using declaration[namespace.udecl]")*s* are described in [[namespace.udecl]](namespace.udecl "9.10The using declaration") and[*using-directive*](namespace.udir#nt:using-directive "9.9.4Using namespace directive[namespace.udir]")*s* are described in [[namespace.udir]](namespace.udir "9.9.4Using namespace directive")[.](#1.sentence-3)
— *end note*]
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L132)
Certain declarations contain one or more scopes ([[basic.scope.scope]](basic.scope.scope "6.4.1General"))[.](#2.sentence-1)
Unless otherwise stated, utterances in[[dcl]](dcl "9Declarations") about components in, of, or contained by a
declaration or subcomponent thereof refer only to those components of
the declaration that are not nested within scopes nested within
the declaration[.](#2.sentence-2)
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L142)
If a [*name-declaration*](#nt:name-declaration "9.1Preamble[dcl.pre]") matches
the syntactic requirements of [*friend-type-declaration*](class.mem.general#nt:friend-type-declaration "11.4.1General[class.mem.general]"),
it is a [*friend-type-declaration*](class.mem.general#nt:friend-type-declaration "11.4.1General[class.mem.general]")[.](#3.sentence-1)
[4](#4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L147)
A[*simple-declaration*](#nt:simple-declaration "9.1Preamble[dcl.pre]") or[*nodeclspec-function-declaration*](#nt:nodeclspec-function-declaration "9.1Preamble[dcl.pre]") of the form
[*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1Attribute syntax and semantics[dcl.attr.grammar]")opt [*decl-specifier-seq*](dcl.spec.general#nt:decl-specifier-seq "9.2.1General[dcl.spec.general]")opt [*init-declarator-list*](dcl.decl.general#nt:init-declarator-list "9.3.1General[dcl.decl.general]")opt ;
is divided into three parts[.](#4.sentence-1)
Attributes are described in [[dcl.attr]](dcl.attr "9.13Attributes")[.](#4.sentence-2)
[*decl-specifier*](dcl.spec.general#nt:decl-specifier "9.2.1General[dcl.spec.general]")*s*, the principal components of
a [*decl-specifier-seq*](dcl.spec.general#nt:decl-specifier-seq "9.2.1General[dcl.spec.general]"), are described in [[dcl.spec]](dcl.spec "9.2Specifiers")[.](#4.sentence-3)
[*declarator*](dcl.decl.general#nt:declarator "9.3.1General[dcl.decl.general]")*s*, the components of an[*init-declarator-list*](dcl.decl.general#nt:init-declarator-list "9.3.1General[dcl.decl.general]"), are described in [[dcl.decl]](dcl.decl "9.3Declarators")[.](#4.sentence-4)
The [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") appertains to each of the entities declared by
the [*declarator*](dcl.decl.general#nt:declarator "9.3.1General[dcl.decl.general]")*s* of the [*init-declarator-list*](dcl.decl.general#nt:init-declarator-list "9.3.1General[dcl.decl.general]")[.](#4.sentence-5)
[*Note [2](#note-2)*:
In the declaration for an entity, attributes appertaining to that
entity can appear at the start of the declaration and after the[*declarator-id*](dcl.decl.general#nt:declarator-id "9.3.1General[dcl.decl.general]") for that declaration[.](#4.sentence-6)
— *end note*]
[*Example [1](#example-1)*: [[noreturn]] void f [[noreturn]] (); // OK — *end example*]
[5](#5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L175)
If a [*declarator-id*](dcl.decl.general#nt:declarator-id "9.3.1General[dcl.decl.general]") is a name, the[*init-declarator*](dcl.decl.general#nt:init-declarator "9.3.1General[dcl.decl.general]") and (hence) the declaration introduce that name[.](#5.sentence-1)
[*Note [3](#note-3)*:
Otherwise, the [*declarator-id*](dcl.decl.general#nt:declarator-id "9.3.1General[dcl.decl.general]") is
a [*qualified-id*](expr.prim.id.qual#nt:qualified-id "7.5.5.3Qualified names[expr.prim.id.qual]") or
names a destructor or
its [*unqualified-id*](expr.prim.id.unqual#nt:unqualified-id "7.5.5.2Unqualified names[expr.prim.id.unqual]") is a [*template-id*](temp.names#nt:template-id "13.3Names of template specializations[temp.names]") and
no name is introduced[.](#5.sentence-2)
— *end note*]
The [*defining-type-specifier*](dcl.type.general#nt:defining-type-specifier "9.2.9.1General[dcl.type.general]")*s* ([[dcl.type]](dcl.type "9.2.9Type specifiers")) in
the [*decl-specifier-seq*](dcl.spec.general#nt:decl-specifier-seq "9.2.1General[dcl.spec.general]") and
the recursive [*declarator*](dcl.decl.general#nt:declarator "9.3.1General[dcl.decl.general]") structure
describe a type ([[dcl.meaning]](dcl.meaning "9.3.4Meaning of declarators")),
which is then associated with the [*declarator-id*](dcl.decl.general#nt:declarator-id "9.3.1General[dcl.decl.general]")[.](#5.sentence-3)
[6](#6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L191)
In a [*simple-declaration*](#nt:simple-declaration "9.1Preamble[dcl.pre]"), the optional[*init-declarator-list*](dcl.decl.general#nt:init-declarator-list "9.3.1General[dcl.decl.general]") can be omitted only when declaring a
class ([[class.pre]](class.pre "11.1Preamble")) or enumeration ([[dcl.enum]](dcl.enum "9.8.1Enumeration declarations")), that is,
when the [*decl-specifier-seq*](dcl.spec.general#nt:decl-specifier-seq "9.2.1General[dcl.spec.general]") contains either a[*class-specifier*](class.pre#nt:class-specifier "11.1Preamble[class.pre]"), an [*elaborated-type-specifier*](dcl.type.elab#nt:elaborated-type-specifier "9.2.9.5Elaborated type specifiers[dcl.type.elab]") with
a [*class-key*](class.pre#nt:class-key "11.1Preamble[class.pre]") ([[class.name]](class.name "11.3Class names")), or an[*enum-specifier*](dcl.enum#nt:enum-specifier "9.8.1Enumeration declarations[dcl.enum]")[.](#6.sentence-1)
In these cases and whenever a[*class-specifier*](class.pre#nt:class-specifier "11.1Preamble[class.pre]") or [*enum-specifier*](dcl.enum#nt:enum-specifier "9.8.1Enumeration declarations[dcl.enum]") is present in
the [*decl-specifier-seq*](dcl.spec.general#nt:decl-specifier-seq "9.2.1General[dcl.spec.general]"), the identifiers in these specifiers
are also declared (as[*class-name*](class.pre#nt:class-name "11.1Preamble[class.pre]")*s*, [*enum-name*](dcl.enum#nt:enum-name "9.8.1Enumeration declarations[dcl.enum]")*s*, or[*enumerator*](dcl.enum#nt:enumerator "9.8.1Enumeration declarations[dcl.enum]")*s*, depending on the syntax)[.](#6.sentence-2)
In such cases,
the [*decl-specifier-seq*](dcl.spec.general#nt:decl-specifier-seq "9.2.1General[dcl.spec.general]") shall (re)introduce one or more names into
the program[.](#6.sentence-3)
[*Example [2](#example-2)*: enum { }; // errortypedef class { }; // error — *end example*]
[7](#7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L215)
A [*simple-declaration*](#nt:simple-declaration "9.1Preamble[dcl.pre]") or a [*condition*](stmt.pre#nt:condition "8.1Preamble[stmt.pre]") with a [*structured-binding-declaration*](#nt:structured-binding-declaration "9.1Preamble[dcl.pre]") is called
a [*structured binding declaration*](#def:structured_binding_declaration "9.1Preamble[dcl.pre]") ([[dcl.struct.bind]](dcl.struct.bind "9.7Structured binding declarations"))[.](#7.sentence-1)
Each [*decl-specifier*](dcl.spec.general#nt:decl-specifier "9.2.1General[dcl.spec.general]") in the [*decl-specifier-seq*](dcl.spec.general#nt:decl-specifier-seq "9.2.1General[dcl.spec.general]") shall beconstexpr,constinit,static,thread_local,auto ([[dcl.spec.auto]](dcl.spec.auto "9.2.9.7Placeholder type specifiers")), or
a [*cv-qualifier*](dcl.decl.general#nt:cv-qualifier "9.3.1General[dcl.decl.general]")[.](#7.sentence-2)
The declaration shall contain at most one [*sb-identifier*](#nt:sb-identifier "9.1Preamble[dcl.pre]") whose [*identifier*](lex.name#nt:identifier "5.11Identifiers[lex.name]") is preceded by an ellipsis[.](#7.sentence-3)
If the declaration contains any such [*sb-identifier*](#nt:sb-identifier "9.1Preamble[dcl.pre]"),
it shall declare a templated entity ([[temp.pre]](temp.pre "13.1Preamble"))[.](#7.sentence-4)
[*Example [3](#example-3)*: template<class T> concept C = true;
C auto [x, y] = std::pair{1, 2}; // error: constrained [*placeholder-type-specifier*](dcl.spec.auto.general#nt:placeholder-type-specifier "9.2.9.7.1General[dcl.spec.auto.general]")// not permitted for structured bindings — *end example*]
The [*initializer*](dcl.init.general#nt:initializer "9.5.1General[dcl.init.general]") shall be
of the form “= [*assignment-expression*](expr.assign#nt:assignment-expression "7.6.19Assignment and compound assignment operators[expr.assign]")”,
of the form “{ [*assignment-expression*](expr.assign#nt:assignment-expression "7.6.19Assignment and compound assignment operators[expr.assign]") }”,
or
of the form “( [*assignment-expression*](expr.assign#nt:assignment-expression "7.6.19Assignment and compound assignment operators[expr.assign]") )”[.](#7.sentence-5)
If the [*structured-binding-declaration*](#nt:structured-binding-declaration "9.1Preamble[dcl.pre]") appears as
a [*condition*](stmt.pre#nt:condition "8.1Preamble[stmt.pre]"),
the [*assignment-expression*](expr.assign#nt:assignment-expression "7.6.19Assignment and compound assignment operators[expr.assign]") shall be of non-union class type[.](#7.sentence-6)
Otherwise,
the [*assignment-expression*](expr.assign#nt:assignment-expression "7.6.19Assignment and compound assignment operators[expr.assign]") shall be of
array or non-union class type[.](#7.sentence-7)
[8](#8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L250)
If the [*decl-specifier-seq*](dcl.spec.general#nt:decl-specifier-seq "9.2.1General[dcl.spec.general]") contains the typedef specifier, the declaration is a [*typedef declaration*](#def:declaration,typedef "9.1Preamble[dcl.pre]") and each [*declarator-id*](dcl.decl.general#nt:declarator-id "9.3.1General[dcl.decl.general]") is declared to be a [*typedef-name*](dcl.typedef#nt:typedef-name "9.2.4The typedef specifier[dcl.typedef]") ([[dcl.typedef]](dcl.typedef "9.2.4The typedef specifier"))[.](#8.sentence-1)
[*Note [4](#note-4)*:
Such a [*declarator-id*](dcl.decl.general#nt:declarator-id "9.3.1General[dcl.decl.general]") is
an [*identifier*](lex.name#nt:identifier "5.11Identifiers[lex.name]") ([[class.conv.fct]](class.conv.fct "11.4.8.3Conversion functions"))[.](#8.sentence-2)
— *end note*]
Otherwise, if the type associated with a [*declarator-id*](dcl.decl.general#nt:declarator-id "9.3.1General[dcl.decl.general]") is a function type ([[dcl.fct]](dcl.fct "9.3.4.6Functions")),
the declaration is a [*function declaration*](#def:declaration,function "9.1Preamble[dcl.pre]")[.](#8.sentence-3)
Otherwise, if the type associated with a [*declarator-id*](dcl.decl.general#nt:declarator-id "9.3.1General[dcl.decl.general]") is an object or reference type, the declaration is
an [*object declaration*](#def:declaration,object "9.1Preamble[dcl.pre]")[.](#8.sentence-4)
Otherwise, the program is ill-formed[.](#8.sentence-5)
[*Example [4](#example-4)*: int f(), x; // OK, function declaration for f and object declaration for xextern void g(), // OK, function declaration for g y; // error: void is not an object type — *end example*]
[9](#9)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L274)
An object definition causes
storage of appropriate size and alignment to be reserved and
any appropriate initialization ([[dcl.init]](dcl.init "9.5Initializers")) to be done[.](#9.sentence-1)
[10](#10)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L280)
Syntactic components beyond those found in the general form of[*simple-declaration*](#nt:simple-declaration "9.1Preamble[dcl.pre]") are added to a function declaration to make a[*function-definition*](dcl.fct.def.general#nt:function-definition "9.6.1General[dcl.fct.def.general]")[.](#10.sentence-1)
A token sequence starting with { or = is treated as a [*function-body*](dcl.fct.def.general#nt:function-body "9.6.1General[dcl.fct.def.general]") ([[dcl.fct.def.general]](dcl.fct.def.general "9.6.1General"))
if the type of the [*declarator-id*](dcl.decl.general#nt:declarator-id "9.3.1General[dcl.decl.general]") ([[dcl.meaning.general]](dcl.meaning.general "9.3.4.1General"))
is a function type, and
is otherwise
treated as a [*brace-or-equal-initializer*](dcl.init.general#nt:brace-or-equal-initializer "9.5.1General[dcl.init.general]") ([[dcl.init.general]](dcl.init.general "9.5.1General"))[.](#10.sentence-2)
[*Note [5](#note-5)*:
If the declaration acquires a function type through template instantiation,
the program is ill-formed; see [[temp.spec.general]](temp.spec.general "13.9.1General")[.](#10.sentence-3)
The function type of a function definition
cannot be specified with a [*typedef-name*](dcl.typedef#nt:typedef-name "9.2.4The typedef specifier[dcl.typedef]") ([[dcl.fct]](dcl.fct "9.3.4.6Functions"))[.](#10.sentence-4)
— *end note*]
[11](#11)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L298)
A [*nodeclspec-function-declaration*](#nt:nodeclspec-function-declaration "9.1Preamble[dcl.pre]") shall declare a
constructor, destructor, or conversion function[.](#11.sentence-1)
[*Note [6](#note-6)*:
Because a member function cannot be subject to a non-defining declaration
outside of a class definition ([[class.mfct]](class.mfct "11.4.2Member functions")), a [*nodeclspec-function-declaration*](#nt:nodeclspec-function-declaration "9.1Preamble[dcl.pre]") can only be used in a [*template-declaration*](temp.pre#nt:template-declaration "13.1Preamble[temp.pre]") ([[temp.pre]](temp.pre "13.1Preamble")),[*explicit-instantiation*](temp.explicit#nt:explicit-instantiation "13.9.3Explicit instantiation[temp.explicit]") ([[temp.explicit]](temp.explicit "13.9.3Explicit instantiation")), or[*explicit-specialization*](temp.expl.spec#nt:explicit-specialization "13.9.4Explicit specialization[temp.expl.spec]") ([[temp.expl.spec]](temp.expl.spec "13.9.4Explicit specialization"))[.](#11.sentence-2)
— *end note*]
[12](#12)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L309)
If a [*static_assert-message*](#nt:static_assert-message "9.1Preamble[dcl.pre]") matches the syntactic requirements of [*unevaluated-string*](lex.string.uneval#nt:unevaluated-string "5.13.6Unevaluated strings[lex.string.uneval]"),
it is an [*unevaluated-string*](lex.string.uneval#nt:unevaluated-string "5.13.6Unevaluated strings[lex.string.uneval]") and
the text of the [*static_assert-message*](#nt:static_assert-message "9.1Preamble[dcl.pre]") is
the text of the [*unevaluated-string*](lex.string.uneval#nt:unevaluated-string "5.13.6Unevaluated strings[lex.string.uneval]")[.](#12.sentence-1)
Otherwise, a [*static_assert-message*](#nt:static_assert-message "9.1Preamble[dcl.pre]") shall be an expression M such that
- [(12.1)](#12.1)
the expression M.size() is
implicitly convertible to the type std::size_t, and
- [(12.2)](#12.2)
the expression M.data() is
implicitly convertible to the type “pointer to const char”[.](#12.sentence-2)
[13](#13)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L326)
In a [*static_assert-declaration*](#nt:static_assert-declaration "9.1Preamble[dcl.pre]"),
the [*constant-expression*](expr.const#nt:constant-expression "7.7Constant expressions[expr.const]") E is contextually converted to bool and
the converted expression shall be a constant expression ([[expr.const]](expr.const "7.7Constant expressions"))[.](#13.sentence-1)
If the value of the expression E when so converted is true or
the expression is evaluated in the context of a template definition,
the declaration has no effect and
the [*static_assert-message*](#nt:static_assert-message "9.1Preamble[dcl.pre]") is
an unevaluated operand ([[expr.context]](expr.context#term.unevaluated.operand "7.2.3Context dependence"))[.](#13.sentence-2)
Otherwise,
the [*static_assert-declaration*](#nt:static_assert-declaration "9.1Preamble[dcl.pre]") [*fails*](#def:static_assert,failed "9.1Preamble[dcl.pre]") and
- [(13.1)](#13.1)
the program is ill-formed, and
- [(13.2)](#13.2)
if the [*static_assert-message*](#nt:static_assert-message "9.1Preamble[dcl.pre]") is
a [*constant-expression*](expr.const#nt:constant-expression "7.7Constant expressions[expr.const]") M,
* [(13.2.1)](#13.2.1)
M.size() shall be a converted constant expression of
type std::size_t and
let N denote the value of that expression,
* [(13.2.2)](#13.2.2)
M.data(), implicitly converted to
the type “pointer to const char”,
shall be a core constant expression and let D denote the converted expression,
* [(13.2.3)](#13.2.3)
for each i where 0≤i<N,D[i] shall be an integral constant expression, and
* [(13.2.4)](#13.2.4)
the text of the [*static_assert-message*](#nt:static_assert-message "9.1Preamble[dcl.pre]") is formed by
the sequence of N code units, starting at D, of
the ordinary literal encoding ([[lex.charset]](lex.charset "5.3.1Character sets"))[.](#13.sentence-3)
[14](#14)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L364)
*Recommended practice*: When a [*static_assert-declaration*](#nt:static_assert-declaration "9.1Preamble[dcl.pre]") fails,
the resulting diagnostic message should include the text of
the [*static_assert-message*](#nt:static_assert-message "9.1Preamble[dcl.pre]"), if one is supplied[.](#14.sentence-1)
[*Example [5](#example-5)*: static_assert(sizeof(int) == sizeof(void*), "wrong pointer size");static_assert(sizeof(int[2])); // OK, narrowing allowedtemplate <class T>void f(T t) {if constexpr (sizeof(T) == sizeof(int)) { use(t); } else {static_assert(false, "must be int-sized"); }}void g(char c) { f(0); // OK f(c); // error on implementations where sizeof(int) > 1: must be int-sized} — *end example*]
[15](#15)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L390)
For a [*consteval-block-declaration*](#nt:consteval-block-declaration "9.1Preamble[dcl.pre]") D,
the expression E corresponding to D is: [] -> void static consteval [*compound-statement*](stmt.block#nt:compound-statement "8.4Compound statement or block[stmt.block]") ()E shall be a constant expression ([[expr.const]](expr.const "7.7Constant expressions"))[.](#15.sentence-1)
[*Note [7](#note-7)*:
The evaluation of the expression
corresponding to a [*consteval-block-declaration*](#nt:consteval-block-declaration "9.1Preamble[dcl.pre]") ([[lex.phases]](lex.phases "5.2Phases of translation"))
can produce injected declarations as side effects[.](#15.sentence-2)
— *end note*]
[*Example [6](#example-6)*: struct S;consteval { std::meta::define_aggregate(^^S, {}); // OKtemplate<class T>struct X { }; // error: local templates are not allowedtemplate<class T>concept C = true; // error: local concepts are not allowedreturn; // OK} — *end example*]
[16](#16)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L419)
An [*empty-declaration*](#nt:empty-declaration "9.1Preamble[dcl.pre]") has no effect[.](#16.sentence-1)
[17](#17)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L422)
Except where otherwise specified, the meaning of an [*attribute-declaration*](#nt:attribute-declaration "9.1Preamble[dcl.pre]") is implementation-defined[.](#17.sentence-1)

79
cppdraft/dcl/ptr.md Normal file
View File

@@ -0,0 +1,79 @@
[dcl.ptr]
# 9 Declarations [[dcl]](./#dcl)
## 9.3 Declarators [[dcl.decl]](dcl.decl#dcl.ptr)
### 9.3.4 Meaning of declarators [[dcl.meaning]](dcl.meaning#dcl.ptr)
#### 9.3.4.2 Pointers [dcl.ptr]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L3032)
In a declarationTD whereD has the form
* [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1Attribute syntax and semantics[dcl.attr.grammar]")opt [*cv-qualifier-seq*](dcl.decl.general#nt:cv-qualifier-seq "9.3.1General[dcl.decl.general]")opt D1
and the type of the contained [*declarator-id*](dcl.decl.general#nt:declarator-id "9.3.1General[dcl.decl.general]") in the declarationTD1 is “*derived-declarator-type-list*T”,
the type of the [*declarator-id*](dcl.decl.general#nt:declarator-id "9.3.1General[dcl.decl.general]") inD is “*derived-declarator-type-list* [*cv-qualifier-seq*](dcl.decl.general#nt:cv-qualifier-seq "9.3.1General[dcl.decl.general]") pointer toT”[.](#1.sentence-1)
The[*cv-qualifier*](dcl.decl.general#nt:cv-qualifier "9.3.1General[dcl.decl.general]")*s* apply to the pointer and not to the object pointed to[.](#1.sentence-2)
Similarly, the optional [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") ([[dcl.attr.grammar]](dcl.attr.grammar "9.13.1Attribute syntax and semantics")) appertains to the pointer and not to the object pointed to[.](#1.sentence-3)
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L3058)
[*Example [1](#example-1)*:
The declarationsconst int ci = 10, *pc = &ci, *const cpc = pc, **ppc;int i, *p, *const cp = &i; declareci,
a constant integer;pc,
a pointer to a constant integer;cpc,
a constant pointer to a constant integer;ppc,
a pointer to a pointer to a constant integer;i,
an integer;p,
a pointer to integer; andcp,
a constant pointer to integer[.](#2.sentence-1)
The value ofci,cpc,
andcp cannot be changed after initialization[.](#2.sentence-2)
The value ofpc can be changed, and so can the object pointed to bycp[.](#2.sentence-3)
Examples of
some correct operations arei = ci;*cp = ci;
pc++;
pc = cpc;
pc = p;
ppc = &pc;
Examples of ill-formed operations areci = 1; // error ci++; // error*pc = 2; // error cp = &ci; // error cpc++; // error p = pc; // error ppc = &p; // error
Each is unacceptable because it would either change the value of an object declaredconst or allow it to be changed through a cv-unqualified pointer later, for example:*ppc = &ci; // OK, but would make p point to ci because of previous error*p = 5; // clobber ci
— *end example*]
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L3121)
See also [[expr.assign]](expr.assign "7.6.19Assignment and compound assignment operators") and [[dcl.init]](dcl.init "9.5Initializers")[.](#3.sentence-1)
[4](#4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L3124)
[*Note [1](#note-1)*:
Forming a pointer to reference type is ill-formed; see [[dcl.ref]](dcl.ref "9.3.4.3References")[.](#4.sentence-1)
Forming a function pointer type is ill-formed if the function type has[*cv-qualifier*](dcl.decl.general#nt:cv-qualifier "9.3.1General[dcl.decl.general]")*s* or a [*ref-qualifier*](dcl.decl.general#nt:ref-qualifier "9.3.1General[dcl.decl.general]");
see [[dcl.fct]](dcl.fct "9.3.4.6Functions")[.](#4.sentence-2)
Since the address of a bit-field ([[class.bit]](class.bit "11.4.10Bit-fields")) cannot be taken,
a pointer can never point to a bit-field[.](#4.sentence-3)
— *end note*]

168
cppdraft/dcl/ref.md Normal file
View File

@@ -0,0 +1,168 @@
[dcl.ref]
# 9 Declarations [[dcl]](./#dcl)
## 9.3 Declarators [[dcl.decl]](dcl.decl#dcl.ref)
### 9.3.4 Meaning of declarators [[dcl.meaning]](dcl.meaning#dcl.ref)
#### 9.3.4.3 References [dcl.ref]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L3137)
In a declarationTD whereD has either of the forms
& [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1Attribute syntax and semantics[dcl.attr.grammar]")opt D1
&& [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1Attribute syntax and semantics[dcl.attr.grammar]")opt D1
and the type of the contained [*declarator-id*](dcl.decl.general#nt:declarator-id "9.3.1General[dcl.decl.general]") in the declarationTD1 is “*derived-declarator-type-list*T”,
the type of the [*declarator-id*](dcl.decl.general#nt:declarator-id "9.3.1General[dcl.decl.general]") inD is “*derived-declarator-type-list* reference toT”[.](#1.sentence-1)
The optional [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") appertains to the reference type[.](#1.sentence-2)
Cv-qualified references are ill-formed except when the cv-qualifiers
are introduced through the use of a[*typedef-name*](dcl.typedef#nt:typedef-name "9.2.4The typedef specifier[dcl.typedef]") ([[dcl.typedef]](dcl.typedef "9.2.4The typedef specifier"), [[temp.param]](temp.param "13.2Template parameters")) or[*decltype-specifier*](dcl.type.decltype#nt:decltype-specifier "9.2.9.6Decltype specifiers[dcl.type.decltype]") ([[dcl.type.decltype]](dcl.type.decltype "9.2.9.6Decltype specifiers")),
in which case the cv-qualifiers are ignored[.](#1.sentence-3)
[*Example [1](#example-1)*: typedef int& A;const A aref = 3; // error: lvalue reference to non-const initialized with rvalue
The type ofaref is “lvalue reference to int”,
not “lvalue reference to const int”[.](#1.sentence-4)
— *end example*]
[*Note [1](#note-1)*:
A reference can be thought of as a name of an object[.](#1.sentence-5)
— *end note*]
Forming the type
“reference to cv void”
is ill-formed[.](#1.sentence-6)
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L3183)
A reference type that is declared using & is called an[*lvalue reference*](#def:lvalue_reference "9.3.4.3References[dcl.ref]"), and a reference type that
is declared using && is called an[*rvalue reference*](#def:rvalue_reference "9.3.4.3References[dcl.ref]")[.](#2.sentence-1)
Lvalue references and
rvalue references are distinct types[.](#2.sentence-2)
Except where explicitly noted, they are
semantically equivalent and commonly referred to as references[.](#2.sentence-3)
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L3191)
[*Example [2](#example-2)*:
void f(double& a) { a += 3.14; }// ...double d = 0;
f(d); declaresa to be a reference parameter off so the callf(d) will add3.14 tod[.](#3.sentence-1)
int v[20];// ...int& g(int i) { return v[i]; }// ... g(3) = 7; declares the functiong() to return a reference to an integer sog(3)=7 will assign7 to the fourth element of the arrayv[.](#3.sentence-2)
For another example,struct link { link* next;};
link* first;
void h(link*& p) { // p is a reference to pointer p->next = first;
first = p;
p = 0;}void k() { link* q = new link;
h(q);} declaresp to be a reference to a pointer tolink soh(q) will leaveq with the value zero[.](#3.sentence-3)
See also [[dcl.init.ref]](dcl.init.ref "9.5.4References")[.](#3.sentence-4)
— *end example*]
[4](#4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L3258)
It is unspecified whether or not
a reference requires storage ([[basic.stc]](basic.stc "6.8.6Storage duration"))[.](#4.sentence-1)
[5](#5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L3262)
There shall be no references to references,
no arrays of references, and no pointers to references[.](#5.sentence-1)
The declaration of a reference shall contain an[*initializer*](dcl.init.general#nt:initializer "9.5.1General[dcl.init.general]") ([[dcl.init.ref]](dcl.init.ref "9.5.4References"))
except when the declaration contains an explicitextern specifier ([[dcl.stc]](dcl.stc "9.2.2Storage class specifiers")),
is a class member ([[class.mem]](class.mem "11.4Class members")) declaration within a class definition,
or is the declaration of a parameter or a return type ([[dcl.fct]](dcl.fct "9.3.4.6Functions")); see [[basic.def]](basic.def "6.2Declarations and definitions")[.](#5.sentence-2)
[6](#6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L3275)
Attempting to bind a reference to a function where
the converted initializer is a glvalue whose
type is not call-compatible ([[expr.call]](expr.call "7.6.1.3Function call"))
with the type of the function's definition
results in undefined behavior[.](#6.sentence-1)
Attempting to bind a reference to an object where
the converted initializer is a glvalue through which
the object is not type-accessible ([[basic.lval]](basic.lval "7.2.1Value category"))
results in undefined behavior[.](#6.sentence-2)
[*Note [2](#note-2)*:
The object designated by such a glvalue can be
outside its lifetime ([[basic.life]](basic.life "6.8.4Lifetime"))[.](#6.sentence-3)
Because a null pointer value or a pointer past the end of an object
does not point to an object,
a reference in a well-defined program cannot refer to such things;
see [[expr.unary.op]](expr.unary.op "7.6.2.2Unary operators")[.](#6.sentence-4)
As described in [[class.bit]](class.bit "11.4.10Bit-fields"), a reference cannot be bound directly
to a bit-field[.](#6.sentence-5)
— *end note*]
The behavior of an evaluation of a reference ([[expr.prim.id]](expr.prim.id "7.5.5Names"), [[expr.ref]](expr.ref "7.6.1.5Class member access")) that
does not happen after ([[intro.races]](intro.races "6.10.2.2Data races")) the initialization of the reference
is undefined[.](#6.sentence-6)
[*Example [3](#example-3)*: int &f(int&);int &g();extern int &ir3;int *ip = 0;int &ir1 = *ip; // undefined behavior: null pointerint &ir2 = f(ir3); // undefined behavior: ir3 not yet initializedint &ir3 = g();int &ir4 = f(ir4); // undefined behavior: ir4 used in its own initializerchar x alignas(int);int &ir5 = *reinterpret_cast<int *>(&x); // undefined behavior: initializer refers to char object — *end example*]
[7](#7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L3315)
If a [*typedef-name*](dcl.typedef#nt:typedef-name "9.2.4The typedef specifier[dcl.typedef]") ([[dcl.typedef]](dcl.typedef "9.2.4The typedef specifier"), [[temp.param]](temp.param "13.2Template parameters"))
or a [*decltype-specifier*](dcl.type.decltype#nt:decltype-specifier "9.2.9.6Decltype specifiers[dcl.type.decltype]") ([[dcl.type.decltype]](dcl.type.decltype "9.2.9.6Decltype specifiers")) denotes a type TR that
is a reference to a type T, an attempt to create the type “lvalue reference to cv TR”
creates the type “lvalue reference to T”, while an attempt to create
the type “rvalue reference to cv TR” creates the type TR[.](#7.sentence-1)
[*Note [3](#note-3)*:
This rule is known as reference collapsing[.](#7.sentence-2)
— *end note*]
[*Example [4](#example-4)*: int i;typedef int& LRI;typedef int&& RRI;
LRI& r1 = i; // r1 has the type int&const LRI& r2 = i; // r2 has the type int&const LRI&& r3 = i; // r3 has the type int& RRI& r4 = i; // r4 has the type int& RRI&& r5 = 5; // r5 has the type int&&decltype(r2)& r6 = i; // r6 has the type int&decltype(r2)&& r7 = i; // r7 has the type int& — *end example*]
[8](#8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L3343)
[*Note [4](#note-4)*:
Forming a reference to function type is ill-formed if the function
type has [*cv-qualifier*](dcl.decl.general#nt:cv-qualifier "9.3.1General[dcl.decl.general]")*s* or a [*ref-qualifier*](dcl.decl.general#nt:ref-qualifier "9.3.1General[dcl.decl.general]");
see [[dcl.fct]](dcl.fct "9.3.4.6Functions")[.](#8.sentence-1)
— *end note*]

1814
cppdraft/dcl/spec.md Normal file

File diff suppressed because it is too large Load Diff

412
cppdraft/dcl/spec/auto.md Normal file
View File

@@ -0,0 +1,412 @@
[dcl.spec.auto]
# 9 Declarations [[dcl]](./#dcl)
## 9.2 Specifiers [[dcl.spec]](dcl.spec#auto)
### 9.2.9 Type specifiers [[dcl.type]](dcl.type#dcl.spec.auto)
#### 9.2.9.7 Placeholder type specifiers [dcl.spec.auto]
#### [9.2.9.7.1](#general) General [[dcl.spec.auto.general]](dcl.spec.auto.general)
[placeholder-type-specifier:](#nt:placeholder-type-specifier "9.2.9.7.1General[dcl.spec.auto.general]")
[*type-constraint*](temp.param#nt:type-constraint "13.2Template parameters[temp.param]")opt auto
[*type-constraint*](temp.param#nt:type-constraint "13.2Template parameters[temp.param]")opt decltype ( auto )
[1](#general-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L1825)
A [*placeholder-type-specifier*](#nt:placeholder-type-specifier "9.2.9.7.1General[dcl.spec.auto.general]") designates a placeholder type that will be replaced later,
typically by deduction
from an initializer[.](#general-1.sentence-1)
[2](#general-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L1831)
The type of a [*parameter-declaration*](dcl.fct#nt:parameter-declaration "9.3.4.6Functions[dcl.fct]") of a
- [(2.1)](#general-2.1)
function declaration ([[dcl.fct]](dcl.fct "9.3.4.6Functions")),
- [(2.2)](#general-2.2)
[*lambda-expression*](expr.prim.lambda.general#nt:lambda-expression "7.5.6.1General[expr.prim.lambda.general]") ([[expr.prim.lambda]](expr.prim.lambda "7.5.6Lambda expressions")), or
- [(2.3)](#general-2.3)
[*template-parameter*](temp.param#nt:template-parameter "13.2Template parameters[temp.param]") ([[temp.param]](temp.param "13.2Template parameters"))
can be declared using
a [*placeholder-type-specifier*](#nt:placeholder-type-specifier "9.2.9.7.1General[dcl.spec.auto.general]") of the form[*type-constraint*](temp.param#nt:type-constraint "13.2Template parameters[temp.param]")opt auto[.](#general-2.sentence-1)
The placeholder type shall appear
as one of the [*decl-specifier*](dcl.spec.general#nt:decl-specifier "9.2.1General[dcl.spec.general]")*s* in
the [*decl-specifier-seq*](dcl.spec.general#nt:decl-specifier-seq "9.2.1General[dcl.spec.general]") or
as one of the [*type-specifier*](dcl.type.general#nt:type-specifier "9.2.9.1General[dcl.type.general]")*s* in
a [*trailing-return-type*](dcl.decl.general#nt:trailing-return-type "9.3.1General[dcl.decl.general]") that specifies the type that replaces such
a [*decl-specifier*](dcl.spec.general#nt:decl-specifier "9.2.1General[dcl.spec.general]") (see below);
the placeholder type
is a [*generic parameter type placeholder*](#def:generic_parameter_type_placeholder "9.2.9.7.1General[dcl.spec.auto.general]") of the
function declaration,[*lambda-expression*](expr.prim.lambda.general#nt:lambda-expression "7.5.6.1General[expr.prim.lambda.general]"), or[*template-parameter*](temp.param#nt:template-parameter "13.2Template parameters[temp.param]"), respectively[.](#general-2.sentence-2)
[*Note [1](#general-note-1)*:
Having a generic parameter type placeholder
signifies that the function is
an abbreviated function template ([[dcl.fct]](dcl.fct "9.3.4.6Functions")) or
the lambda is a generic lambda ([[expr.prim.lambda]](expr.prim.lambda "7.5.6Lambda expressions"))[.](#general-2.sentence-3)
— *end note*]
[3](#general-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L1861)
A placeholder type can appear in
the [*decl-specifier-seq*](dcl.spec.general#nt:decl-specifier-seq "9.2.1General[dcl.spec.general]") for a function declarator
that includes a [*trailing-return-type*](dcl.decl.general#nt:trailing-return-type "9.3.1General[dcl.decl.general]") ([[dcl.fct]](dcl.fct "9.3.4.6Functions"))[.](#general-3.sentence-1)
[4](#general-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L1866)
A placeholder type can appear in
the [*decl-specifier-seq*](dcl.spec.general#nt:decl-specifier-seq "9.2.1General[dcl.spec.general]") or [*type-specifier-seq*](dcl.type.general#nt:type-specifier-seq "9.2.9.1General[dcl.type.general]") in the declared return type of a function declarator that declares a function;
the return type of the function is
deduced from non-discarded return statements, if any, in the body
of the function ([[stmt.if]](stmt.if "8.5.2The if statement"))[.](#general-4.sentence-1)
[5](#general-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L1874)
The type of a variable declared using a placeholder type is
deduced from its initializer[.](#general-5.sentence-1)
This use is allowed
in an initializing declaration ([[dcl.init]](dcl.init "9.5Initializers")) of a variable[.](#general-5.sentence-2)
The placeholder type shall appear as one of the[*decl-specifier*](dcl.spec.general#nt:decl-specifier "9.2.1General[dcl.spec.general]")*s* in the [*decl-specifier-seq*](dcl.spec.general#nt:decl-specifier-seq "9.2.1General[dcl.spec.general]") or as one of the[*type-specifier*](dcl.type.general#nt:type-specifier "9.2.9.1General[dcl.type.general]")*s* in a [*trailing-return-type*](dcl.decl.general#nt:trailing-return-type "9.3.1General[dcl.decl.general]") that specifies the type that replaces such a [*decl-specifier*](dcl.spec.general#nt:decl-specifier "9.2.1General[dcl.spec.general]");
the [*decl-specifier-seq*](dcl.spec.general#nt:decl-specifier-seq "9.2.1General[dcl.spec.general]") shall be followed by one or more[*declarator*](dcl.decl.general#nt:declarator "9.3.1General[dcl.decl.general]")*s*,
each of which shall
be followed by a non-empty[*initializer*](dcl.init.general#nt:initializer "9.5.1General[dcl.init.general]")[.](#general-5.sentence-3)
[*Example [1](#general-example-1)*: auto x = 5; // OK, x has type intconst auto *v = &x, u = 6; // OK, v has type const int*, u has type const intstatic auto y = 0.0; // OK, y has type doubleauto int r; // error: auto is not a [*storage-class-specifier*](dcl.stc#nt:storage-class-specifier "9.2.2Storage class specifiers[dcl.stc]")auto f() -> int; // OK, f returns intauto g() { return 0.0; } // OK, g returns doubleauto (*fp)() -> auto = f; // OKauto h(); // OK, h's return type will be deduced when it is defined — *end example*]
The auto [*type-specifier*](dcl.type.general#nt:type-specifier "9.2.9.1General[dcl.type.general]") can also be used to introduce
a structured binding declaration ([[dcl.struct.bind]](dcl.struct.bind "9.7Structured binding declarations"))[.](#general-5.sentence-4)
[6](#general-6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L1906)
A placeholder type can also be used
in the [*type-specifier-seq*](dcl.type.general#nt:type-specifier-seq "9.2.9.1General[dcl.type.general]") of
the [*new-type-id*](expr.new#nt:new-type-id "7.6.2.8New[expr.new]") or
in the [*type-id*](dcl.name#nt:type-id "9.3.2Type names[dcl.name]") of a[*new-expression*](expr.new#nt:new-expression "7.6.2.8New[expr.new]") ([[expr.new]](expr.new "7.6.2.8New"))[.](#general-6.sentence-1)
In such a [*type-id*](dcl.name#nt:type-id "9.3.2Type names[dcl.name]"),
the placeholder type shall appear
as one of the [*type-specifier*](dcl.type.general#nt:type-specifier "9.2.9.1General[dcl.type.general]")*s* in
the [*type-specifier-seq*](dcl.type.general#nt:type-specifier-seq "9.2.9.1General[dcl.type.general]") or
as one of the [*type-specifier*](dcl.type.general#nt:type-specifier "9.2.9.1General[dcl.type.general]")*s* in
a [*trailing-return-type*](dcl.decl.general#nt:trailing-return-type "9.3.1General[dcl.decl.general]") that specifies the type that replaces such a [*type-specifier*](dcl.type.general#nt:type-specifier "9.2.9.1General[dcl.type.general]")[.](#general-6.sentence-2)
[7](#general-7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L1920)
The auto [*type-specifier*](dcl.type.general#nt:type-specifier "9.2.9.1General[dcl.type.general]") can also be used
as the [*simple-type-specifier*](dcl.type.simple#nt:simple-type-specifier "9.2.9.3Simple type specifiers[dcl.type.simple]") in an explicit type conversion (functional notation) ([[expr.type.conv]](expr.type.conv "7.6.1.4Explicit type conversion (functional notation)"))[.](#general-7.sentence-1)
[8](#general-8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L1925)
A program that uses a placeholder type in a context not
explicitly allowed in [dcl.spec.auto] is ill-formed[.](#general-8.sentence-1)
[9](#general-9)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L1929)
If the [*init-declarator-list*](dcl.decl.general#nt:init-declarator-list "9.3.1General[dcl.decl.general]") contains more than one[*init-declarator*](dcl.decl.general#nt:init-declarator "9.3.1General[dcl.decl.general]"), they shall all form declarations of
variables[.](#general-9.sentence-1)
The type of each declared variable is determined
by [placeholder type deduction](#def:placeholder_type_deduction "9.2.9.7.2Placeholder type deduction[dcl.type.auto.deduct]"),
and if the type that replaces the placeholder type is not the
same in each deduction, the program is ill-formed[.](#general-9.sentence-2)
[*Example [2](#general-example-2)*: auto x = 5, *y = &x; // OK, auto is intauto a = 5, b = { 1, 2 }; // error: different types for auto — *end example*]
[10](#general-10)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L1944)
If a function with a declared return type that contains a placeholder type has
multiple non-discarded return statements, the return type is deduced for each
such return statement[.](#general-10.sentence-1)
If the type deduced is not the same in each
deduction, the program is ill-formed[.](#general-10.sentence-2)
[11](#general-11)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L1950)
If a function with a declared return type that uses a placeholder type has no
non-discarded return statements, the return type is deduced as though from areturn statement with no operand at the closing brace of the function
body[.](#general-11.sentence-1)
[*Example [3](#general-example-3)*: auto f() { } // OK, return type is voidauto* g() { } // error: cannot deduce auto* from void() — *end example*]
[12](#general-12)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L1962)
An exported function
with a declared return type that uses a placeholder type
shall be defined in the translation unit
containing its exported declaration,
outside the [*private-module-fragment*](module.private.frag#nt:private-module-fragment "10.5Private module fragment[module.private.frag]") (if any)[.](#general-12.sentence-1)
[*Note [2](#general-note-2)*:
The deduced return type cannot have
a name with internal linkage ([[basic.link]](basic.link "6.7Program and linkage"))[.](#general-12.sentence-2)
— *end note*]
[13](#general-13)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L1973)
If a variable or function with an undeduced placeholder type is named by an
expression ([[basic.def.odr]](basic.def.odr "6.3One-definition rule")), the program is ill-formed[.](#general-13.sentence-1)
Once a
non-discarded return statement has been seen in a function, however, the return type deduced
from that statement can be used in the rest of the function, including in otherreturn statements[.](#general-13.sentence-2)
[*Example [4](#general-example-4)*: auto n = n; // error: n's initializer refers to nauto f();void g() { &f; } // error: f's return type is unknownauto sum(int i) {if (i == 1)return i; // sum's return type is intelsereturn sum(i-1)+i; // OK, sum's return type has been deduced} — *end example*]
[14](#general-14)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L1993)
A result binding never has
an undeduced placeholder type ([[dcl.contract.res]](dcl.contract.res "9.4.2Referring to the result object"))[.](#general-14.sentence-1)
[*Example [5](#general-example-5)*: auto f() post(r : r == 7) // OK{return 7;} — *end example*]
[15](#general-15)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L2007)
Return type deduction for a templated
function with a placeholder in its
declared type occurs when the definition is instantiated even if the function
body contains a return statement with a non-type-dependent operand[.](#general-15.sentence-1)
[*Note [3](#general-note-3)*:
Therefore, any use of a specialization of the function template will
cause an implicit instantiation[.](#general-15.sentence-2)
Any errors that arise from this instantiation
are not in the immediate context of the function type and can result in the
program being ill-formed ([[temp.deduct]](temp.deduct "13.10.3Template argument deduction"))[.](#general-15.sentence-3)
— *end note*]
[*Example [6](#general-example-6)*: template <class T> auto f(T t) { return t; } // return type deduced at instantiation timetypedef decltype(f(1)) fint_t; // instantiates f<int> to deduce return typetemplate<class T> auto f(T* t) { return *t; }void g() { int (*p)(int*) = &f; } // instantiates both fs to determine return types,// chooses second — *end example*]
[16](#general-16)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L2028)
If a function or function template F has
a declared return type that uses a placeholder type,
redeclarations or specializations of F shall use that
placeholder type, not a deduced type;
otherwise, they shall not use a placeholder type[.](#general-16.sentence-1)
[*Example [7](#general-example-7)*: auto f();auto f() { return 42; } // return type is intauto f(); // OKint f(); // error: auto and int don't matchdecltype(auto) f(); // error: auto and decltype(auto) don't matchtemplate <typename T> auto g(T t) { return t; } // #1template auto g(int); // OK, return type is inttemplate char g(char); // error: no matching templatetemplate<> auto g(double); // OK, forward declaration with unknown return typetemplate <class T> T g(T t) { return t; } // OK, not functionally equivalent to #1template char g(char); // OK, now there is a matching templatetemplate auto g(float); // still matches #1void h() { return g(42); } // error: ambiguoustemplate <typename T> struct A {friend T frf(T);};auto frf(int i) { return i; } // not a friend of A<int>extern int v;auto v = 17; // OK, redeclares vstruct S {static int i;};auto S::i = 23; // OK — *end example*]
[17](#general-17)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L2066)
A function declared with a return type that uses a placeholder type shall not
be virtual ([[class.virtual]](class.virtual "11.7.3Virtual functions"))[.](#general-17.sentence-1)
[18](#general-18)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L2070)
A function declared with a return type that uses a placeholder type shall not
be a coroutine ([[dcl.fct.def.coroutine]](dcl.fct.def.coroutine "9.6.4Coroutine definitions"))[.](#general-18.sentence-1)
[19](#general-19)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L2074)
An [explicit instantiation declaration](temp.explicit "13.9.3Explicit instantiation[temp.explicit]") does not cause the
instantiation of an entity declared using a placeholder type, but it also does
not prevent that entity from being instantiated as needed to determine its
type[.](#general-19.sentence-1)
[*Example [8](#general-example-8)*: template <typename T> auto f(T t) { return t; }extern template auto f(int); // does not instantiate f<int>int (*p)(int) = f; // instantiates f<int> to determine its return type, but an explicit// instantiation definition is still required somewhere in the program — *end example*]
#### [9.2.9.7.2](#dcl.type.auto.deduct) Placeholder type deduction [[dcl.type.auto.deduct]](dcl.type.auto.deduct)
[1](#dcl.type.auto.deduct-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L2091)
[*Placeholder type deduction*](#def:placeholder_type_deduction "9.2.9.7.2Placeholder type deduction[dcl.type.auto.deduct]") is the process by which
a type containing a placeholder type
is replaced by a deduced type[.](#dcl.type.auto.deduct-1.sentence-1)
[2](#dcl.type.auto.deduct-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L2097)
A type T containing a placeholder type,
and a corresponding [*initializer-clause*](dcl.init.general#nt:initializer-clause "9.5.1General[dcl.init.general]") E,
are determined as follows:
- [(2.1)](#dcl.type.auto.deduct-2.1)
For a non-discarded return statement that occurs
in a function declared with a return type
that contains a placeholder type,T is the declared return type[.](#dcl.type.auto.deduct-2.1.sentence-1)
* [(2.1.1)](#dcl.type.auto.deduct-2.1.1)
If the return statement has no operand,
then E is void()[.](#dcl.type.auto.deduct-2.1.1.sentence-1)
* [(2.1.2)](#dcl.type.auto.deduct-2.1.2)
If the operand is a [*braced-init-list*](dcl.init.general#nt:braced-init-list "9.5.1General[dcl.init.general]") ([[dcl.init.list]](dcl.init.list "9.5.5List-initialization")),
the program is ill-formed[.](#dcl.type.auto.deduct-2.1.2.sentence-1)
* [(2.1.3)](#dcl.type.auto.deduct-2.1.3)
If the operand is an [*expression*](expr.comma#nt:expression "7.6.20Comma operator[expr.comma]") X that is not an [*assignment-expression*](expr.assign#nt:assignment-expression "7.6.19Assignment and compound assignment operators[expr.assign]"),E is (X)[.](#dcl.type.auto.deduct-2.1.3.sentence-1)
[*Note [1](#dcl.type.auto.deduct-note-1)*:
A comma expression ([[expr.comma]](expr.comma "7.6.20Comma operator")) is not
an [*assignment-expression*](expr.assign#nt:assignment-expression "7.6.19Assignment and compound assignment operators[expr.assign]")[.](#dcl.type.auto.deduct-2.1.3.sentence-2)
— *end note*]
* [(2.1.4)](#dcl.type.auto.deduct-2.1.4)
Otherwise, E is the operand of the return statement[.](#dcl.type.auto.deduct-2.1.4.sentence-1)
If E has type void,T shall be either[*type-constraint*](temp.param#nt:type-constraint "13.2Template parameters[temp.param]")opt decltype(auto) orcv [*type-constraint*](temp.param#nt:type-constraint "13.2Template parameters[temp.param]")opt auto[.](#dcl.type.auto.deduct-2.1.sentence-2)
- [(2.2)](#dcl.type.auto.deduct-2.2)
For a variable declared with a type
that contains a placeholder type,T is the declared type of the variable[.](#dcl.type.auto.deduct-2.2.sentence-1)
* [(2.2.1)](#dcl.type.auto.deduct-2.2.1)
If the initializer of the variable is a [*brace-or-equal-initializer*](dcl.init.general#nt:brace-or-equal-initializer "9.5.1General[dcl.init.general]") of the form = [*initializer-clause*](dcl.init.general#nt:initializer-clause "9.5.1General[dcl.init.general]"),E is the [*initializer-clause*](dcl.init.general#nt:initializer-clause "9.5.1General[dcl.init.general]")[.](#dcl.type.auto.deduct-2.2.1.sentence-1)
* [(2.2.2)](#dcl.type.auto.deduct-2.2.2)
If the initializer is a [*braced-init-list*](dcl.init.general#nt:braced-init-list "9.5.1General[dcl.init.general]"),
it shall consist of a single brace-enclosed [*assignment-expression*](expr.assign#nt:assignment-expression "7.6.19Assignment and compound assignment operators[expr.assign]") and E is the [*assignment-expression*](expr.assign#nt:assignment-expression "7.6.19Assignment and compound assignment operators[expr.assign]")[.](#dcl.type.auto.deduct-2.2.2.sentence-1)
* [(2.2.3)](#dcl.type.auto.deduct-2.2.3)
If the initializer is a parenthesized [*expression-list*](expr.post.general#nt:expression-list "7.6.1.1General[expr.post.general]"),
the [*expression-list*](expr.post.general#nt:expression-list "7.6.1.1General[expr.post.general]") shall be
a single [*assignment-expression*](expr.assign#nt:assignment-expression "7.6.19Assignment and compound assignment operators[expr.assign]") and E is the [*assignment-expression*](expr.assign#nt:assignment-expression "7.6.19Assignment and compound assignment operators[expr.assign]")[.](#dcl.type.auto.deduct-2.2.3.sentence-1)
- [(2.3)](#dcl.type.auto.deduct-2.3)
For an explicit type conversion ([[expr.type.conv]](expr.type.conv "7.6.1.4Explicit type conversion (functional notation)")),T is the specified type, which shall be auto[.](#dcl.type.auto.deduct-2.3.sentence-1)
* [(2.3.1)](#dcl.type.auto.deduct-2.3.1)
If the initializer is a [*braced-init-list*](dcl.init.general#nt:braced-init-list "9.5.1General[dcl.init.general]"),
it shall consist of a single brace-enclosed [*assignment-expression*](expr.assign#nt:assignment-expression "7.6.19Assignment and compound assignment operators[expr.assign]") and E is the [*assignment-expression*](expr.assign#nt:assignment-expression "7.6.19Assignment and compound assignment operators[expr.assign]")[.](#dcl.type.auto.deduct-2.3.1.sentence-1)
* [(2.3.2)](#dcl.type.auto.deduct-2.3.2)
If the initializer is a parenthesized [*expression-list*](expr.post.general#nt:expression-list "7.6.1.1General[expr.post.general]"),
the [*expression-list*](expr.post.general#nt:expression-list "7.6.1.1General[expr.post.general]") shall be
a single [*assignment-expression*](expr.assign#nt:assignment-expression "7.6.19Assignment and compound assignment operators[expr.assign]") and E is the [*assignment-expression*](expr.assign#nt:assignment-expression "7.6.19Assignment and compound assignment operators[expr.assign]")[.](#dcl.type.auto.deduct-2.3.2.sentence-1)
- [(2.4)](#dcl.type.auto.deduct-2.4)
For a constant template parameter declared with a type
that contains a placeholder type,T is the declared type of the constant template parameter
and E is the corresponding template argument[.](#dcl.type.auto.deduct-2.4.sentence-1)
T shall not be an array type[.](#dcl.type.auto.deduct-2.sentence-2)
[3](#dcl.type.auto.deduct-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L2171)
If the [*placeholder-type-specifier*](#nt:placeholder-type-specifier "9.2.9.7.1General[dcl.spec.auto.general]") is of the form[*type-constraint*](temp.param#nt:type-constraint "13.2Template parameters[temp.param]")opt auto,
the deduced typeT′ replacing T is determined using the rules for template argument deduction[.](#dcl.type.auto.deduct-3.sentence-1)
If the initialization is copy-list-initialization,
a declaration of std::initializer_list shall precede ([[basic.lookup.general]](basic.lookup.general "6.5.1General"))
the [*placeholder-type-specifier*](#nt:placeholder-type-specifier "9.2.9.7.1General[dcl.spec.auto.general]")[.](#dcl.type.auto.deduct-3.sentence-2)
Obtain P fromT by replacing the occurrence of[*type-constraint*](temp.param#nt:type-constraint "13.2Template parameters[temp.param]")opt auto either with
a new invented type template parameter U or,
if the initialization is copy-list-initialization, withstd::initializer_list<U>[.](#dcl.type.auto.deduct-3.sentence-3)
Deduce a value for U using the rules
of [template argument deduction from a function call](temp.deduct.call "13.10.3.2Deducing template arguments from a function call[temp.deduct.call]"),
where P is a
function template parameter type and
the corresponding argument is E[.](#dcl.type.auto.deduct-3.sentence-4)
If the deduction fails, the declaration is ill-formed[.](#dcl.type.auto.deduct-3.sentence-5)
Otherwise, T′ is obtained by
substituting the deduced U into P[.](#dcl.type.auto.deduct-3.sentence-6)
[*Example [1](#dcl.type.auto.deduct-example-1)*: auto x1 = { 1, 2 }; // decltype(x1) is std::initializer_list<int>auto x2 = { 1, 2.0 }; // error: cannot deduce element typeauto x3{ 1, 2 }; // error: not a single elementauto x4 = { 3 }; // decltype(x4) is std::initializer_list<int>auto x5{ 3 }; // decltype(x5) is int — *end example*]
[*Example [2](#dcl.type.auto.deduct-example-2)*: const auto &i = expr;
The type of i is the deduced type of the parameter u in
the call f(expr) of the following invented function template:template <class U> void f(const U& u);
— *end example*]
[4](#dcl.type.auto.deduct-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L2215)
If the [*placeholder-type-specifier*](#nt:placeholder-type-specifier "9.2.9.7.1General[dcl.spec.auto.general]") is of the form[*type-constraint*](temp.param#nt:type-constraint "13.2Template parameters[temp.param]")opt decltype(auto),T shall be the
placeholder alone[.](#dcl.type.auto.deduct-4.sentence-1)
The type deduced for T is
determined as described in [[dcl.type.decltype]](dcl.type.decltype "9.2.9.6Decltype specifiers"), as thoughE had
been the operand of the decltype[.](#dcl.type.auto.deduct-4.sentence-2)
[*Example [3](#dcl.type.auto.deduct-example-3)*: int i;int&& f();auto x2a(i); // decltype(x2a) is intdecltype(auto) x2d(i); // decltype(x2d) is intauto x3a = i; // decltype(x3a) is intdecltype(auto) x3d = i; // decltype(x3d) is intauto x4a = (i); // decltype(x4a) is intdecltype(auto) x4d = (i); // decltype(x4d) is int&auto x5a = f(); // decltype(x5a) is intdecltype(auto) x5d = f(); // decltype(x5d) is int&&auto x6a = { 1, 2 }; // decltype(x6a) is std::initializer_list<int>decltype(auto) x6d = { 1, 2 }; // error: { 1, 2 } is not an expressionauto *x7a = &i; // decltype(x7a) is int*decltype(auto)*x7d = &i; // error: declared type is not plain decltype(auto)auto f1(int x) -> decltype((x)) { return (x); } // return type is int&auto f2(int x) -> decltype(auto) { return (x); } // return type is int&& — *end example*]
[5](#dcl.type.auto.deduct-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L2244)
For a [*placeholder-type-specifier*](#nt:placeholder-type-specifier "9.2.9.7.1General[dcl.spec.auto.general]") with a [*type-constraint*](temp.param#nt:type-constraint "13.2Template parameters[temp.param]"),
the immediately-declared constraint ([[temp.param]](temp.param "13.2Template parameters"))
of the [*type-constraint*](temp.param#nt:type-constraint "13.2Template parameters[temp.param]") for the type deduced for the placeholder
shall be satisfied[.](#dcl.type.auto.deduct-5.sentence-1)

View File

@@ -0,0 +1,264 @@
[dcl.spec.auto.general]
# 9 Declarations [[dcl]](./#dcl)
## 9.2 Specifiers [[dcl.spec]](dcl.spec#auto.general)
### 9.2.9 Type specifiers [[dcl.type]](dcl.type#dcl.spec.auto.general)
#### 9.2.9.7 Placeholder type specifiers [[dcl.spec.auto]](dcl.spec.auto#general)
#### 9.2.9.7.1 General [dcl.spec.auto.general]
[placeholder-type-specifier:](#nt:placeholder-type-specifier "9.2.9.7.1General[dcl.spec.auto.general]")
[*type-constraint*](temp.param#nt:type-constraint "13.2Template parameters[temp.param]")opt auto
[*type-constraint*](temp.param#nt:type-constraint "13.2Template parameters[temp.param]")opt decltype ( auto )
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L1825)
A [*placeholder-type-specifier*](#nt:placeholder-type-specifier "9.2.9.7.1General[dcl.spec.auto.general]") designates a placeholder type that will be replaced later,
typically by deduction
from an initializer[.](#1.sentence-1)
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L1831)
The type of a [*parameter-declaration*](dcl.fct#nt:parameter-declaration "9.3.4.6Functions[dcl.fct]") of a
- [(2.1)](#2.1)
function declaration ([[dcl.fct]](dcl.fct "9.3.4.6Functions")),
- [(2.2)](#2.2)
[*lambda-expression*](expr.prim.lambda.general#nt:lambda-expression "7.5.6.1General[expr.prim.lambda.general]") ([[expr.prim.lambda]](expr.prim.lambda "7.5.6Lambda expressions")), or
- [(2.3)](#2.3)
[*template-parameter*](temp.param#nt:template-parameter "13.2Template parameters[temp.param]") ([[temp.param]](temp.param "13.2Template parameters"))
can be declared using
a [*placeholder-type-specifier*](#nt:placeholder-type-specifier "9.2.9.7.1General[dcl.spec.auto.general]") of the form[*type-constraint*](temp.param#nt:type-constraint "13.2Template parameters[temp.param]")opt auto[.](#2.sentence-1)
The placeholder type shall appear
as one of the [*decl-specifier*](dcl.spec.general#nt:decl-specifier "9.2.1General[dcl.spec.general]")*s* in
the [*decl-specifier-seq*](dcl.spec.general#nt:decl-specifier-seq "9.2.1General[dcl.spec.general]") or
as one of the [*type-specifier*](dcl.type.general#nt:type-specifier "9.2.9.1General[dcl.type.general]")*s* in
a [*trailing-return-type*](dcl.decl.general#nt:trailing-return-type "9.3.1General[dcl.decl.general]") that specifies the type that replaces such
a [*decl-specifier*](dcl.spec.general#nt:decl-specifier "9.2.1General[dcl.spec.general]") (see below);
the placeholder type
is a [*generic parameter type placeholder*](#def:generic_parameter_type_placeholder "9.2.9.7.1General[dcl.spec.auto.general]") of the
function declaration,[*lambda-expression*](expr.prim.lambda.general#nt:lambda-expression "7.5.6.1General[expr.prim.lambda.general]"), or[*template-parameter*](temp.param#nt:template-parameter "13.2Template parameters[temp.param]"), respectively[.](#2.sentence-2)
[*Note [1](#note-1)*:
Having a generic parameter type placeholder
signifies that the function is
an abbreviated function template ([[dcl.fct]](dcl.fct "9.3.4.6Functions")) or
the lambda is a generic lambda ([[expr.prim.lambda]](expr.prim.lambda "7.5.6Lambda expressions"))[.](#2.sentence-3)
— *end note*]
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L1861)
A placeholder type can appear in
the [*decl-specifier-seq*](dcl.spec.general#nt:decl-specifier-seq "9.2.1General[dcl.spec.general]") for a function declarator
that includes a [*trailing-return-type*](dcl.decl.general#nt:trailing-return-type "9.3.1General[dcl.decl.general]") ([[dcl.fct]](dcl.fct "9.3.4.6Functions"))[.](#3.sentence-1)
[4](#4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L1866)
A placeholder type can appear in
the [*decl-specifier-seq*](dcl.spec.general#nt:decl-specifier-seq "9.2.1General[dcl.spec.general]") or [*type-specifier-seq*](dcl.type.general#nt:type-specifier-seq "9.2.9.1General[dcl.type.general]") in the declared return type of a function declarator that declares a function;
the return type of the function is
deduced from non-discarded return statements, if any, in the body
of the function ([[stmt.if]](stmt.if "8.5.2The if statement"))[.](#4.sentence-1)
[5](#5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L1874)
The type of a variable declared using a placeholder type is
deduced from its initializer[.](#5.sentence-1)
This use is allowed
in an initializing declaration ([[dcl.init]](dcl.init "9.5Initializers")) of a variable[.](#5.sentence-2)
The placeholder type shall appear as one of the[*decl-specifier*](dcl.spec.general#nt:decl-specifier "9.2.1General[dcl.spec.general]")*s* in the [*decl-specifier-seq*](dcl.spec.general#nt:decl-specifier-seq "9.2.1General[dcl.spec.general]") or as one of the[*type-specifier*](dcl.type.general#nt:type-specifier "9.2.9.1General[dcl.type.general]")*s* in a [*trailing-return-type*](dcl.decl.general#nt:trailing-return-type "9.3.1General[dcl.decl.general]") that specifies the type that replaces such a [*decl-specifier*](dcl.spec.general#nt:decl-specifier "9.2.1General[dcl.spec.general]");
the [*decl-specifier-seq*](dcl.spec.general#nt:decl-specifier-seq "9.2.1General[dcl.spec.general]") shall be followed by one or more[*declarator*](dcl.decl.general#nt:declarator "9.3.1General[dcl.decl.general]")*s*,
each of which shall
be followed by a non-empty[*initializer*](dcl.init.general#nt:initializer "9.5.1General[dcl.init.general]")[.](#5.sentence-3)
[*Example [1](#example-1)*: auto x = 5; // OK, x has type intconst auto *v = &x, u = 6; // OK, v has type const int*, u has type const intstatic auto y = 0.0; // OK, y has type doubleauto int r; // error: auto is not a [*storage-class-specifier*](dcl.stc#nt:storage-class-specifier "9.2.2Storage class specifiers[dcl.stc]")auto f() -> int; // OK, f returns intauto g() { return 0.0; } // OK, g returns doubleauto (*fp)() -> auto = f; // OKauto h(); // OK, h's return type will be deduced when it is defined — *end example*]
The auto [*type-specifier*](dcl.type.general#nt:type-specifier "9.2.9.1General[dcl.type.general]") can also be used to introduce
a structured binding declaration ([[dcl.struct.bind]](dcl.struct.bind "9.7Structured binding declarations"))[.](#5.sentence-4)
[6](#6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L1906)
A placeholder type can also be used
in the [*type-specifier-seq*](dcl.type.general#nt:type-specifier-seq "9.2.9.1General[dcl.type.general]") of
the [*new-type-id*](expr.new#nt:new-type-id "7.6.2.8New[expr.new]") or
in the [*type-id*](dcl.name#nt:type-id "9.3.2Type names[dcl.name]") of a[*new-expression*](expr.new#nt:new-expression "7.6.2.8New[expr.new]") ([[expr.new]](expr.new "7.6.2.8New"))[.](#6.sentence-1)
In such a [*type-id*](dcl.name#nt:type-id "9.3.2Type names[dcl.name]"),
the placeholder type shall appear
as one of the [*type-specifier*](dcl.type.general#nt:type-specifier "9.2.9.1General[dcl.type.general]")*s* in
the [*type-specifier-seq*](dcl.type.general#nt:type-specifier-seq "9.2.9.1General[dcl.type.general]") or
as one of the [*type-specifier*](dcl.type.general#nt:type-specifier "9.2.9.1General[dcl.type.general]")*s* in
a [*trailing-return-type*](dcl.decl.general#nt:trailing-return-type "9.3.1General[dcl.decl.general]") that specifies the type that replaces such a [*type-specifier*](dcl.type.general#nt:type-specifier "9.2.9.1General[dcl.type.general]")[.](#6.sentence-2)
[7](#7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L1920)
The auto [*type-specifier*](dcl.type.general#nt:type-specifier "9.2.9.1General[dcl.type.general]") can also be used
as the [*simple-type-specifier*](dcl.type.simple#nt:simple-type-specifier "9.2.9.3Simple type specifiers[dcl.type.simple]") in an explicit type conversion (functional notation) ([[expr.type.conv]](expr.type.conv "7.6.1.4Explicit type conversion (functional notation)"))[.](#7.sentence-1)
[8](#8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L1925)
A program that uses a placeholder type in a context not
explicitly allowed in [[dcl.spec.auto]](dcl.spec.auto "9.2.9.7Placeholder type specifiers") is ill-formed[.](#8.sentence-1)
[9](#9)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L1929)
If the [*init-declarator-list*](dcl.decl.general#nt:init-declarator-list "9.3.1General[dcl.decl.general]") contains more than one[*init-declarator*](dcl.decl.general#nt:init-declarator "9.3.1General[dcl.decl.general]"), they shall all form declarations of
variables[.](#9.sentence-1)
The type of each declared variable is determined
by [placeholder type deduction](dcl.type.auto.deduct#def:placeholder_type_deduction "9.2.9.7.2Placeholder type deduction[dcl.type.auto.deduct]"),
and if the type that replaces the placeholder type is not the
same in each deduction, the program is ill-formed[.](#9.sentence-2)
[*Example [2](#example-2)*: auto x = 5, *y = &x; // OK, auto is intauto a = 5, b = { 1, 2 }; // error: different types for auto — *end example*]
[10](#10)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L1944)
If a function with a declared return type that contains a placeholder type has
multiple non-discarded return statements, the return type is deduced for each
such return statement[.](#10.sentence-1)
If the type deduced is not the same in each
deduction, the program is ill-formed[.](#10.sentence-2)
[11](#11)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L1950)
If a function with a declared return type that uses a placeholder type has no
non-discarded return statements, the return type is deduced as though from areturn statement with no operand at the closing brace of the function
body[.](#11.sentence-1)
[*Example [3](#example-3)*: auto f() { } // OK, return type is voidauto* g() { } // error: cannot deduce auto* from void() — *end example*]
[12](#12)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L1962)
An exported function
with a declared return type that uses a placeholder type
shall be defined in the translation unit
containing its exported declaration,
outside the [*private-module-fragment*](module.private.frag#nt:private-module-fragment "10.5Private module fragment[module.private.frag]") (if any)[.](#12.sentence-1)
[*Note [2](#note-2)*:
The deduced return type cannot have
a name with internal linkage ([[basic.link]](basic.link "6.7Program and linkage"))[.](#12.sentence-2)
— *end note*]
[13](#13)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L1973)
If a variable or function with an undeduced placeholder type is named by an
expression ([[basic.def.odr]](basic.def.odr "6.3One-definition rule")), the program is ill-formed[.](#13.sentence-1)
Once a
non-discarded return statement has been seen in a function, however, the return type deduced
from that statement can be used in the rest of the function, including in otherreturn statements[.](#13.sentence-2)
[*Example [4](#example-4)*: auto n = n; // error: n's initializer refers to nauto f();void g() { &f; } // error: f's return type is unknownauto sum(int i) {if (i == 1)return i; // sum's return type is intelsereturn sum(i-1)+i; // OK, sum's return type has been deduced} — *end example*]
[14](#14)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L1993)
A result binding never has
an undeduced placeholder type ([[dcl.contract.res]](dcl.contract.res "9.4.2Referring to the result object"))[.](#14.sentence-1)
[*Example [5](#example-5)*: auto f() post(r : r == 7) // OK{return 7;} — *end example*]
[15](#15)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L2007)
Return type deduction for a templated
function with a placeholder in its
declared type occurs when the definition is instantiated even if the function
body contains a return statement with a non-type-dependent operand[.](#15.sentence-1)
[*Note [3](#note-3)*:
Therefore, any use of a specialization of the function template will
cause an implicit instantiation[.](#15.sentence-2)
Any errors that arise from this instantiation
are not in the immediate context of the function type and can result in the
program being ill-formed ([[temp.deduct]](temp.deduct "13.10.3Template argument deduction"))[.](#15.sentence-3)
— *end note*]
[*Example [6](#example-6)*: template <class T> auto f(T t) { return t; } // return type deduced at instantiation timetypedef decltype(f(1)) fint_t; // instantiates f<int> to deduce return typetemplate<class T> auto f(T* t) { return *t; }void g() { int (*p)(int*) = &f; } // instantiates both fs to determine return types,// chooses second — *end example*]
[16](#16)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L2028)
If a function or function template F has
a declared return type that uses a placeholder type,
redeclarations or specializations of F shall use that
placeholder type, not a deduced type;
otherwise, they shall not use a placeholder type[.](#16.sentence-1)
[*Example [7](#example-7)*: auto f();auto f() { return 42; } // return type is intauto f(); // OKint f(); // error: auto and int don't matchdecltype(auto) f(); // error: auto and decltype(auto) don't matchtemplate <typename T> auto g(T t) { return t; } // #1template auto g(int); // OK, return type is inttemplate char g(char); // error: no matching templatetemplate<> auto g(double); // OK, forward declaration with unknown return typetemplate <class T> T g(T t) { return t; } // OK, not functionally equivalent to #1template char g(char); // OK, now there is a matching templatetemplate auto g(float); // still matches #1void h() { return g(42); } // error: ambiguoustemplate <typename T> struct A {friend T frf(T);};auto frf(int i) { return i; } // not a friend of A<int>extern int v;auto v = 17; // OK, redeclares vstruct S {static int i;};auto S::i = 23; // OK — *end example*]
[17](#17)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L2066)
A function declared with a return type that uses a placeholder type shall not
be virtual ([[class.virtual]](class.virtual "11.7.3Virtual functions"))[.](#17.sentence-1)
[18](#18)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L2070)
A function declared with a return type that uses a placeholder type shall not
be a coroutine ([[dcl.fct.def.coroutine]](dcl.fct.def.coroutine "9.6.4Coroutine definitions"))[.](#18.sentence-1)
[19](#19)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L2074)
An [explicit instantiation declaration](temp.explicit "13.9.3Explicit instantiation[temp.explicit]") does not cause the
instantiation of an entity declared using a placeholder type, but it also does
not prevent that entity from being instantiated as needed to determine its
type[.](#19.sentence-1)
[*Example [8](#example-8)*: template <typename T> auto f(T t) { return t; }extern template auto f(int); // does not instantiate f<int>int (*p)(int) = f; // instantiates f<int> to determine its return type, but an explicit// instantiation definition is still required somewhere in the program — *end example*]

View File

@@ -0,0 +1,82 @@
[dcl.spec.general]
# 9 Declarations [[dcl]](./#dcl)
## 9.2 Specifiers [[dcl.spec]](dcl.spec#general)
### 9.2.1 General [dcl.spec.general]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L431)
The specifiers that can be used in a declaration are
[decl-specifier:](#nt:decl-specifier "9.2.1General[dcl.spec.general]")
[*storage-class-specifier*](dcl.stc#nt:storage-class-specifier "9.2.2Storage class specifiers[dcl.stc]")
[*defining-type-specifier*](dcl.type.general#nt:defining-type-specifier "9.2.9.1General[dcl.type.general]")
[*function-specifier*](dcl.fct.spec#nt:function-specifier "9.2.3Function specifiers[dcl.fct.spec]")
friend
typedef
constexpr
consteval
constinit
inline
[decl-specifier-seq:](#nt:decl-specifier-seq "9.2.1General[dcl.spec.general]")
[*decl-specifier*](#nt:decl-specifier "9.2.1General[dcl.spec.general]") [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1Attribute syntax and semantics[dcl.attr.grammar]")opt
[*decl-specifier*](#nt:decl-specifier "9.2.1General[dcl.spec.general]") [*decl-specifier-seq*](#nt:decl-specifier-seq "9.2.1General[dcl.spec.general]")
The optional [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") in a [*decl-specifier-seq*](#nt:decl-specifier-seq "9.2.1General[dcl.spec.general]") appertains to the type determined by the preceding[*decl-specifier*](#nt:decl-specifier "9.2.1General[dcl.spec.general]")*s* ([[dcl.meaning]](dcl.meaning "9.3.4Meaning of declarators"))[.](#1.sentence-2)
The [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") affects the type only for the declaration it appears in, not other declarations involving the
same type[.](#1.sentence-3)
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L459)
At most one of each of the [*decl-specifier*](#nt:decl-specifier "9.2.1General[dcl.spec.general]")*s*friend, typedef, or inline shall appear in a [*decl-specifier-seq*](#nt:decl-specifier-seq "9.2.1General[dcl.spec.general]")[.](#2.sentence-1)
At most one of
the constexpr, consteval, and constinit keywords
shall appear in a [*decl-specifier-seq*](#nt:decl-specifier-seq "9.2.1General[dcl.spec.general]")[.](#2.sentence-2)
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L467)
If a [*type-name*](dcl.type.simple#nt:type-name "9.2.9.3Simple type specifiers[dcl.type.simple]") is encountered while parsing a [*decl-specifier-seq*](#nt:decl-specifier-seq "9.2.1General[dcl.spec.general]"),
it is interpreted as part of the [*decl-specifier-seq*](#nt:decl-specifier-seq "9.2.1General[dcl.spec.general]") if and only if there is no
previous [*defining-type-specifier*](dcl.type.general#nt:defining-type-specifier "9.2.9.1General[dcl.type.general]") other than a [*cv-qualifier*](dcl.decl.general#nt:cv-qualifier "9.3.1General[dcl.decl.general]") in the[*decl-specifier-seq*](#nt:decl-specifier-seq "9.2.1General[dcl.spec.general]")[.](#3.sentence-1)
The sequence shall be self-consistent as
described below[.](#3.sentence-2)
[*Example [1](#example-1)*: typedef char* Pc;static Pc; // error: name missing
Here, the declaration static Pc is ill-formed because no
name was specified for the static variable of type Pc[.](#3.sentence-3)
To get a
variable called Pc, a [*type-specifier*](dcl.type.general#nt:type-specifier "9.2.9.1General[dcl.type.general]") (other thanconst or volatile) has to be present to indicate that
the [*typedef-name*](dcl.typedef#nt:typedef-name "9.2.4The typedef specifier[dcl.typedef]") Pc is the name being (re)declared,
rather than being part of the [*decl-specifier*](#nt:decl-specifier "9.2.1General[dcl.spec.general]") sequence[.](#3.sentence-4)
For
another example,void f(const Pc); // void f(char* const) (not const char*)void g(const int Pc); // void g(const int)
— *end example*]
[4](#4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L493)
[*Note [1](#note-1)*:
Since signed, unsigned, long, and short by default imply int, a [*type-name*](dcl.type.simple#nt:type-name "9.2.9.3Simple type specifiers[dcl.type.simple]") appearing after one
of those specifiers is treated as the name being (re)declared[.](#4.sentence-1)
[*Example [2](#example-2)*: void h(unsigned Pc); // void h(unsigned int)void k(unsigned int Pc); // void k(unsigned int) — *end example*]
— *end note*]

157
cppdraft/dcl/stc.md Normal file
View File

@@ -0,0 +1,157 @@
[dcl.stc]
# 9 Declarations [[dcl]](./#dcl)
## 9.2 Specifiers [[dcl.spec]](dcl.spec#dcl.stc)
### 9.2.2 Storage class specifiers [dcl.stc]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L518)
The storage class specifiers are
[storage-class-specifier:](#nt:storage-class-specifier "9.2.2Storage class specifiers[dcl.stc]")
static
thread_local
extern
mutable
At most one [*storage-class-specifier*](#nt:storage-class-specifier "9.2.2Storage class specifiers[dcl.stc]") shall appear in a given[*decl-specifier-seq*](dcl.spec.general#nt:decl-specifier-seq "9.2.1General[dcl.spec.general]"), except that thread_local may appear with static orextern[.](#1.sentence-2)
If thread_local appears in any declaration of
a variable it shall be present in all declarations of that entity[.](#1.sentence-3)
If a[*storage-class-specifier*](#nt:storage-class-specifier "9.2.2Storage class specifiers[dcl.stc]") appears in a [*decl-specifier-seq*](dcl.spec.general#nt:decl-specifier-seq "9.2.1General[dcl.spec.general]"), there can be notypedef specifier in the same [*decl-specifier-seq*](dcl.spec.general#nt:decl-specifier-seq "9.2.1General[dcl.spec.general]") and
the [*init-declarator-list*](dcl.decl.general#nt:init-declarator-list "9.3.1General[dcl.decl.general]") or [*member-declarator-list*](class.mem.general#nt:member-declarator-list "11.4.1General[class.mem.general]") of the declaration shall not be
empty (except for an anonymous union declared in a namespace scope ([[class.union.anon]](class.union.anon "11.5.2Anonymous unions")))[.](#1.sentence-4)
The[*storage-class-specifier*](#nt:storage-class-specifier "9.2.2Storage class specifiers[dcl.stc]") applies to the name declared by each[*init-declarator*](dcl.decl.general#nt:init-declarator "9.3.1General[dcl.decl.general]") in the list and not to any names declared by
other specifiers[.](#1.sentence-5)
[*Note [1](#note-1)*:
See [[temp.expl.spec]](temp.expl.spec "13.9.4Explicit specialization") and [[temp.explicit]](temp.explicit "13.9.3Explicit instantiation") for restrictions
in explicit specializations and explicit instantiations, respectively[.](#1.sentence-6)
— *end note*]
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L546)
[*Note [2](#note-2)*:
A variable declared without a [*storage-class-specifier*](#nt:storage-class-specifier "9.2.2Storage class specifiers[dcl.stc]") at block scope or declared as a function parameter
has [automatic storage duration](basic.stc.auto#def:storage_duration,automatic "6.8.6.4Automatic storage duration[basic.stc.auto]") by default[.](#2.sentence-1)
— *end note*]
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L553)
The thread_local specifier
indicates that the named entity has thread storage duration ([[basic.stc.thread]](basic.stc.thread "6.8.6.3Thread storage duration"))[.](#3.sentence-1)
It
shall be applied only
to the declaration of a variable of namespace or block scope,
to a structured binding declaration ([[dcl.struct.bind]](dcl.struct.bind "9.7Structured binding declarations")), or
to the declaration of a static data member[.](#3.sentence-2)
When thread_local is applied to a variable of block scope the[*storage-class-specifier*](#nt:storage-class-specifier "9.2.2Storage class specifiers[dcl.stc]") static is implied if no other[*storage-class-specifier*](#nt:storage-class-specifier "9.2.2Storage class specifiers[dcl.stc]") appears in the[*decl-specifier-seq*](dcl.spec.general#nt:decl-specifier-seq "9.2.1General[dcl.spec.general]")[.](#3.sentence-3)
[4](#4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L565)
The static specifier shall be applied only
to the declaration of a variable or function,
to a structured binding declaration ([[dcl.struct.bind]](dcl.struct.bind "9.7Structured binding declarations")), or
to the declaration of an anonymous union ([[class.union.anon]](class.union.anon "11.5.2Anonymous unions"))[.](#4.sentence-1)
There can be nostatic function declarations within a block, nor anystatic function parameters[.](#4.sentence-2)
A static specifier used in
the declaration of a variable declares the variable to have static storage
duration ([[basic.stc.static]](basic.stc.static "6.8.6.2Static storage duration")), unless accompanied by thethread_local specifier, which declares the variable to have thread
storage duration ([[basic.stc.thread]](basic.stc.thread "6.8.6.3Thread storage duration"))[.](#4.sentence-3)
A static specifier can be
used in declarations of class members; [[class.static]](class.static "11.4.9Static members") describes its
effect[.](#4.sentence-4)
For the linkage of a name declared with a static specifier,
see [[basic.link]](basic.link "6.7Program and linkage")[.](#4.sentence-5)
[5](#5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L584)
The extern specifier shall be applied only to the declaration of a variable
or function[.](#5.sentence-1)
The extern specifier shall not be used in the
declaration of a class member or function parameter[.](#5.sentence-2)
For the linkage of a name declared with an extern specifier,
see [[basic.link]](basic.link "6.7Program and linkage")[.](#5.sentence-3)
[*Note [3](#note-3)*:
The extern keyword can also be used in[*explicit-instantiation*](temp.explicit#nt:explicit-instantiation "13.9.3Explicit instantiation[temp.explicit]")*s* and[*linkage-specification*](dcl.link#nt:linkage-specification "9.12Linkage specifications[dcl.link]")*s*, but it is not a[*storage-class-specifier*](#nt:storage-class-specifier "9.2.2Storage class specifiers[dcl.stc]") in such contexts[.](#5.sentence-4)
— *end note*]
[6](#6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L600)
All declarations for a given entity shall give its name the same linkage[.](#6.sentence-1)
[*Note [4](#note-4)*:
The linkage given by some declarations is affected by previous declarations[.](#6.sentence-2)
Overloads are distinct entities[.](#6.sentence-3)
— *end note*]
[*Example [1](#example-1)*: static char* f(); // f() has internal linkagechar* f() // f() still has internal linkage{ /* ... */ }char* g(); // g() has external linkagestatic char* g() // error: inconsistent linkage{ /* ... */ }void h();inline void h(); // external linkageinline void l();void l(); // external linkageinline void m();extern void m(); // external linkagestatic void n();inline void n(); // internal linkagestatic int a; // a has internal linkageint a; // error: two definitionsstatic int b; // b has internal linkageextern int b; // b still has internal linkageint c; // c has external linkagestatic int c; // error: inconsistent linkageextern int d; // d has external linkagestatic int d; // error: inconsistent linkage — *end example*]
[7](#7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L642)
The name of a declared but undefined class can be used in anextern declaration[.](#7.sentence-1)
Such a declaration can only be used in ways
that do not require a complete class type[.](#7.sentence-2)
[*Example [2](#example-2)*: struct S;extern S a;extern S f();extern void g(S);
void h() { g(a); // error: S is incomplete f(); // error: S is incomplete} — *end example*]
[8](#8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L661)
The mutable specifier shall appear only in the declaration of
a non-static data member ([[class.mem]](class.mem "11.4Class members"))
whose type is neither const-qualified nor a reference type[.](#8.sentence-1)
[*Example [3](#example-3)*: class X {mutable const int* p; // OKmutable int* const q; // error}; — *end example*]
[9](#9)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L674)
[*Note [5](#note-5)*:
The mutable specifier on a class data member nullifies aconst specifier applied to the containing class object and
permits modification of the mutable class member even though the rest of
the object is const ([[basic.type.qualifier]](basic.type.qualifier "6.9.5CV-qualifiers"), [[dcl.type.cv]](dcl.type.cv "9.2.9.2The cv-qualifiers"))[.](#9.sentence-1)
— *end note*]

215
cppdraft/dcl/struct/bind.md Normal file
View File

@@ -0,0 +1,215 @@
[dcl.struct.bind]
# 9 Declarations [[dcl]](./#dcl)
## 9.7 Structured binding declarations [dcl.struct.bind]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L7580)
A structured binding declaration introduces the [*identifier*](lex.name#nt:identifier "5.11Identifiers[lex.name]")*s*v0, v1, v2,…,vN−1 of the[*sb-identifier-list*](dcl.pre#nt:sb-identifier-list "9.1Preamble[dcl.pre]") as names[.](#1.sentence-1)
An [*sb-identifier*](dcl.pre#nt:sb-identifier "9.1Preamble[dcl.pre]") that contains an ellipsis
introduces a structured binding pack ([[temp.variadic]](temp.variadic "13.7.4Variadic templates"))[.](#1.sentence-2)
A [*structured binding*](#def:structured_binding "9.7Structured binding declarations[dcl.struct.bind]") is either
an [*sb-identifier*](dcl.pre#nt:sb-identifier "9.1Preamble[dcl.pre]") that does not contain an ellipsis or
an element of a structured binding pack[.](#1.sentence-3)
The optional [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") of
an [*sb-identifier*](dcl.pre#nt:sb-identifier "9.1Preamble[dcl.pre]") appertains to the associated structured bindings[.](#1.sentence-4)
Let cv denote the [*cv-qualifier*](dcl.decl.general#nt:cv-qualifier "9.3.1General[dcl.decl.general]")*s* in
the [*decl-specifier-seq*](dcl.spec.general#nt:decl-specifier-seq "9.2.1General[dcl.spec.general]") and*S* consist of
each [*decl-specifier*](dcl.spec.general#nt:decl-specifier "9.2.1General[dcl.spec.general]") of the [*decl-specifier-seq*](dcl.spec.general#nt:decl-specifier-seq "9.2.1General[dcl.spec.general]") that is constexpr, constinit, or
a [*storage-class-specifier*](dcl.stc#nt:storage-class-specifier "9.2.2Storage class specifiers[dcl.stc]")[.](#1.sentence-5)
A cv that includes volatile is deprecated;
see [[depr.volatile.type]](depr.volatile.type "D.4Deprecated volatile types")[.](#1.sentence-6)
First, a variable with a unique name *e* is introduced[.](#1.sentence-7)
If the[*assignment-expression*](expr.assign#nt:assignment-expression "7.6.19Assignment and compound assignment operators[expr.assign]") in the [*initializer*](dcl.init.general#nt:initializer "9.5.1General[dcl.init.general]") has array type *cv1* A and no [*ref-qualifier*](dcl.decl.general#nt:ref-qualifier "9.3.1General[dcl.decl.general]") is present,*e* is defined by
[*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1Attribute syntax and semantics[dcl.attr.grammar]")opt *S* cv A *e* ;
and each element is copy-initialized or direct-initialized
from the corresponding element of the [*assignment-expression*](expr.assign#nt:assignment-expression "7.6.19Assignment and compound assignment operators[expr.assign]") as specified
by the form of the [*initializer*](dcl.init.general#nt:initializer "9.5.1General[dcl.init.general]")[.](#1.sentence-8)
Otherwise, *e* is defined as-if by
[*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1Attribute syntax and semantics[dcl.attr.grammar]")opt [*decl-specifier-seq*](dcl.spec.general#nt:decl-specifier-seq "9.2.1General[dcl.spec.general]") [*ref-qualifier*](dcl.decl.general#nt:ref-qualifier "9.3.1General[dcl.decl.general]")opt *e* [*initializer*](dcl.init.general#nt:initializer "9.5.1General[dcl.init.general]") ;
where
the declaration is never interpreted as a function declaration and
the parts of the declaration other than the [*declarator-id*](dcl.decl.general#nt:declarator-id "9.3.1General[dcl.decl.general]") are taken
from the corresponding structured binding declaration[.](#1.sentence-9)
The type of the [*id-expression*](expr.prim.id.general#nt:id-expression "7.5.5.1General[expr.prim.id.general]")*e* is called E[.](#1.sentence-10)
[*Note [1](#note-1)*:
E is never a reference type ([[expr.prop]](expr.prop "7.2Properties of expressions"))[.](#1.sentence-11)
— *end note*]
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L7626)
The [*structured binding size*](#def:structured_binding_size "9.7Structured binding declarations[dcl.struct.bind]") of E, as defined below,
is the number of structured bindings
that need to be introduced by the structured binding declaration[.](#2.sentence-1)
If there is no structured binding pack,
then the number of elements in the [*sb-identifier-list*](dcl.pre#nt:sb-identifier-list "9.1Preamble[dcl.pre]") shall be equal to the structured binding size of E[.](#2.sentence-2)
Otherwise, the number of non-pack elements shall be no more than
the structured binding size of E;
the number of elements of the structured binding pack is
the structured binding size of E less
the number of non-pack elements in the [*sb-identifier-list*](dcl.pre#nt:sb-identifier-list "9.1Preamble[dcl.pre]")[.](#2.sentence-3)
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L7639)
Let SBi denote
the ith structured binding in the structured binding declaration
after expanding the structured binding pack, if any[.](#3.sentence-1)
[*Note [2](#note-2)*:
If there is no structured binding pack,
then SBi denotes vi[.](#3.sentence-2)
— *end note*]
[*Example [1](#example-1)*: struct C { int x, y, z; };
template<class T>void now_i_know_my() {auto [a, b, c] = C(); // OK, SB0 is a, SB1 is b, and SB2 is cauto [d, ...e] = C(); // OK, SB0 is d, the pack e (v1) contains two structured bindings: SB1 and SB2auto [...f, g] = C(); // OK, the pack f (v0) contains two structured bindings: SB0 and SB1, and SB2 is gauto [h, i, j, ...k] = C(); // OK, the pack k is emptyauto [l, m, n, o, ...p] = C(); // error: structured binding size is too small} — *end example*]
[4](#4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L7662)
If a structured binding declaration appears as a [*condition*](stmt.pre#nt:condition "8.1Preamble[stmt.pre]"),
the decision variable ([[stmt.pre]](stmt.pre "8.1Preamble")) of the condition is *e*[.](#4.sentence-1)
[5](#5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L7666)
If the [*initializer*](dcl.init.general#nt:initializer "9.5.1General[dcl.init.general]") refers to
one of the names introduced by the structured binding declaration,
the program is ill-formed[.](#5.sentence-1)
[6](#6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L7671)
E shall not be an array type of unknown bound[.](#6.sentence-1)
If E is any other array type with element type T,
the structured binding size of E is equal to the
number of elements of E[.](#6.sentence-2)
Each SBi is the name of an
lvalue that refers to the element i of the array and whose type
is T; the referenced type is T[.](#6.sentence-3)
[*Note [3](#note-3)*:
The top-level cv-qualifiers of T are cv[.](#6.sentence-4)
— *end note*]
[*Example [2](#example-2)*: auto f() -> int(&)[2];auto [ x, y ] = f(); // x and y refer to elements in a copy of the array return valueauto& [ xr, yr ] = f(); // xr and yr refer to elements in the array referred to by f's return valueauto g() -> int(&)[4];
template<size_t N>void h(int (&arr)[N]) {auto [a, ...b, c] = arr; // a names the first element of the array, b is a pack referring to the second and// third elements, and c names the fourth elementauto& [...e] = arr; // e is a pack referring to the four elements of the array}void call_h() { h(g());} — *end example*]
[7](#7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L7703)
Otherwise, if
the [*qualified-id*](expr.prim.id.qual#nt:qualified-id "7.5.5.3Qualified names[expr.prim.id.qual]") std::tuple_size<E> names a complete class type with a member named value,
the expression std::tuple_size<E>::value shall be a well-formed integral constant expression
and
the structured binding size of E is equal to the value of that
expression[.](#7.sentence-1)
Let i be an index prvalue of type std::size_t corresponding to vi[.](#7.sentence-2)
If a search for the name get in the scope of E ([[class.member.lookup]](class.member.lookup "6.5.2Member name lookup"))
finds at least one declaration
that is a function template whose first template parameter
is a constant template parameter,
the initializer is*e*.get<i>()[.](#7.sentence-3)
Otherwise, the initializer is get<i>(*e*),
where get undergoes argument-dependent lookup ([[basic.lookup.argdep]](basic.lookup.argdep "6.5.4Argument-dependent name lookup"))[.](#7.sentence-4)
In either case, get<i> is interpreted as a [*template-id*](temp.names#nt:template-id "13.3Names of template specializations[temp.names]")[.](#7.sentence-5)
[*Note [4](#note-4)*:
Ordinary [unqualified lookup](basic.lookup.unqual "6.5.3Unqualified name lookup[basic.lookup.unqual]") is not performed[.](#7.sentence-6)
— *end note*]
In either case, *e* is an lvalue if the type of the entity *e* is an lvalue reference and an xvalue otherwise[.](#7.sentence-7)
Given the type Ti designated bystd::tuple_element<i, E>::type and
the type Ui designated by
either Ti& or Ti&&,
where Ui is an lvalue reference if
the initializer is an lvalue and an rvalue reference otherwise,
variables are introduced with unique names ri as follows:
*S* Ui ri = [*initializer*](dcl.init.general#nt:initializer "9.5.1General[dcl.init.general]") ;
Each SBi is the name of an lvalue of type Ti that refers to the object bound to ri;
the referenced type is Ti[.](#7.sentence-9)
The initialization of *e* and
any conversion of *e* considered as a decision variable ([[stmt.pre]](stmt.pre "8.1Preamble"))
is
sequenced before the initialization of any ri[.](#7.sentence-10)
The initialization of each ri is
sequenced before the initialization of any rj where i<j[.](#7.sentence-11)
[8](#8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L7749)
Otherwise,
all of E's non-static data members
shall be direct members of E or
of the same base class of E,
well-formed when named as *e*.*name* in the context of the structured binding,E shall not have an anonymous union member, and
the structured binding size of E is
equal to the number of non-static data members of E[.](#8.sentence-1)
Designating the non-static data members of E asm0, m1, m2,… (in declaration order),
each SBi is the
name of an lvalue that refers to the member mi of *e* and
whose type is
that of *e*.mi ([[expr.ref]](expr.ref "7.6.1.5Class member access"));
the referenced type is
the declared type of mi if that type is a reference type, or
the type of *e*.mi otherwise[.](#8.sentence-2)
The lvalue is a
bit-field if that member is a bit-field[.](#8.sentence-3)
[*Example [3](#example-3)*: struct S { mutable int x1 : 2; volatile double y1; };
S f();const auto [ x, y ] = f();
The type of the [*id-expression*](expr.prim.id.general#nt:id-expression "7.5.5.1General[expr.prim.id.general]") x is “int”,
the type of the [*id-expression*](expr.prim.id.general#nt:id-expression "7.5.5.1General[expr.prim.id.general]") y is “const volatile double”[.](#8.sentence-4)
— *end example*]

1121
cppdraft/dcl/type.md Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,157 @@
[dcl.type.auto.deduct]
# 9 Declarations [[dcl]](./#dcl)
## 9.2 Specifiers [[dcl.spec]](dcl.spec#dcl.type.auto.deduct)
### 9.2.9 Type specifiers [[dcl.type]](dcl.type#auto.deduct)
#### 9.2.9.7 Placeholder type specifiers [[dcl.spec.auto]](dcl.spec.auto#dcl.type.auto.deduct)
#### 9.2.9.7.2 Placeholder type deduction [dcl.type.auto.deduct]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L2091)
[*Placeholder type deduction*](#def:placeholder_type_deduction "9.2.9.7.2Placeholder type deduction[dcl.type.auto.deduct]") is the process by which
a type containing a placeholder type
is replaced by a deduced type[.](#1.sentence-1)
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L2097)
A type T containing a placeholder type,
and a corresponding [*initializer-clause*](dcl.init.general#nt:initializer-clause "9.5.1General[dcl.init.general]") E,
are determined as follows:
- [(2.1)](#2.1)
For a non-discarded return statement that occurs
in a function declared with a return type
that contains a placeholder type,T is the declared return type[.](#2.1.sentence-1)
* [(2.1.1)](#2.1.1)
If the return statement has no operand,
then E is void()[.](#2.1.1.sentence-1)
* [(2.1.2)](#2.1.2)
If the operand is a [*braced-init-list*](dcl.init.general#nt:braced-init-list "9.5.1General[dcl.init.general]") ([[dcl.init.list]](dcl.init.list "9.5.5List-initialization")),
the program is ill-formed[.](#2.1.2.sentence-1)
* [(2.1.3)](#2.1.3)
If the operand is an [*expression*](expr.comma#nt:expression "7.6.20Comma operator[expr.comma]") X that is not an [*assignment-expression*](expr.assign#nt:assignment-expression "7.6.19Assignment and compound assignment operators[expr.assign]"),E is (X)[.](#2.1.3.sentence-1)
[*Note [1](#note-1)*:
A comma expression ([[expr.comma]](expr.comma "7.6.20Comma operator")) is not
an [*assignment-expression*](expr.assign#nt:assignment-expression "7.6.19Assignment and compound assignment operators[expr.assign]")[.](#2.1.3.sentence-2)
— *end note*]
* [(2.1.4)](#2.1.4)
Otherwise, E is the operand of the return statement[.](#2.1.4.sentence-1)
If E has type void,T shall be either[*type-constraint*](temp.param#nt:type-constraint "13.2Template parameters[temp.param]")opt decltype(auto) orcv [*type-constraint*](temp.param#nt:type-constraint "13.2Template parameters[temp.param]")opt auto[.](#2.1.sentence-2)
- [(2.2)](#2.2)
For a variable declared with a type
that contains a placeholder type,T is the declared type of the variable[.](#2.2.sentence-1)
* [(2.2.1)](#2.2.1)
If the initializer of the variable is a [*brace-or-equal-initializer*](dcl.init.general#nt:brace-or-equal-initializer "9.5.1General[dcl.init.general]") of the form = [*initializer-clause*](dcl.init.general#nt:initializer-clause "9.5.1General[dcl.init.general]"),E is the [*initializer-clause*](dcl.init.general#nt:initializer-clause "9.5.1General[dcl.init.general]")[.](#2.2.1.sentence-1)
* [(2.2.2)](#2.2.2)
If the initializer is a [*braced-init-list*](dcl.init.general#nt:braced-init-list "9.5.1General[dcl.init.general]"),
it shall consist of a single brace-enclosed [*assignment-expression*](expr.assign#nt:assignment-expression "7.6.19Assignment and compound assignment operators[expr.assign]") and E is the [*assignment-expression*](expr.assign#nt:assignment-expression "7.6.19Assignment and compound assignment operators[expr.assign]")[.](#2.2.2.sentence-1)
* [(2.2.3)](#2.2.3)
If the initializer is a parenthesized [*expression-list*](expr.post.general#nt:expression-list "7.6.1.1General[expr.post.general]"),
the [*expression-list*](expr.post.general#nt:expression-list "7.6.1.1General[expr.post.general]") shall be
a single [*assignment-expression*](expr.assign#nt:assignment-expression "7.6.19Assignment and compound assignment operators[expr.assign]") and E is the [*assignment-expression*](expr.assign#nt:assignment-expression "7.6.19Assignment and compound assignment operators[expr.assign]")[.](#2.2.3.sentence-1)
- [(2.3)](#2.3)
For an explicit type conversion ([[expr.type.conv]](expr.type.conv "7.6.1.4Explicit type conversion (functional notation)")),T is the specified type, which shall be auto[.](#2.3.sentence-1)
* [(2.3.1)](#2.3.1)
If the initializer is a [*braced-init-list*](dcl.init.general#nt:braced-init-list "9.5.1General[dcl.init.general]"),
it shall consist of a single brace-enclosed [*assignment-expression*](expr.assign#nt:assignment-expression "7.6.19Assignment and compound assignment operators[expr.assign]") and E is the [*assignment-expression*](expr.assign#nt:assignment-expression "7.6.19Assignment and compound assignment operators[expr.assign]")[.](#2.3.1.sentence-1)
* [(2.3.2)](#2.3.2)
If the initializer is a parenthesized [*expression-list*](expr.post.general#nt:expression-list "7.6.1.1General[expr.post.general]"),
the [*expression-list*](expr.post.general#nt:expression-list "7.6.1.1General[expr.post.general]") shall be
a single [*assignment-expression*](expr.assign#nt:assignment-expression "7.6.19Assignment and compound assignment operators[expr.assign]") and E is the [*assignment-expression*](expr.assign#nt:assignment-expression "7.6.19Assignment and compound assignment operators[expr.assign]")[.](#2.3.2.sentence-1)
- [(2.4)](#2.4)
For a constant template parameter declared with a type
that contains a placeholder type,T is the declared type of the constant template parameter
and E is the corresponding template argument[.](#2.4.sentence-1)
T shall not be an array type[.](#2.sentence-2)
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L2171)
If the [*placeholder-type-specifier*](dcl.spec.auto.general#nt:placeholder-type-specifier "9.2.9.7.1General[dcl.spec.auto.general]") is of the form[*type-constraint*](temp.param#nt:type-constraint "13.2Template parameters[temp.param]")opt auto,
the deduced typeT′ replacing T is determined using the rules for template argument deduction[.](#3.sentence-1)
If the initialization is copy-list-initialization,
a declaration of std::initializer_list shall precede ([[basic.lookup.general]](basic.lookup.general "6.5.1General"))
the [*placeholder-type-specifier*](dcl.spec.auto.general#nt:placeholder-type-specifier "9.2.9.7.1General[dcl.spec.auto.general]")[.](#3.sentence-2)
Obtain P fromT by replacing the occurrence of[*type-constraint*](temp.param#nt:type-constraint "13.2Template parameters[temp.param]")opt auto either with
a new invented type template parameter U or,
if the initialization is copy-list-initialization, withstd::initializer_list<U>[.](#3.sentence-3)
Deduce a value for U using the rules
of [template argument deduction from a function call](temp.deduct.call "13.10.3.2Deducing template arguments from a function call[temp.deduct.call]"),
where P is a
function template parameter type and
the corresponding argument is E[.](#3.sentence-4)
If the deduction fails, the declaration is ill-formed[.](#3.sentence-5)
Otherwise, T′ is obtained by
substituting the deduced U into P[.](#3.sentence-6)
[*Example [1](#example-1)*: auto x1 = { 1, 2 }; // decltype(x1) is std::initializer_list<int>auto x2 = { 1, 2.0 }; // error: cannot deduce element typeauto x3{ 1, 2 }; // error: not a single elementauto x4 = { 3 }; // decltype(x4) is std::initializer_list<int>auto x5{ 3 }; // decltype(x5) is int — *end example*]
[*Example [2](#example-2)*: const auto &i = expr;
The type of i is the deduced type of the parameter u in
the call f(expr) of the following invented function template:template <class U> void f(const U& u);
— *end example*]
[4](#4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L2215)
If the [*placeholder-type-specifier*](dcl.spec.auto.general#nt:placeholder-type-specifier "9.2.9.7.1General[dcl.spec.auto.general]") is of the form[*type-constraint*](temp.param#nt:type-constraint "13.2Template parameters[temp.param]")opt decltype(auto),T shall be the
placeholder alone[.](#4.sentence-1)
The type deduced for T is
determined as described in [[dcl.type.decltype]](dcl.type.decltype "9.2.9.6Decltype specifiers"), as thoughE had
been the operand of the decltype[.](#4.sentence-2)
[*Example [3](#example-3)*: int i;int&& f();auto x2a(i); // decltype(x2a) is intdecltype(auto) x2d(i); // decltype(x2d) is intauto x3a = i; // decltype(x3a) is intdecltype(auto) x3d = i; // decltype(x3d) is intauto x4a = (i); // decltype(x4a) is intdecltype(auto) x4d = (i); // decltype(x4d) is int&auto x5a = f(); // decltype(x5a) is intdecltype(auto) x5d = f(); // decltype(x5d) is int&&auto x6a = { 1, 2 }; // decltype(x6a) is std::initializer_list<int>decltype(auto) x6d = { 1, 2 }; // error: { 1, 2 } is not an expressionauto *x7a = &i; // decltype(x7a) is int*decltype(auto)*x7d = &i; // error: declared type is not plain decltype(auto)auto f1(int x) -> decltype((x)) { return (x); } // return type is int&auto f2(int x) -> decltype(auto) { return (x); } // return type is int&& — *end example*]
[5](#5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L2244)
For a [*placeholder-type-specifier*](dcl.spec.auto.general#nt:placeholder-type-specifier "9.2.9.7.1General[dcl.spec.auto.general]") with a [*type-constraint*](temp.param#nt:type-constraint "13.2Template parameters[temp.param]"),
the immediately-declared constraint ([[temp.param]](temp.param "13.2Template parameters"))
of the [*type-constraint*](temp.param#nt:type-constraint "13.2Template parameters[temp.param]") for the type deduced for the placeholder
shall be satisfied[.](#5.sentence-1)

View File

@@ -0,0 +1,51 @@
[dcl.type.class.deduct]
# 9 Declarations [[dcl]](./#dcl)
## 9.2 Specifiers [[dcl.spec]](dcl.spec#dcl.type.class.deduct)
### 9.2.9 Type specifiers [[dcl.type]](dcl.type#class.deduct)
#### 9.2.9.8 Deduced class template specialization types [dcl.type.class.deduct]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L2254)
If a placeholder for a deduced class type
appears as a [*decl-specifier*](dcl.spec.general#nt:decl-specifier "9.2.1General[dcl.spec.general]") in the [*decl-specifier-seq*](dcl.spec.general#nt:decl-specifier-seq "9.2.1General[dcl.spec.general]") of an initializing declaration ([[dcl.init]](dcl.init "9.5Initializers")) of a variable,
the declared type of the variable shall be cv T,
where T is the placeholder[.](#1.sentence-1)
[*Example [1](#example-1)*: template <class ...T> struct A { A(T...) {}};
A x[29]{}; // error: no declarator operators allowedconst A& y{}; // error: no declarator operators allowed — *end example*]
The placeholder is replaced by the return type
of the function selected by overload resolution
for class template deduction ([[over.match.class.deduct]](over.match.class.deduct "12.2.2.9Class template argument deduction"))[.](#1.sentence-2)
If the [*decl-specifier-seq*](dcl.spec.general#nt:decl-specifier-seq "9.2.1General[dcl.spec.general]") is followed by an [*init-declarator-list*](dcl.decl.general#nt:init-declarator-list "9.3.1General[dcl.decl.general]") or [*member-declarator-list*](class.mem.general#nt:member-declarator-list "11.4.1General[class.mem.general]") containing more than one [*declarator*](dcl.decl.general#nt:declarator "9.3.1General[dcl.decl.general]"),
the type that replaces the placeholder shall be the same in each deduction[.](#1.sentence-3)
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L2279)
A placeholder for a deduced class type
can also be used
in the [*type-specifier-seq*](dcl.type.general#nt:type-specifier-seq "9.2.9.1General[dcl.type.general]") in the [*new-type-id*](expr.new#nt:new-type-id "7.6.2.8New[expr.new]") or [*type-id*](dcl.name#nt:type-id "9.3.2Type names[dcl.name]") of a [*new-expression*](expr.new#nt:new-expression "7.6.2.8New[expr.new]") ([[expr.new]](expr.new "7.6.2.8New")),
as the [*simple-type-specifier*](dcl.type.simple#nt:simple-type-specifier "9.2.9.3Simple type specifiers[dcl.type.simple]") in an [explicit type conversion (functional notation)](expr.type.conv "7.6.1.4Explicit type conversion (functional notation)[expr.type.conv]"),
or
as the [*type-specifier*](dcl.type.general#nt:type-specifier "9.2.9.1General[dcl.type.general]") in the [*parameter-declaration*](dcl.fct#nt:parameter-declaration "9.3.4.6Functions[dcl.fct]") of a [*template-parameter*](temp.param#nt:template-parameter "13.2Template parameters[temp.param]") ([[temp.param]](temp.param "13.2Template parameters"))[.](#2.sentence-1)
A placeholder for a deduced class type
shall not appear in any other context[.](#2.sentence-2)
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L2293)
[*Example [2](#example-2)*: template<class T> struct container { container(T t) {}template<class Iter> container(Iter beg, Iter end);};template<class Iter> container(Iter b, Iter e) -> container<typename std::iterator_traits<Iter>::value_type>;
std::vector<double> v = { /* ... */ };
container c(7); // OK, deduces int for Tauto d = container(v.begin(), v.end()); // OK, deduces double for T container e{5, 6}; // error: int is not an iterator — *end example*]

120
cppdraft/dcl/type/cv.md Normal file
View File

@@ -0,0 +1,120 @@
[dcl.type.cv]
# 9 Declarations [[dcl]](./#dcl)
## 9.2 Specifiers [[dcl.spec]](dcl.spec#dcl.type.cv)
### 9.2.9 Type specifiers [[dcl.type]](dcl.type#cv)
#### 9.2.9.2 The *cv-qualifier**s* [dcl.type.cv]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L1266)
There are two [*cv-qualifier*](dcl.decl.general#nt:cv-qualifier "9.3.1General[dcl.decl.general]")*s*, const andvolatile[.](#1.sentence-1)
Each [*cv-qualifier*](dcl.decl.general#nt:cv-qualifier "9.3.1General[dcl.decl.general]") shall appear at most once in
a [*cv-qualifier-seq*](dcl.decl.general#nt:cv-qualifier-seq "9.3.1General[dcl.decl.general]")[.](#1.sentence-2)
If a [*cv-qualifier*](dcl.decl.general#nt:cv-qualifier "9.3.1General[dcl.decl.general]") appears in a[*decl-specifier-seq*](dcl.spec.general#nt:decl-specifier-seq "9.2.1General[dcl.spec.general]"), the [*init-declarator-list*](dcl.decl.general#nt:init-declarator-list "9.3.1General[dcl.decl.general]") or [*member-declarator-list*](class.mem.general#nt:member-declarator-list "11.4.1General[class.mem.general]") of
the declaration shall not be empty[.](#1.sentence-3)
[*Note [1](#note-1)*:
[[basic.type.qualifier]](basic.type.qualifier "6.9.5CV-qualifiers") and [[dcl.fct]](dcl.fct "9.3.4.6Functions") describe how cv-qualifiers affect object and
function types[.](#1.sentence-4)
— *end note*]
Redundant cv-qualifications are ignored[.](#1.sentence-5)
[*Note [2](#note-2)*:
For example,
these could be introduced by typedefs[.](#1.sentence-6)
— *end note*]
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L1283)
[*Note [3](#note-3)*:
Declaring a variable const can affect its linkage ([[dcl.stc]](dcl.stc "9.2.2Storage class specifiers"))
and its usability in constant expressions ([[expr.const]](expr.const "7.7Constant expressions"))[.](#2.sentence-1)
As
described in [[dcl.init]](dcl.init "9.5Initializers"), the definition of an object or subobject
of const-qualified type must specify an initializer or be subject to
default-initialization[.](#2.sentence-2)
— *end note*]
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L1292)
A pointer or reference to a cv-qualified type need not actually point or
refer to a cv-qualified object, but it is treated as if it does; a
const-qualified access path cannot be used to modify an object even if
the object referenced is a non-const object and can be modified through
some other access path[.](#3.sentence-1)
[*Note [4](#note-4)*:
Cv-qualifiers are supported by the type system so that they cannot be
subverted without [casting](expr.const.cast "7.6.1.11Const cast[expr.const.cast]")[.](#3.sentence-2)
— *end note*]
[4](#4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L1303)
Any attempt to modify ([[expr.assign]](expr.assign "7.6.19Assignment and compound assignment operators"), [[expr.post.incr]](expr.post.incr "7.6.1.6Increment and decrement"), [[expr.pre.incr]](expr.pre.incr "7.6.2.3Increment and decrement")) a
const object ([[basic.type.qualifier]](basic.type.qualifier "6.9.5CV-qualifiers")) during its
lifetime ([[basic.life]](basic.life "6.8.4Lifetime")) results in undefined behavior[.](#4.sentence-1)
[*Example [1](#example-1)*: const int ci = 3; // cv-qualified (initialized as required) ci = 4; // error: attempt to modify constint i = 2; // not cv-qualifiedconst int* cip; // pointer to const int cip = &i; // OK, cv-qualified access path to unqualified*cip = 4; // error: attempt to modify through ptr to constint* ip;
ip = const_cast<int*>(cip); // cast needed to convert const int* to int**ip = 4; // defined: *ip points to i, a non-const objectconst int* ciq = new const int (3); // initialized as requiredint* iq = const_cast<int*>(ciq); // cast required*iq = 4; // undefined behavior: modifies a const object
For another example,struct X {mutable int i; int j;};struct Y { X x;
Y();};
const Y y;
y.x.i++; // well-formed: mutable member can be modified y.x.j++; // error: const-qualified member modified Y* p = const_cast<Y*>(&y); // cast away const-ness of y p->x.i = 99; // well-formed: mutable member can be modified p->x.j = 99; // undefined behavior: modifies a const subobject
— *end example*]
[5](#5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L1346)
The semantics of an access through a volatile glvalue areimplementation-defined[.](#5.sentence-1)
If an attempt is made to access an object defined with a
volatile-qualified type through the use of a non-volatile glvalue,
the behavior is undefined[.](#5.sentence-2)
[6](#6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L1353)
[*Note [5](#note-5)*:
volatile is a hint to the implementation to avoid aggressive
optimization involving the object because it is possible for the value of the object
to change by means undetectable by an implementation[.](#6.sentence-1)
Furthermore, for some implementations, volatile can indicate that
special hardware instructions are needed to access the object[.](#6.sentence-2)
See [[intro.execution]](intro.execution "6.10.1Sequential execution") for detailed semantics[.](#6.sentence-3)
In general, the
semantics of volatile are intended to be the same in C++ as
they are in C[.](#6.sentence-4)
— *end note*]

View File

@@ -0,0 +1,106 @@
[dcl.type.decltype]
# 9 Declarations [[dcl]](./#dcl)
## 9.2 Specifiers [[dcl.spec]](dcl.spec#dcl.type.decltype)
### 9.2.9 Type specifiers [[dcl.type]](dcl.type#decltype)
#### 9.2.9.6 Decltype specifiers [dcl.type.decltype]
[decltype-specifier:](#nt:decltype-specifier "9.2.9.6Decltype specifiers[dcl.type.decltype]")
decltype ( [*expression*](expr.comma#nt:expression "7.6.20Comma operator[expr.comma]") )
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L1699)
For an expression E, the type denoted by decltype(E) is defined as follows:
- [(1.1)](#1.1)
if E is an unparenthesized [*id-expression*](expr.prim.id.general#nt:id-expression "7.5.5.1General[expr.prim.id.general]") naming a structured binding ([[dcl.struct.bind]](dcl.struct.bind "9.7Structured binding declarations")),decltype(E) is the referenced type as given in
the specification of the structured binding declaration;
- [(1.2)](#1.2)
otherwise, if E is an unparenthesized [*id-expression*](expr.prim.id.general#nt:id-expression "7.5.5.1General[expr.prim.id.general]") naming a constant template parameter ([[temp.param]](temp.param "13.2Template parameters")),decltype(E) is the type of the template parameter
after performing any necessary
type deduction ([[dcl.spec.auto]](dcl.spec.auto "9.2.9.7Placeholder type specifiers"), [[dcl.type.class.deduct]](dcl.type.class.deduct "9.2.9.8Deduced class template specialization types"));
- [(1.3)](#1.3)
otherwise, if E is an unparenthesized [*id-expression*](expr.prim.id.general#nt:id-expression "7.5.5.1General[expr.prim.id.general]") or
an unparenthesized
class
member access ([[expr.ref]](expr.ref "7.6.1.5Class member access")), decltype(E) is the
type of the entity named by E[.](#1.3.sentence-1)
If there is no such entity, the program is ill-formed;
- [(1.4)](#1.4)
otherwise, if E is an unparenthesized [*splice-expression*](expr.prim.splice#nt:splice-expression "7.5.9Expression splicing[expr.prim.splice]"),decltype(E) is the type of the entity, object, or value
designated by the [*splice-specifier*](basic.splice#nt:splice-specifier "6.6Splice specifiers[basic.splice]") of E;
- [(1.5)](#1.5)
otherwise, if E is
an xvalue, decltype(E) is T&&, where T is the type
of E;
- [(1.6)](#1.6)
otherwise, if E is an lvalue, decltype(E) is T&, where T is the type of E;
- [(1.7)](#1.7)
otherwise, decltype(E) is the type of E[.](#1.7.sentence-1)
The operand of the decltype specifier is an [unevaluated operand](expr.context#def:unevaluated_operand "7.2.3Context dependence[expr.context]")[.](#1.sentence-2)
[*Example [1](#example-1)*: const int&& foo();int i;struct A { double x; };const A* a = new A();decltype(foo()) x1 = 17; // type is const int&&decltype(i) x2; // type is intdecltype(a->x) x3; // type is doubledecltype((a->x)) x4 = x3; // type is const double&decltype([:^^x1:]) x5 = 18; // type is const int&&decltype(([:^^x1:])) x6 = 19; // type is const int&void f() {[](auto ...pack) {decltype(pack...[0]) x7; // type is intdecltype((pack...[0])) x8; // type is int&}(0);} — *end example*]
[*Note [1](#note-1)*:
The rules for determining types involving decltype(auto) are specified
in [[dcl.spec.auto]](dcl.spec.auto "9.2.9.7Placeholder type specifiers")[.](#1.sentence-3)
— *end note*]
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L1763)
If the operand of a [*decltype-specifier*](#nt:decltype-specifier "9.2.9.6Decltype specifiers[dcl.type.decltype]") is a prvalue
and is not a (possibly parenthesized) immediate invocation ([[expr.const]](expr.const "7.7Constant expressions")),
the temporary materialization conversion is not applied ([[conv.rval]](conv.rval "7.3.5Temporary materialization conversion"))
and no result object is provided for the prvalue[.](#2.sentence-1)
The type of the prvalue may be incomplete or an abstract class type[.](#2.sentence-2)
[*Note [2](#note-2)*:
As a result, storage is not allocated for the prvalue and it is not destroyed[.](#2.sentence-3)
Thus, a class type is not instantiated
as a result of being the type of a function call in this context[.](#2.sentence-4)
In this context, the common purpose of
writing the expression is merely to refer to its type[.](#2.sentence-5)
In that sense, a[*decltype-specifier*](#nt:decltype-specifier "9.2.9.6Decltype specifiers[dcl.type.decltype]") is analogous to a use of a [*typedef-name*](dcl.typedef#nt:typedef-name "9.2.4The typedef specifier[dcl.typedef]"),
so the usual reasons for requiring a complete type do not apply[.](#2.sentence-6)
In particular,
it is not necessary to allocate storage for a temporary object or to enforce the
semantic constraints associated with invoking the type's destructor[.](#2.sentence-7)
— *end note*]
[*Note [3](#note-3)*:
Unlike the preceding rule, parentheses have no special meaning in this context[.](#2.sentence-8)
— *end note*]
[*Example [2](#example-2)*: template<class T> struct A { ~A() = delete; };template<class T> auto h()-> A<T>;template<class T> auto i(T) // identity-> T;template<class T> auto f(T) // #1-> decltype(i(h<T>())); // forces completion of A<T> and implicitly uses A<T>::~A()// for the temporary introduced by the use of h().// (A temporary is not introduced as a result of the use of i().)template<class T> auto f(T) // #2-> void;auto g() -> void { f(42); // OK, calls #2. (#1 is not a viable candidate: type deduction// fails ([[temp.deduct]](temp.deduct "13.10.3Template argument deduction")) because A<int>::~A() is implicitly used in its// [*decltype-specifier*](#nt:decltype-specifier "9.2.9.6Decltype specifiers[dcl.type.decltype]"))}template<class T> auto q(T)-> decltype((h<T>())); // does not force completion of A<T>; A<T>::~A() is not implicitly// used within the context of this [*decltype-specifier*](#nt:decltype-specifier "9.2.9.6Decltype specifiers[dcl.type.decltype]")void r() { q(42); // error: deduction against q succeeds, so overload resolution selects// the specialization “q(T) -> decltype((h<T>()))'' with T=int;// the return type is A<int>, so a temporary is introduced and its// destructor is used, so the program is ill-formed} — *end example*]

134
cppdraft/dcl/type/elab.md Normal file
View File

@@ -0,0 +1,134 @@
[dcl.type.elab]
# 9 Declarations [[dcl]](./#dcl)
## 9.2 Specifiers [[dcl.spec]](dcl.spec#dcl.type.elab)
### 9.2.9 Type specifiers [[dcl.type]](dcl.type#elab)
#### 9.2.9.5 Elaborated type specifiers [dcl.type.elab]
[elaborated-type-specifier:](#nt:elaborated-type-specifier "9.2.9.5Elaborated type specifiers[dcl.type.elab]")
[*class-key*](class.pre#nt:class-key "11.1Preamble[class.pre]") [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1Attribute syntax and semantics[dcl.attr.grammar]")opt [*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3Qualified names[expr.prim.id.qual]")opt [*identifier*](lex.name#nt:identifier "5.11Identifiers[lex.name]")
[*class-key*](class.pre#nt:class-key "11.1Preamble[class.pre]") [*simple-template-id*](temp.names#nt:simple-template-id "13.3Names of template specializations[temp.names]")
[*class-key*](class.pre#nt:class-key "11.1Preamble[class.pre]") [*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3Qualified names[expr.prim.id.qual]") templateopt [*simple-template-id*](temp.names#nt:simple-template-id "13.3Names of template specializations[temp.names]")
enum [*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3Qualified names[expr.prim.id.qual]")opt [*identifier*](lex.name#nt:identifier "5.11Identifiers[lex.name]")
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L1579)
The component names of an [*elaborated-type-specifier*](#nt:elaborated-type-specifier "9.2.9.5Elaborated type specifiers[dcl.type.elab]") are
its [*identifier*](lex.name#nt:identifier "5.11Identifiers[lex.name]") (if any) and
those of its [*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3Qualified names[expr.prim.id.qual]") and[*simple-template-id*](temp.names#nt:simple-template-id "13.3Names of template specializations[temp.names]") (if any)[.](#1.sentence-1)
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L1586)
If an [*elaborated-type-specifier*](#nt:elaborated-type-specifier "9.2.9.5Elaborated type specifiers[dcl.type.elab]") is the sole constituent of a
declaration, the declaration is ill-formed unless it is an explicit
specialization ([[temp.expl.spec]](temp.expl.spec "13.9.4Explicit specialization")),
a partial specialization ([[temp.spec.partial]](temp.spec.partial "13.7.6Partial specialization")),
an explicit
instantiation ([[temp.explicit]](temp.explicit "13.9.3Explicit instantiation")), or it has one of the following
forms:
[*class-key*](class.pre#nt:class-key "11.1Preamble[class.pre]") [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1Attribute syntax and semantics[dcl.attr.grammar]")opt [*identifier*](lex.name#nt:identifier "5.11Identifiers[lex.name]") ;
[*class-key*](class.pre#nt:class-key "11.1Preamble[class.pre]") [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1Attribute syntax and semantics[dcl.attr.grammar]")opt [*simple-template-id*](temp.names#nt:simple-template-id "13.3Names of template specializations[temp.names]") ;
In the first case,
the [*elaborated-type-specifier*](#nt:elaborated-type-specifier "9.2.9.5Elaborated type specifiers[dcl.type.elab]") declares
the [*identifier*](lex.name#nt:identifier "5.11Identifiers[lex.name]") as a [*class-name*](class.pre#nt:class-name "11.1Preamble[class.pre]")[.](#2.sentence-2)
The second case shall appear only
in an [*explicit-specialization*](temp.expl.spec#nt:explicit-specialization "13.9.4Explicit specialization[temp.expl.spec]") ([[temp.expl.spec]](temp.expl.spec "13.9.4Explicit specialization")) or
in a [*template-declaration*](temp.pre#nt:template-declaration "13.1Preamble[temp.pre]") (where it declares a partial specialization)[.](#2.sentence-3)
The [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1Attribute syntax and semantics[dcl.attr.grammar]"), if any, appertains
to the class or template being declared[.](#2.sentence-4)
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L1611)
Otherwise, an [*elaborated-type-specifier*](#nt:elaborated-type-specifier "9.2.9.5Elaborated type specifiers[dcl.type.elab]") E shall not have
an [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1Attribute syntax and semantics[dcl.attr.grammar]")[.](#3.sentence-1)
If E contains an [*identifier*](lex.name#nt:identifier "5.11Identifiers[lex.name]") but no [*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3Qualified names[expr.prim.id.qual]") and
(unqualified) lookup for the [*identifier*](lex.name#nt:identifier "5.11Identifiers[lex.name]") finds nothing,E shall not be introduced by the enum keyword and
declares the [*identifier*](lex.name#nt:identifier "5.11Identifiers[lex.name]") as a [*class-name*](class.pre#nt:class-name "11.1Preamble[class.pre]")[.](#3.sentence-2)
The target scope of E is the nearest enclosing namespace or block scope[.](#3.sentence-3)
[4](#4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L1621)
A [*friend-type-specifier*](class.mem.general#nt:friend-type-specifier "11.4.1General[class.mem.general]") that is an [*elaborated-type-specifier*](#nt:elaborated-type-specifier "9.2.9.5Elaborated type specifiers[dcl.type.elab]") shall have one of the following forms:
[*class-key*](class.pre#nt:class-key "11.1Preamble[class.pre]") [*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3Qualified names[expr.prim.id.qual]")opt [*identifier*](lex.name#nt:identifier "5.11Identifiers[lex.name]")
[*class-key*](class.pre#nt:class-key "11.1Preamble[class.pre]") [*simple-template-id*](temp.names#nt:simple-template-id "13.3Names of template specializations[temp.names]")
[*class-key*](class.pre#nt:class-key "11.1Preamble[class.pre]") [*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3Qualified names[expr.prim.id.qual]") templateopt [*simple-template-id*](temp.names#nt:simple-template-id "13.3Names of template specializations[temp.names]")
Any unqualified lookup for the [*identifier*](lex.name#nt:identifier "5.11Identifiers[lex.name]") (in the first case)
does not consider scopes that contain
the nearest enclosing namespace or block scope; no name is bound[.](#4.sentence-1)
[*Note [1](#note-1)*:
A [*using-directive*](namespace.udir#nt:using-directive "9.9.4Using namespace directive[namespace.udir]") in the target scope is ignored
if it refers to a namespace not contained by that scope[.](#4.sentence-2)
— *end note*]
[5](#5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L1638)
[*Note [2](#note-2)*:
[[basic.lookup.elab]](basic.lookup.elab "6.5.6Elaborated type specifiers") describes how name lookup proceeds
in an [*elaborated-type-specifier*](#nt:elaborated-type-specifier "9.2.9.5Elaborated type specifiers[dcl.type.elab]")[.](#5.sentence-1)
An [*elaborated-type-specifier*](#nt:elaborated-type-specifier "9.2.9.5Elaborated type specifiers[dcl.type.elab]") can be used to refer to
a previously declared [*class-name*](class.pre#nt:class-name "11.1Preamble[class.pre]") or [*enum-name*](dcl.enum#nt:enum-name "9.8.1Enumeration declarations[dcl.enum]") even if the name has been hidden by a non-type declaration[.](#5.sentence-2)
— *end note*]
[6](#6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L1647)
If the [*identifier*](lex.name#nt:identifier "5.11Identifiers[lex.name]") or [*simple-template-id*](temp.names#nt:simple-template-id "13.3Names of template specializations[temp.names]") in an [*elaborated-type-specifier*](#nt:elaborated-type-specifier "9.2.9.5Elaborated type specifiers[dcl.type.elab]") resolves to a [*class-name*](class.pre#nt:class-name "11.1Preamble[class.pre]") or[*enum-name*](dcl.enum#nt:enum-name "9.8.1Enumeration declarations[dcl.enum]"), the [*elaborated-type-specifier*](#nt:elaborated-type-specifier "9.2.9.5Elaborated type specifiers[dcl.type.elab]") introduces it into the declaration the same way a[*simple-type-specifier*](dcl.type.simple#nt:simple-type-specifier "9.2.9.3Simple type specifiers[dcl.type.simple]") introduces
its [*type-name*](dcl.type.simple#nt:type-name "9.2.9.3Simple type specifiers[dcl.type.simple]") ([[dcl.type.simple]](dcl.type.simple "9.2.9.3Simple type specifiers"))[.](#6.sentence-1)
If the [*identifier*](lex.name#nt:identifier "5.11Identifiers[lex.name]") or [*simple-template-id*](temp.names#nt:simple-template-id "13.3Names of template specializations[temp.names]") resolves to a[*typedef-name*](dcl.typedef#nt:typedef-name "9.2.4The typedef specifier[dcl.typedef]") ([[dcl.typedef]](dcl.typedef "9.2.4The typedef specifier"), [[temp.names]](temp.names "13.3Names of template specializations")),
the [*elaborated-type-specifier*](#nt:elaborated-type-specifier "9.2.9.5Elaborated type specifiers[dcl.type.elab]") is ill-formed[.](#6.sentence-2)
[*Note [3](#note-3)*:
This implies that, within a class template with a template[*type-parameter*](temp.param#nt:type-parameter "13.2Template parameters[temp.param]") T, the declarationfriend class T; is ill-formed[.](#6.sentence-3)
However, the similar declaration friend T; is well-formed ([[class.friend]](class.friend "11.8.4Friends"))[.](#6.sentence-4)
— *end note*]
[7](#7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L1667)
The [*class-key*](class.pre#nt:class-key "11.1Preamble[class.pre]") or enum keyword
present in an[*elaborated-type-specifier*](#nt:elaborated-type-specifier "9.2.9.5Elaborated type specifiers[dcl.type.elab]") shall agree in kind with the
declaration to which the name in the[*elaborated-type-specifier*](#nt:elaborated-type-specifier "9.2.9.5Elaborated type specifiers[dcl.type.elab]") refers[.](#7.sentence-1)
This rule also applies to
the form of [*elaborated-type-specifier*](#nt:elaborated-type-specifier "9.2.9.5Elaborated type specifiers[dcl.type.elab]") that declares a[*class-name*](class.pre#nt:class-name "11.1Preamble[class.pre]") or friend class since it can be construed
as referring to the definition of the class[.](#7.sentence-2)
Thus, in any[*elaborated-type-specifier*](#nt:elaborated-type-specifier "9.2.9.5Elaborated type specifiers[dcl.type.elab]"), the enum keyword
shall be
used to refer to an enumeration ([[dcl.enum]](dcl.enum "9.8.1Enumeration declarations")), the union[*class-key*](class.pre#nt:class-key "11.1Preamble[class.pre]") shall be used to refer to a union ([[class.union]](class.union "11.5Unions")),
and either the class or struct[*class-key*](class.pre#nt:class-key "11.1Preamble[class.pre]") shall be used to refer to a non-union class ([[class.pre]](class.pre "11.1Preamble"))[.](#7.sentence-3)
[*Example [1](#example-1)*: enum class E { a, b };enum E x = E::a; // OKstruct S { } s;class S* p = &s; // OK — *end example*]

View File

@@ -0,0 +1,103 @@
[dcl.type.general]
# 9 Declarations [[dcl]](./#dcl)
## 9.2 Specifiers [[dcl.spec]](dcl.spec#dcl.type.general)
### 9.2.9 Type specifiers [[dcl.type]](dcl.type#general)
#### 9.2.9.1 General [dcl.type.general]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L1165)
The type-specifiers are
[type-specifier:](#nt:type-specifier "9.2.9.1General[dcl.type.general]")
[*simple-type-specifier*](dcl.type.simple#nt:simple-type-specifier "9.2.9.3Simple type specifiers[dcl.type.simple]")
[*elaborated-type-specifier*](dcl.type.elab#nt:elaborated-type-specifier "9.2.9.5Elaborated type specifiers[dcl.type.elab]")
[*typename-specifier*](temp.res.general#nt:typename-specifier "13.8.1General[temp.res.general]")
[*cv-qualifier*](dcl.decl.general#nt:cv-qualifier "9.3.1General[dcl.decl.general]")
[type-specifier-seq:](#nt:type-specifier-seq "9.2.9.1General[dcl.type.general]")
[*type-specifier*](#nt:type-specifier "9.2.9.1General[dcl.type.general]") [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1Attribute syntax and semantics[dcl.attr.grammar]")opt
[*type-specifier*](#nt:type-specifier "9.2.9.1General[dcl.type.general]") [*type-specifier-seq*](#nt:type-specifier-seq "9.2.9.1General[dcl.type.general]")
[defining-type-specifier:](#nt:defining-type-specifier "9.2.9.1General[dcl.type.general]")
[*type-specifier*](#nt:type-specifier "9.2.9.1General[dcl.type.general]")
[*class-specifier*](class.pre#nt:class-specifier "11.1Preamble[class.pre]")
[*enum-specifier*](dcl.enum#nt:enum-specifier "9.8.1Enumeration declarations[dcl.enum]")
[defining-type-specifier-seq:](#nt:defining-type-specifier-seq "9.2.9.1General[dcl.type.general]")
[*defining-type-specifier*](#nt:defining-type-specifier "9.2.9.1General[dcl.type.general]") [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1Attribute syntax and semantics[dcl.attr.grammar]")opt
[*defining-type-specifier*](#nt:defining-type-specifier "9.2.9.1General[dcl.type.general]") [*defining-type-specifier-seq*](#nt:defining-type-specifier-seq "9.2.9.1General[dcl.type.general]")
The optional [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") in a [*type-specifier-seq*](#nt:type-specifier-seq "9.2.9.1General[dcl.type.general]") or a [*defining-type-specifier-seq*](#nt:defining-type-specifier-seq "9.2.9.1General[dcl.type.general]") appertains
to the type denoted by the preceding [*type-specifier*](#nt:type-specifier "9.2.9.1General[dcl.type.general]")*s* or [*defining-type-specifier*](#nt:defining-type-specifier "9.2.9.1General[dcl.type.general]")*s* ([[dcl.meaning]](dcl.meaning "9.3.4Meaning of declarators"))[.](#1.sentence-2)
The[*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") affects the type only for the declaration it appears in,
not other declarations involving the same type[.](#1.sentence-3)
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L1205)
As a general rule, at most one[*defining-type-specifier*](#nt:defining-type-specifier "9.2.9.1General[dcl.type.general]") is allowed in the complete[*decl-specifier-seq*](dcl.spec.general#nt:decl-specifier-seq "9.2.1General[dcl.spec.general]") of a [*declaration*](dcl.pre#nt:declaration "9.1Preamble[dcl.pre]") or in a[*defining-type-specifier-seq*](#nt:defining-type-specifier-seq "9.2.9.1General[dcl.type.general]"),
and at most one[*type-specifier*](#nt:type-specifier "9.2.9.1General[dcl.type.general]") is allowed in a[*type-specifier-seq*](#nt:type-specifier-seq "9.2.9.1General[dcl.type.general]")[.](#2.sentence-1)
The only exceptions to this rule are the following:
- [(2.1)](#2.1)
const can be combined with any type specifier except itself[.](#2.1.sentence-1)
- [(2.2)](#2.2)
volatile can be combined with any type specifier except itself[.](#2.2.sentence-1)
- [(2.3)](#2.3)
signed or unsigned can be combined withchar, long, short, or int[.](#2.3.sentence-1)
- [(2.4)](#2.4)
short or long can be combined with int[.](#2.4.sentence-1)
- [(2.5)](#2.5)
long can be combined with double[.](#2.5.sentence-1)
- [(2.6)](#2.6)
long can be combined with long[.](#2.6.sentence-1)
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L1231)
Except in a declaration of a constructor, destructor, or conversion
function, at least one [*defining-type-specifier*](#nt:defining-type-specifier "9.2.9.1General[dcl.type.general]") that is not a[*cv-qualifier*](dcl.decl.general#nt:cv-qualifier "9.3.1General[dcl.decl.general]") shall appear in a complete[*type-specifier-seq*](#nt:type-specifier-seq "9.2.9.1General[dcl.type.general]") or a complete[*decl-specifier-seq*](dcl.spec.general#nt:decl-specifier-seq "9.2.1General[dcl.spec.general]")[.](#3.sentence-1)[74](#footnote-74 "There is no special provision for a decl-specifier-seq that lacks a type-specifier or that has a type-specifier that only specifies cv-qualifiers. The “implicit int” rule of C is no longer supported.")
[4](#4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L1245)
[*Note [1](#note-1)*:
[*enum-specifier*](dcl.enum#nt:enum-specifier "9.8.1Enumeration declarations[dcl.enum]")*s*,[*class-specifier*](class.pre#nt:class-specifier "11.1Preamble[class.pre]")*s*,
and[*typename-specifier*](temp.res.general#nt:typename-specifier "13.8.1General[temp.res.general]")*s* are discussed
in[[dcl.enum]](dcl.enum "9.8.1Enumeration declarations"),[[class]](class "11Classes"),
and[[temp.res]](temp.res "13.8Name resolution"), respectively[.](#4.sentence-1)
The remaining[*type-specifier*](#nt:type-specifier "9.2.9.1General[dcl.type.general]")*s* are discussed in the rest of [[dcl.type]](dcl.type "9.2.9Type specifiers")[.](#4.sentence-2)
— *end note*]
[74)](#footnote-74)[74)](#footnoteref-74)
There is no special
provision for a [*decl-specifier-seq*](dcl.spec.general#nt:decl-specifier-seq "9.2.1General[dcl.spec.general]") that
lacks a [*type-specifier*](#nt:type-specifier "9.2.9.1General[dcl.type.general]") or that has a[*type-specifier*](#nt:type-specifier "9.2.9.1General[dcl.type.general]") that only specifies [*cv-qualifier*](dcl.decl.general#nt:cv-qualifier "9.3.1General[dcl.decl.general]")*s*[.](#footnote-74.sentence-1)
The “implicit int” rule of C is no longer supported[.](#footnote-74.sentence-2)

View File

@@ -0,0 +1,43 @@
[dcl.type.pack.index]
# 9 Declarations [[dcl]](./#dcl)
## 9.2 Specifiers [[dcl.spec]](dcl.spec#dcl.type.pack.index)
### 9.2.9 Type specifiers [[dcl.type]](dcl.type#pack.index)
#### 9.2.9.4 Pack indexing specifier [dcl.type.pack.index]
[pack-index-specifier:](#nt:pack-index-specifier "9.2.9.4Pack indexing specifier[dcl.type.pack.index]")
[*typedef-name*](dcl.typedef#nt:typedef-name "9.2.4The typedef specifier[dcl.typedef]") ... [ [*constant-expression*](expr.const#nt:constant-expression "7.7Constant expressions[expr.const]") ]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L1547)
The [*typedef-name*](dcl.typedef#nt:typedef-name "9.2.4The typedef specifier[dcl.typedef]") P in a [*pack-index-specifier*](#nt:pack-index-specifier "9.2.9.4Pack indexing specifier[dcl.type.pack.index]") shall denote a pack[.](#1.sentence-1)
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L1551)
The [*constant-expression*](expr.const#nt:constant-expression "7.7Constant expressions[expr.const]") shall be
a converted constant expression ([[expr.const]](expr.const "7.7Constant expressions")) of type std::size_t whose value V, termed the index,
is such that 0≤V<sizeof...(P)[.](#2.sentence-1)
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L1557)
A [*pack-index-specifier*](#nt:pack-index-specifier "9.2.9.4Pack indexing specifier[dcl.type.pack.index]") is a pack expansion ([[temp.variadic]](temp.variadic "13.7.4Variadic templates"))[.](#3.sentence-1)
[4](#4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L1560)
[*Note [1](#note-1)*:
The [*pack-index-specifier*](#nt:pack-index-specifier "9.2.9.4Pack indexing specifier[dcl.type.pack.index]") denotes
the type of the Vth element of the pack[.](#4.sentence-1)
— *end note*]

162
cppdraft/dcl/type/simple.md Normal file
View File

@@ -0,0 +1,162 @@
[dcl.type.simple]
# 9 Declarations [[dcl]](./#dcl)
## 9.2 Specifiers [[dcl.spec]](dcl.spec#dcl.type.simple)
### 9.2.9 Type specifiers [[dcl.type]](dcl.type#simple)
#### 9.2.9.3 Simple type specifiers [dcl.type.simple]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L1370)
The simple type specifiers are
[simple-type-specifier:](#nt:simple-type-specifier "9.2.9.3Simple type specifiers[dcl.type.simple]")
[*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3Qualified names[expr.prim.id.qual]")opt [*type-name*](#nt:type-name "9.2.9.3Simple type specifiers[dcl.type.simple]")
[*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3Qualified names[expr.prim.id.qual]") template [*simple-template-id*](temp.names#nt:simple-template-id "13.3Names of template specializations[temp.names]")
[*computed-type-specifier*](#nt:computed-type-specifier "9.2.9.3Simple type specifiers[dcl.type.simple]")
[*placeholder-type-specifier*](dcl.spec.auto.general#nt:placeholder-type-specifier "9.2.9.7.1General[dcl.spec.auto.general]")
[*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3Qualified names[expr.prim.id.qual]")opt [*template-name*](temp.names#nt:template-name "13.3Names of template specializations[temp.names]")
char
char8_t
char16_t
char32_t
wchar_t
bool
short
int
long
signed
unsigned
float
double
void
[type-name:](#nt:type-name "9.2.9.3Simple type specifiers[dcl.type.simple]")
[*class-name*](class.pre#nt:class-name "11.1Preamble[class.pre]")
[*enum-name*](dcl.enum#nt:enum-name "9.8.1Enumeration declarations[dcl.enum]")
[*typedef-name*](dcl.typedef#nt:typedef-name "9.2.4The typedef specifier[dcl.typedef]")
[computed-type-specifier:](#nt:computed-type-specifier "9.2.9.3Simple type specifiers[dcl.type.simple]")
[*decltype-specifier*](dcl.type.decltype#nt:decltype-specifier "9.2.9.6Decltype specifiers[dcl.type.decltype]")
[*pack-index-specifier*](dcl.type.pack.index#nt:pack-index-specifier "9.2.9.4Pack indexing specifier[dcl.type.pack.index]")
[*splice-type-specifier*](dcl.type.splice#nt:splice-type-specifier "9.2.9.9Type splicing[dcl.type.splice]")
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L1409)
The component names of a [*simple-type-specifier*](#nt:simple-type-specifier "9.2.9.3Simple type specifiers[dcl.type.simple]") are those of its[*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3Qualified names[expr.prim.id.qual]"),[*type-name*](#nt:type-name "9.2.9.3Simple type specifiers[dcl.type.simple]"),[*simple-template-id*](temp.names#nt:simple-template-id "13.3Names of template specializations[temp.names]"),[*template-name*](temp.names#nt:template-name "13.3Names of template specializations[temp.names]"), and/or[*type-constraint*](temp.param#nt:type-constraint "13.2Template parameters[temp.param]") (if it is a [*placeholder-type-specifier*](dcl.spec.auto.general#nt:placeholder-type-specifier "9.2.9.7.1General[dcl.spec.auto.general]"))[.](#2.sentence-1)
The component name of a [*type-name*](#nt:type-name "9.2.9.3Simple type specifiers[dcl.type.simple]") is the first name in it[.](#2.sentence-2)
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L1420)
A [*placeholder-type-specifier*](dcl.spec.auto.general#nt:placeholder-type-specifier "9.2.9.7.1General[dcl.spec.auto.general]") is a placeholder for
a type to be deduced ([[dcl.spec.auto]](dcl.spec.auto "9.2.9.7Placeholder type specifiers"))[.](#3.sentence-1)
A [*type-specifier*](dcl.type.general#nt:type-specifier "9.2.9.1General[dcl.type.general]") is a placeholder for
a deduced class type ([[dcl.type.class.deduct]](dcl.type.class.deduct "9.2.9.8Deduced class template specialization types")) if either
- [(3.1)](#3.1)
it is of the formtypenameopt [*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3Qualified names[expr.prim.id.qual]")opt [*template-name*](temp.names#nt:template-name "13.3Names of template specializations[temp.names]") or
- [(3.2)](#3.2)
it is of the form typenameopt [*splice-specifier*](basic.splice#nt:splice-specifier "6.6Splice specifiers[basic.splice]") and
the [*splice-specifier*](basic.splice#nt:splice-specifier "6.6Splice specifiers[basic.splice]") designates
a class template or alias template[.](#3.sentence-2)
The [*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3Qualified names[expr.prim.id.qual]") or [*splice-specifier*](basic.splice#nt:splice-specifier "6.6Splice specifiers[basic.splice]"),
if any, shall be non-dependent and
the [*template-name*](temp.names#nt:template-name "13.3Names of template specializations[temp.names]") or [*splice-specifier*](basic.splice#nt:splice-specifier "6.6Splice specifiers[basic.splice]") shall designate a deducible template[.](#3.sentence-3)
A [*deducible template*](#def:template,deducible "9.2.9.3Simple type specifiers[dcl.type.simple]") is either a class template or
is an alias template whose [*defining-type-id*](dcl.name#nt:defining-type-id "9.3.2Type names[dcl.name]") is of the form
typenameopt [*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3Qualified names[expr.prim.id.qual]")opt templateopt [*simple-template-id*](temp.names#nt:simple-template-id "13.3Names of template specializations[temp.names]")
where the [*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3Qualified names[expr.prim.id.qual]") (if any) is non-dependent and
the [*template-name*](temp.names#nt:template-name "13.3Names of template specializations[temp.names]") of the [*simple-template-id*](temp.names#nt:simple-template-id "13.3Names of template specializations[temp.names]") names a deducible template[.](#3.sentence-5)
[*Note [1](#note-1)*:
An injected-class-name is never interpreted as a [*template-name*](temp.names#nt:template-name "13.3Names of template specializations[temp.names]") in contexts where class template argument deduction would be performed ([[temp.local]](temp.local "13.8.2Locally declared names"))[.](#3.sentence-6)
— *end note*]
The other[*simple-type-specifier*](#nt:simple-type-specifier "9.2.9.3Simple type specifiers[dcl.type.simple]")*s* specify either a previously-declared type, a type determined from an
expression, or one of the
fundamental types ([[basic.fundamental]](basic.fundamental "6.9.2Fundamental types"))[.](#3.sentence-7)
Table [17](#tab:dcl.type.simple "Table 17: simple-type-specifiers and the types they specify") summarizes the valid combinations of[*simple-type-specifier*](#nt:simple-type-specifier "9.2.9.3Simple type specifiers[dcl.type.simple]")*s* and the types they specify[.](#3.sentence-8)
Table [17](#tab:dcl.type.simple) — [*simple-type-specifier*](#nt:simple-type-specifier "9.2.9.3Simple type specifiers[dcl.type.simple]")*s* and the types they specify [[tab:dcl.type.simple]](./tab:dcl.type.simple)
| [🔗](#tab:dcl.type.simple-row-1)<br>**Specifier(s)** | **Type** |
| --- | --- |
| [🔗](#tab:dcl.type.simple-row-2)<br>[*type-name*](#nt:type-name "9.2.9.3Simple type specifiers[dcl.type.simple]") | the type named |
| [🔗](#tab:dcl.type.simple-row-3)<br>[*simple-template-id*](temp.names#nt:simple-template-id "13.3Names of template specializations[temp.names]") | the type as defined in [[temp.names]](temp.names "13.3Names of template specializations") |
| [🔗](#tab:dcl.type.simple-row-4)<br>[*decltype-specifier*](dcl.type.decltype#nt:decltype-specifier "9.2.9.6Decltype specifiers[dcl.type.decltype]") | the type as defined in [[dcl.type.decltype]](dcl.type.decltype "9.2.9.6Decltype specifiers") |
| [🔗](#tab:dcl.type.simple-row-5)<br>[*pack-index-specifier*](dcl.type.pack.index#nt:pack-index-specifier "9.2.9.4Pack indexing specifier[dcl.type.pack.index]") | the type as defined in [[dcl.type.pack.index]](dcl.type.pack.index "9.2.9.4Pack indexing specifier") |
| [🔗](#tab:dcl.type.simple-row-6)<br>[*placeholder-type-specifier*](dcl.spec.auto.general#nt:placeholder-type-specifier "9.2.9.7.1General[dcl.spec.auto.general]") | the type as defined in [[dcl.spec.auto]](dcl.spec.auto "9.2.9.7Placeholder type specifiers") |
| [🔗](#tab:dcl.type.simple-row-7)<br>[*template-name*](temp.names#nt:template-name "13.3Names of template specializations[temp.names]") | the type as defined in [[dcl.type.class.deduct]](dcl.type.class.deduct "9.2.9.8Deduced class template specialization types") |
| [🔗](#tab:dcl.type.simple-row-8)<br>[*splice-type-specifier*](dcl.type.splice#nt:splice-type-specifier "9.2.9.9Type splicing[dcl.type.splice]") | the type as defined in [[dcl.type.splice]](dcl.type.splice "9.2.9.9Type splicing") |
| [🔗](#tab:dcl.type.simple-row-9)<br>char | “char” |
| [🔗](#tab:dcl.type.simple-row-10)<br>unsigned char | “unsigned char” |
| [🔗](#tab:dcl.type.simple-row-11)<br>signed char | “signed char” |
| [🔗](#tab:dcl.type.simple-row-12)<br>char8_t | “char8_t” |
| [🔗](#tab:dcl.type.simple-row-13)<br>char16_t | “char16_t” |
| [🔗](#tab:dcl.type.simple-row-14)<br>char32_t | “char32_t” |
| [🔗](#tab:dcl.type.simple-row-15)<br>bool | “bool” |
| [🔗](#tab:dcl.type.simple-row-16)<br>unsigned | “unsigned int” |
| [🔗](#tab:dcl.type.simple-row-17)<br>unsigned int | “unsigned int” |
| [🔗](#tab:dcl.type.simple-row-18)<br>signed | “int” |
| [🔗](#tab:dcl.type.simple-row-19)<br>signed int | “int” |
| [🔗](#tab:dcl.type.simple-row-20)<br>int | “int” |
| [🔗](#tab:dcl.type.simple-row-21)<br>unsigned short int | “unsigned short int” |
| [🔗](#tab:dcl.type.simple-row-22)<br>unsigned short | “unsigned short int” |
| [🔗](#tab:dcl.type.simple-row-23)<br>unsigned long int | “unsigned long int” |
| [🔗](#tab:dcl.type.simple-row-24)<br>unsigned long | “unsigned long int” |
| [🔗](#tab:dcl.type.simple-row-25)<br>unsigned long long int | “unsigned long long int” |
| [🔗](#tab:dcl.type.simple-row-26)<br>unsigned long long | “unsigned long long int” |
| [🔗](#tab:dcl.type.simple-row-27)<br>signed long int | “long int” |
| [🔗](#tab:dcl.type.simple-row-28)<br>signed long | “long int” |
| [🔗](#tab:dcl.type.simple-row-29)<br>signed long long int | “long long int” |
| [🔗](#tab:dcl.type.simple-row-30)<br>signed long long | “long long int” |
| [🔗](#tab:dcl.type.simple-row-31)<br>long long int | “long long int” |
| [🔗](#tab:dcl.type.simple-row-32)<br>long long | “long long int” |
| [🔗](#tab:dcl.type.simple-row-33)<br>long int | “long int” |
| [🔗](#tab:dcl.type.simple-row-34)<br>long | “long int” |
| [🔗](#tab:dcl.type.simple-row-35)<br>signed short int | “short int” |
| [🔗](#tab:dcl.type.simple-row-36)<br>signed short | “short int” |
| [🔗](#tab:dcl.type.simple-row-37)<br>short int | “short int” |
| [🔗](#tab:dcl.type.simple-row-38)<br>short | “short int” |
| [🔗](#tab:dcl.type.simple-row-39)<br>wchar_t | “wchar_t” |
| [🔗](#tab:dcl.type.simple-row-40)<br>float | “float” |
| [🔗](#tab:dcl.type.simple-row-41)<br>double | “double” |
| [🔗](#tab:dcl.type.simple-row-42)<br>long double | “long double” |
| [🔗](#tab:dcl.type.simple-row-43)<br>void | “void” |
[4](#4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L1531)
When multiple [*simple-type-specifier*](#nt:simple-type-specifier "9.2.9.3Simple type specifiers[dcl.type.simple]")*s* are allowed, they can be
freely intermixed with other [*decl-specifier*](dcl.spec.general#nt:decl-specifier "9.2.1General[dcl.spec.general]")*s* in any order[.](#4.sentence-1)
[*Note [2](#note-2)*:
It is implementation-defined whether objects of char type are
represented as signed or unsigned quantities[.](#4.sentence-2)
The signed specifier
forces char objects to be signed; it is redundant in other contexts[.](#4.sentence-3)
— *end note*]

View File

@@ -0,0 +1,46 @@
[dcl.type.splice]
# 9 Declarations [[dcl]](./#dcl)
## 9.2 Specifiers [[dcl.spec]](dcl.spec#dcl.type.splice)
### 9.2.9 Type specifiers [[dcl.type]](dcl.type#splice)
#### 9.2.9.9 Type splicing [dcl.type.splice]
[splice-type-specifier:](#nt:splice-type-specifier "9.2.9.9Type splicing[dcl.type.splice]")
typenameopt [*splice-specifier*](basic.splice#nt:splice-specifier "6.6Splice specifiers[basic.splice]")
typenameopt [*splice-specialization-specifier*](basic.splice#nt:splice-specialization-specifier "6.6Splice specifiers[basic.splice]")
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L2318)
A [*splice-specifier*](basic.splice#nt:splice-specifier "6.6Splice specifiers[basic.splice]") or[*splice-specialization-specifier*](basic.splice#nt:splice-specialization-specifier "6.6Splice specifiers[basic.splice]") immediately followed by :: is never interpreted as part of a [*splice-type-specifier*](#nt:splice-type-specifier "9.2.9.9Type splicing[dcl.type.splice]")[.](#1.sentence-1)
A [*splice-specifier*](basic.splice#nt:splice-specifier "6.6Splice specifiers[basic.splice]") or[*splice-specialization-specifier*](basic.splice#nt:splice-specialization-specifier "6.6Splice specifiers[basic.splice]") not preceded by typename is only interpreted as a [*splice-type-specifier*](#nt:splice-type-specifier "9.2.9.9Type splicing[dcl.type.splice]") within a type-only context ([[temp.res.general]](temp.res.general "13.8.1General"))[.](#1.sentence-2)
[*Example [1](#example-1)*: template<std::meta::info R> void tfn() {typename [:R:]::type m; // OK, typename applies to the qualified name}struct S { using type = int; };void fn() {[:^^S::type:] *var; // error: [:^^S::type:] is an expressiontypename [:^^S::type:] *var; // OK, declares variable with type int*}using alias = [:^^S::type:]; // OK, type-only context — *end example*]
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L2344)
For a [*splice-type-specifier*](#nt:splice-type-specifier "9.2.9.9Type splicing[dcl.type.splice]") of the formtypenameopt [*splice-specifier*](basic.splice#nt:splice-specifier "6.6Splice specifiers[basic.splice]"),
the [*splice-specifier*](basic.splice#nt:splice-specifier "6.6Splice specifiers[basic.splice]") shall designate
a type, a class template, or an alias template[.](#2.sentence-1)
The [*splice-type-specifier*](#nt:splice-type-specifier "9.2.9.9Type splicing[dcl.type.splice]") designates
the same entity as the [*splice-specifier*](basic.splice#nt:splice-specifier "6.6Splice specifiers[basic.splice]")[.](#2.sentence-2)
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L2352)
For a [*splice-type-specifier*](#nt:splice-type-specifier "9.2.9.9Type splicing[dcl.type.splice]") of the formtypenameopt [*splice-specialization-specifier*](basic.splice#nt:splice-specialization-specifier "6.6Splice specifiers[basic.splice]"),
the [*splice-specifier*](basic.splice#nt:splice-specifier "6.6Splice specifiers[basic.splice]") of
the [*splice-specialization-specifier*](basic.splice#nt:splice-specialization-specifier "6.6Splice specifiers[basic.splice]") shall designate a template T that is either a class template or an alias template[.](#3.sentence-1)
The [*splice-type-specifier*](#nt:splice-type-specifier "9.2.9.9Type splicing[dcl.type.splice]") designates
the specialization of T corresponding to
the template argument list of the [*splice-specialization-specifier*](basic.splice#nt:splice-specialization-specifier "6.6Splice specifiers[basic.splice]")[.](#3.sentence-2)

121
cppdraft/dcl/typedef.md Normal file
View File

@@ -0,0 +1,121 @@
[dcl.typedef]
# 9 Declarations [[dcl]](./#dcl)
## 9.2 Specifiers [[dcl.spec]](dcl.spec#dcl.typedef)
### 9.2.4 The typedef specifier [dcl.typedef]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L743)
Declarations containing the [*decl-specifier*](dcl.spec.general#nt:decl-specifier "9.2.1General[dcl.spec.general]") typedef declare [*type aliases*](#def:alias,type "9.2.4The typedef specifier[dcl.typedef]")[.](#1.sentence-1)
The typedef specifier shall not be
combined in a [*decl-specifier-seq*](dcl.spec.general#nt:decl-specifier-seq "9.2.1General[dcl.spec.general]") with any other kind of
specifier except a [*defining-type-specifier*](dcl.type.general#nt:defining-type-specifier "9.2.9.1General[dcl.type.general]"), and it shall not be used in the[*decl-specifier-seq*](dcl.spec.general#nt:decl-specifier-seq "9.2.1General[dcl.spec.general]") of a[*parameter-declaration*](dcl.fct#nt:parameter-declaration "9.3.4.6Functions[dcl.fct]") ([[dcl.fct]](dcl.fct "9.3.4.6Functions")) nor in the[*decl-specifier-seq*](dcl.spec.general#nt:decl-specifier-seq "9.2.1General[dcl.spec.general]") of a[*function-definition*](dcl.fct.def.general#nt:function-definition "9.6.1General[dcl.fct.def.general]") ([[dcl.fct.def]](dcl.fct.def "9.6Function definitions"))[.](#1.sentence-2)
If a typedef specifier appears in a declaration without a [*declarator*](dcl.decl.general#nt:declarator "9.3.1General[dcl.decl.general]"),
the program is ill-formed[.](#1.sentence-3)
[typedef-name:](#nt:typedef-name "9.2.4The typedef specifier[dcl.typedef]")
[*identifier*](lex.name#nt:identifier "5.11Identifiers[lex.name]")
[*simple-template-id*](temp.names#nt:simple-template-id "13.3Names of template specializations[temp.names]")
A name declared with the typedef specifier becomes a[*typedef-name*](#nt:typedef-name "9.2.4The typedef specifier[dcl.typedef]")[.](#1.sentence-4)
The underlying entity of the type alias is
the type associated with the [*identifier*](lex.name#nt:identifier "5.11Identifiers[lex.name]") ([[dcl.decl]](dcl.decl "9.3Declarators"))
or [*simple-template-id*](temp.names#nt:simple-template-id "13.3Names of template specializations[temp.names]") ([[temp.pre]](temp.pre "13.1Preamble"))[.](#1.sentence-5)
A [*typedef-name*](#nt:typedef-name "9.2.4The typedef specifier[dcl.typedef]") does not introduce a new type the way a class
declaration ([[class.name]](class.name "11.3Class names")) or enum declaration ([[dcl.enum]](dcl.enum "9.8.1Enumeration declarations")) does[.](#1.sentence-6)
[*Example [1](#example-1)*:
Aftertypedef int MILES, *KLICKSP; the constructionsMILES distance;extern KLICKSP metricp; are all correct declarations; the type of distance isint and that of metricp is “pointer to int”[.](#1.sentence-7)
— *end example*]
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L785)
A type alias can also be declared by an[*alias-declaration*](dcl.pre#nt:alias-declaration "9.1Preamble[dcl.pre]")[.](#2.sentence-1)
The [*identifier*](lex.name#nt:identifier "5.11Identifiers[lex.name]") following theusing keyword is not looked up;
it becomes the [*typedef-name*](#nt:typedef-name "9.2.4The typedef specifier[dcl.typedef]") of a type alias
and the optional [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") following the[*identifier*](lex.name#nt:identifier "5.11Identifiers[lex.name]") appertains to that type alias[.](#2.sentence-2)
Such a type alias has the same
semantics as if it were introduced by the typedef specifier[.](#2.sentence-3)
[*Example [2](#example-2)*: using handler_t = void (*)(int);extern handler_t ignore;extern void (*ignore)(int); // redeclare ignoretemplate<class T> struct P { };using cell = P<cell*>; // error: cell not found ([[basic.scope.pdecl]](basic.scope.pdecl "6.4.2Point of declaration")) — *end example*]
The [*defining-type-specifier-seq*](dcl.type.general#nt:defining-type-specifier-seq "9.2.9.1General[dcl.type.general]") of the [*defining-type-id*](dcl.name#nt:defining-type-id "9.3.2Type names[dcl.name]") shall not define
a class or enumeration if the [*alias-declaration*](dcl.pre#nt:alias-declaration "9.1Preamble[dcl.pre]") is the [*declaration*](dcl.pre#nt:declaration "9.1Preamble[dcl.pre]") of a [*template-declaration*](temp.pre#nt:template-declaration "13.1Preamble[temp.pre]")[.](#2.sentence-4)
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L808)
A [*simple-template-id*](temp.names#nt:simple-template-id "13.3Names of template specializations[temp.names]") is only a [*typedef-name*](#nt:typedef-name "9.2.4The typedef specifier[dcl.typedef]") if its [*template-name*](temp.names#nt:template-name "13.3Names of template specializations[temp.names]") names
an alias template or a type template template parameter[.](#3.sentence-1)
[*Note [1](#note-1)*:
A [*simple-template-id*](temp.names#nt:simple-template-id "13.3Names of template specializations[temp.names]") that names a class template specialization
is a [*class-name*](class.pre#nt:class-name "11.1Preamble[class.pre]") ([[class.name]](class.name "11.3Class names"))[.](#3.sentence-2)
If a [*typedef-name*](#nt:typedef-name "9.2.4The typedef specifier[dcl.typedef]") is used to identify the subject of an[*elaborated-type-specifier*](dcl.type.elab#nt:elaborated-type-specifier "9.2.9.5Elaborated type specifiers[dcl.type.elab]") ([[dcl.type.elab]](dcl.type.elab "9.2.9.5Elaborated type specifiers")), a [class
definition](class "11Classes[class]"), a [constructor
declaration](class.ctor "11.4.5Constructors[class.ctor]"), or a [destructor
declaration](class.dtor "11.4.7Destructors[class.dtor]"), the program is ill-formed[.](#3.sentence-3)
— *end note*]
[*Example [3](#example-3)*: struct S { S(); ~S();};
typedef struct S T;
S a = T(); // OKstruct T * p; // error — *end example*]
[4](#4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L836)
An unnamed class or enumeration C defined in a typedef declaration has
the first [*typedef-name*](#nt:typedef-name "9.2.4The typedef specifier[dcl.typedef]") declared by the declaration to be of type C as its [*typedef name for linkage purposes*](#def:typedef_name_for_linkage_purposes "9.2.4The typedef specifier[dcl.typedef]") ([[basic.link]](basic.link "6.7Program and linkage"))[.](#4.sentence-1)
[*Note [2](#note-2)*:
A typedef declaration involving a [*lambda-expression*](expr.prim.lambda.general#nt:lambda-expression "7.5.6.1General[expr.prim.lambda.general]") does not itself define the associated closure type,
and so the closure type is not given a typedef name for linkage purposes[.](#4.sentence-2)
— *end note*]
[*Example [4](#example-4)*: typedef struct { } *ps, S; // S is the typedef name for linkage purposestypedef decltype([]{}) C; // the closure type has no typedef name for linkage purposes — *end example*]
[5](#5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L856)
An unnamed class with a typedef name for linkage purposes shall not
- [(5.1)](#5.1)
declare any members
other than non-static data members, member enumerations, or member classes,
- [(5.2)](#5.2)
have any base classes or default member initializers, or
- [(5.3)](#5.3)
contain a [*lambda-expression*](expr.prim.lambda.general#nt:lambda-expression "7.5.6.1General[expr.prim.lambda.general]"),
and all member classes shall also satisfy these requirements (recursively)[.](#5.sentence-1)
[*Example [5](#example-5)*: typedef struct {int f() {}} X; // error: struct with typedef name for linkage has member functions — *end example*]