Init
This commit is contained in:
102
cppdraft/dcl/align.md
Normal file
102
cppdraft/dcl/align.md
Normal 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.1 Attribute 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.1 Preamble [except.pre]") ([[except.handle]](except.handle "14.4 Handling an exception"))[.](#1.sentence-1)
|
||||
|
||||
An [*alignment-specifier*](dcl.attr.grammar#nt:alignment-specifier "9.13.1 Attribute 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.5 Elaborated type specifiers [dcl.type.elab]") ([[dcl.type.elab]](dcl.type.elab "9.2.9.5 Elaborated type specifiers")) or[*class-head*](class.pre#nt:class-head "11.1 Preamble [class.pre]") ([[class]](class "11 Classes")), respectively)[.](#1.sentence-2)
|
||||
|
||||
An [*alignment-specifier*](dcl.attr.grammar#nt:alignment-specifier "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]") with an ellipsis is a pack expansion ([[temp.variadic]](temp.variadic "13.7.4 Variadic 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.1 Attribute syntax and semantics [dcl.attr.grammar]") is of the formalignas( [*constant-expression*](expr.const#nt:constant-expression "7.7 Constant expressions [expr.const]") ):
|
||||
|
||||
- [(2.1)](#2.1)
|
||||
|
||||
the [*constant-expression*](expr.const#nt:constant-expression "7.7 Constant 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.3 Alignment")), 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.1 Attribute syntax and semantics [dcl.attr.grammar]") of the formalignas( [*type-id*](dcl.name#nt:type-id "9.3.2 Type names [dcl.name]") ) has the same
|
||||
effect as alignas([alignof](expr.alignof "7.6.2.6 Alignof [expr.alignof]")( [*type-id*](dcl.name#nt:type-id "9.3.2 Type 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.1 Attribute syntax and semantics [dcl.attr.grammar]")*s*, if any;
|
||||
otherwise, the [*alignment-specifier*](dcl.attr.grammar#nt:alignment-specifier "9.13.1 Attribute 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.1 Attribute 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.1 Attribute 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.1 Attribute 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.1 Attribute 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.1 Attribute 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.1 Attribute 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
76
cppdraft/dcl/ambig/res.md
Normal 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.11 Ambiguity 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.11 Ambiguity 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.1 Preamble [dcl.pre]") whose outermost [*declarator*](dcl.decl.general#nt:declarator "9.3.1 General [dcl.decl.general]") would match the grammar of a [*declarator*](dcl.decl.general#nt:declarator "9.3.1 General [dcl.decl.general]") with a [*trailing-return-type*](dcl.decl.general#nt:trailing-return-type "9.3.1 General [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.2 Type 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.2 Type names [dcl.name]") in its syntactic context shall be considered a[*type-id*](dcl.name#nt:type-id "9.3.2 Type names [dcl.name]")[.](#2.sentence-2)
|
||||
|
||||
However, a construct that can syntactically be a [*type-id*](dcl.name#nt:type-id "9.3.2 Type names [dcl.name]") whose outermost [*abstract-declarator*](dcl.name#nt:abstract-declarator "9.3.2 Type names [dcl.name]") would match the grammar of an [*abstract-declarator*](dcl.name#nt:abstract-declarator "9.3.2 Type names [dcl.name]") with a [*trailing-return-type*](dcl.decl.general#nt:trailing-return-type "9.3.1 General [dcl.decl.general]") is considered a [*type-id*](dcl.name#nt:type-id "9.3.2 Type 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.6 Functions [dcl.fct]") when a[*type-name*](dcl.type.simple#nt:type-name "9.2.9.3 Simple 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.1 General [dcl.decl.general]")[.](#3.sentence-2)
|
||||
|
||||
The resolution is to consider the[*type-name*](dcl.type.simple#nt:type-name "9.2.9.3 Simple type specifiers [dcl.type.simple]") as a[*simple-type-specifier*](dcl.type.simple#nt:simple-type-specifier "9.2.9.3 Simple type specifiers [dcl.type.simple]") rather than a[*declarator-id*](dcl.decl.general#nt:declarator-id "9.3.1 General [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
216
cppdraft/dcl/array.md
Normal 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.7 Constant expressions [expr.const]")opt ] [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]")opt
|
||||
|
||||
and the type of the contained [*declarator-id*](dcl.decl.general#nt:declarator-id "9.3.1 General [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.1 General [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.7 Constant expressions [expr.const]") shall be a converted constant expression of type std::size_t ([[expr.const]](expr.const "7.7 Constant expressions"))[.](#1.sentence-2)
|
||||
|
||||
Its value N specifies the [*array bound*](#def:array,bound "9.3.4.5 Arrays [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.1 Attribute syntax and semantics [dcl.attr.grammar]")opt
|
||||
|
||||
and the type of the contained [*declarator-id*](dcl.decl.general#nt:declarator-id "9.3.1 General [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.1 General [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.5 Arrays [dcl.array]")[.](#3.sentence-1)
|
||||
|
||||
The optional [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1 Attribute 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.5 Arrays [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.1 General [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.1 General [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.1 General [dcl.decl.general]") Uâ
|
||||
has cv-qualified type; see [[basic.type.qualifier]](basic.type.qualifier "6.9.5 CV-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.5 Arrays [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.6 Functions"))[.](#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.5 Initializers"), [[class.mem]](class.mem "11.4 Class members"), [[expr.type.conv]](expr.type.conv "7.6.1.4 Explicit type conversion (functional notation)"), [[expr.new]](expr.new "7.6.2.8 New"))[.](#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.2 Aggregates")),
|
||||
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.1 General")),
|
||||
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.3 Array-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.3 Array-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.5 Subscripting"))[.](#11.sentence-1)
|
||||
|
||||
For the operator's built-in meaning, see [[expr.sub]](expr.sub "7.6.1.2 Subscripting")[.](#11.sentence-2)
|
||||
|
||||
â *end note*]
|
||||
28
cppdraft/dcl/asm.md
Normal file
28
cppdraft/dcl/asm.md
Normal 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.11 The asm declaration [dcl.asm]")
|
||||
[*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]")opt asm ( [*balanced-token-seq*](dcl.attr.grammar#nt:balanced-token-seq "9.13.1 Attribute 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.1 Attribute 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.1 Attribute syntax and semantics [dcl.attr.grammar]") in
|
||||
an [*asm-declaration*](#nt:asm-declaration "9.11 The 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
881
cppdraft/dcl/attr.md
Normal 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.1 Attribute syntax and semantics [dcl.attr.grammar]")
|
||||
[*attribute-specifier*](#nt:attribute-specifier "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]") [*attribute-specifier-seq*](#nt:attribute-specifier-seq "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]")opt
|
||||
|
||||
[attribute-specifier:](#nt:attribute-specifier "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]")
|
||||
[ [ [*attribute-using-prefix*](#nt:attribute-using-prefix "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]")opt [*attribute-list*](#nt:attribute-list "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]") ] ]
|
||||
[ [ [*annotation-list*](#nt:annotation-list "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]") ] ]
|
||||
[*alignment-specifier*](#nt:alignment-specifier "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]")
|
||||
|
||||
[alignment-specifier:](#nt:alignment-specifier "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]")
|
||||
alignas ( [*type-id*](dcl.name#nt:type-id "9.3.2 Type names [dcl.name]") ...opt )
|
||||
alignas ( [*constant-expression*](expr.const#nt:constant-expression "7.7 Constant expressions [expr.const]") ...opt )
|
||||
|
||||
[attribute-using-prefix:](#nt:attribute-using-prefix "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]")
|
||||
using [*attribute-namespace*](#nt:attribute-namespace "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]") :
|
||||
|
||||
[attribute-list:](#nt:attribute-list "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]")
|
||||
[*attribute*](#nt:attribute "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]")opt
|
||||
[*attribute-list*](#nt:attribute-list "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]") , [*attribute*](#nt:attribute "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]")opt
|
||||
[*attribute*](#nt:attribute "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]") ...
|
||||
[*attribute-list*](#nt:attribute-list "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]") , [*attribute*](#nt:attribute "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]") ...
|
||||
|
||||
[annotation-list:](#nt:annotation-list "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]")
|
||||
[*annotation*](#nt:annotation "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]") ...opt
|
||||
[*annotation-list*](#nt:annotation-list "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]") , [*annotation*](#nt:annotation "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]") ...opt
|
||||
|
||||
[attribute:](#nt:attribute "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]")
|
||||
[*attribute-token*](#nt:attribute-token "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]") [*attribute-argument-clause*](#nt:attribute-argument-clause "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]")opt
|
||||
|
||||
[annotation:](#nt:annotation "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]")
|
||||
= [*constant-expression*](expr.const#nt:constant-expression "7.7 Constant expressions [expr.const]")
|
||||
|
||||
[attribute-token:](#nt:attribute-token "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]")
|
||||
[*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]")
|
||||
[*attribute-scoped-token*](#nt:attribute-scoped-token "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]")
|
||||
|
||||
[attribute-scoped-token:](#nt:attribute-scoped-token "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]")
|
||||
[*attribute-namespace*](#nt:attribute-namespace "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]") :: [*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]")
|
||||
|
||||
[attribute-namespace:](#nt:attribute-namespace "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]")
|
||||
[*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]")
|
||||
|
||||
[attribute-argument-clause:](#nt:attribute-argument-clause "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]")
|
||||
( [*balanced-token-seq*](#nt:balanced-token-seq "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]")opt )
|
||||
|
||||
[balanced-token-seq:](#nt:balanced-token-seq "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]")
|
||||
[*balanced-token*](#nt:balanced-token "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]") [*balanced-token-seq*](#nt:balanced-token-seq "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]")opt
|
||||
|
||||
[balanced-token:](#nt:balanced-token "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]")
|
||||
( [*balanced-token-seq*](#nt:balanced-token-seq "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]")opt )
|
||||
[ [*balanced-token-seq*](#nt:balanced-token-seq "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]")opt ]
|
||||
{ [*balanced-token-seq*](#nt:balanced-token-seq "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]")opt }
|
||||
[: [*balanced-token-seq*](#nt:balanced-token-seq "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]")opt :]
|
||||
any [*token*](lex.token#nt:token "5.10 Tokens [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.1 Attribute syntax and semantics [dcl.attr.grammar]") contains an [*attribute-using-prefix*](#nt:attribute-using-prefix "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]"),
|
||||
the [*attribute-list*](#nt:attribute-list "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]") following that [*attribute-using-prefix*](#nt:attribute-using-prefix "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]") shall not contain an [*attribute-scoped-token*](#nt:attribute-scoped-token "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]") and every [*attribute-token*](#nt:attribute-token "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]") in that [*attribute-list*](#nt:attribute-list "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]") is treated as if
|
||||
its [*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]") were prefixed with N::,
|
||||
where N is the [*attribute-namespace*](#nt:attribute-namespace "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]") specified in the [*attribute-using-prefix*](#nt:attribute-using-prefix "9.13.1 Attribute 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.1 Attribute syntax and semantics [dcl.attr.grammar]") affects the tokens in an [*attribute-argument-clause*](#nt:attribute-argument-clause "9.13.1 Attribute 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.1 Attribute 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.1 Attribute syntax and semantics [dcl.attr.grammar]"), an ellipsis may appear only if that[*attribute*](#nt:attribute "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]")'s specification permits it[.](#grammar-4.sentence-1)
|
||||
|
||||
An [*attribute*](#nt:attribute "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]") followed
|
||||
by an ellipsis is a [pack expansion](temp.variadic#def:pack_expansion "13.7.4 Variadic templates [temp.variadic]")[.](#grammar-4.sentence-2)
|
||||
|
||||
An [*attribute-specifier*](#nt:attribute-specifier "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]") that contains
|
||||
an [*attribute-list*](#nt:attribute-list "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]") with no [*attribute*](#nt:attribute "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]")*s* and no [*alignment-specifier*](#nt:alignment-specifier "9.13.1 Attribute 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.1 Attribute syntax and semantics [dcl.attr.grammar]")*s* appear in an[*attribute-list*](#nt:attribute-list "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]") is not significant[.](#grammar-4.sentence-4)
|
||||
|
||||
If a[keyword](lex.key "5.12 Keywords [lex.key]") or an [alternative token](lex.digraph "5.9 Alternative tokens [lex.digraph]") that satisfies the syntactic requirements
|
||||
of an [*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]") ([[lex.name]](lex.name "5.11 Identifiers")) is
|
||||
contained in
|
||||
an [*attribute-token*](#nt:attribute-token "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]"), it is considered an identifier[.](#grammar-4.sentence-5)
|
||||
|
||||
No[name lookup](basic.lookup "6.5 Name lookup [basic.lookup]") is performed on any of the identifiers contained in an[*attribute-token*](#nt:attribute-token "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]")[.](#grammar-4.sentence-6)
|
||||
|
||||
The [*attribute-token*](#nt:attribute-token "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]") determines additional
|
||||
requirements on the [*attribute-argument-clause*](#nt:attribute-argument-clause "9.13.1 Attribute 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.1 Attribute syntax and semantics [dcl.attr.grammar]") followed by an ellipsis
|
||||
is a pack expansion ([[temp.variadic]](temp.variadic "13.7.4 Variadic 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.1 Attribute syntax and semantics [dcl.attr.grammar]") is said to [*appertain*](#def:appertain "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]") to some entity or
|
||||
statement, identified by the syntactic context
|
||||
where it appears ([[stmt]](stmt "8 Statements"), [[dcl]](dcl "9 Declarations"), [[dcl.decl]](dcl.decl "9.3 Declarators"))[.](#grammar-6.sentence-1)
|
||||
|
||||
If an [*attribute-specifier-seq*](#nt:attribute-specifier-seq "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]") that appertains to some
|
||||
entity or statement contains an [*attribute*](#nt:attribute "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]") or [*alignment-specifier*](#nt:alignment-specifier "9.13.1 Attribute 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.1 Attribute syntax and semantics [dcl.attr.grammar]") appertains to a friend declaration ([[class.friend]](class.friend "11.8.4 Friends")), 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.1 Attribute syntax and semantics [dcl.attr.grammar]") cannot appertain to
|
||||
an explicit instantiation ([[temp.explicit]](temp.explicit "13.9.3 Explicit 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.1 Attribute syntax and semantics [dcl.attr.grammar]") (including an [*attribute-scoped-token*](#nt:attribute-scoped-token "9.13.1 Attribute 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.1 Attribute 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.1 Attribute 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.1 Attribute 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.1 Attribute 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.1 Attribute syntax and semantics [dcl.attr.grammar]")*s* results in a program whose set of possible executions ([[intro.abstract]](intro.abstract "4.1.2 Abstract 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.1 Attribute syntax and semantics [dcl.attr.grammar]")[.](#grammar-7.sentence-3)
|
||||
|
||||
â *end note*]
|
||||
|
||||
An [*attribute-token*](#nt:attribute-token "9.13.1 Attribute 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.1 Attribute 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.1 Attribute syntax and semantics [dcl.attr.grammar]") and
|
||||
its [*attribute-namespace*](#nt:attribute-namespace "9.13.1 Attribute 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.1 Attribute syntax and semantics [dcl.attr.grammar]") in an [*attribute-scoped-token*](#nt:attribute-scoped-token "9.13.1 Attribute 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.1 Attribute syntax and semantics [dcl.attr.grammar]") or
|
||||
within the [*balanced-token-seq*](#nt:balanced-token-seq "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]") of
|
||||
an [*attribute-argument-clause*](#nt:attribute-argument-clause "9.13.1 Attribute 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.1 Attribute 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.1 General [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.1 Attribute 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.1 Preamble [except.pre]") ([[except.handle]](except.handle "14.4 Handling an exception"))[.](#dcl.align-1.sentence-1)
|
||||
|
||||
An [*alignment-specifier*](#nt:alignment-specifier "9.13.1 Attribute 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.5 Elaborated type specifiers [dcl.type.elab]") ([[dcl.type.elab]](dcl.type.elab "9.2.9.5 Elaborated type specifiers")) or[*class-head*](class.pre#nt:class-head "11.1 Preamble [class.pre]") ([[class]](class "11 Classes")), respectively)[.](#dcl.align-1.sentence-2)
|
||||
|
||||
An [*alignment-specifier*](#nt:alignment-specifier "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]") with an ellipsis is a pack expansion ([[temp.variadic]](temp.variadic "13.7.4 Variadic 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.1 Attribute syntax and semantics [dcl.attr.grammar]") is of the formalignas( [*constant-expression*](expr.const#nt:constant-expression "7.7 Constant expressions [expr.const]") ):
|
||||
|
||||
- [(2.1)](#dcl.align-2.1)
|
||||
|
||||
the [*constant-expression*](expr.const#nt:constant-expression "7.7 Constant 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.3 Alignment")), 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.1 Attribute syntax and semantics [dcl.attr.grammar]") of the formalignas( [*type-id*](dcl.name#nt:type-id "9.3.2 Type names [dcl.name]") ) has the same
|
||||
effect as alignas([alignof](expr.alignof "7.6.2.6 Alignof [expr.alignof]")( [*type-id*](dcl.name#nt:type-id "9.3.2 Type 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.1 Attribute syntax and semantics [dcl.attr.grammar]")*s*, if any;
|
||||
otherwise, the [*alignment-specifier*](#nt:alignment-specifier "9.13.1 Attribute 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.1 Attribute 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.1 Attribute 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.1 Attribute 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.1 Attribute 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.1 Attribute 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.1 Attribute 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.1 Attribute syntax and semantics [dcl.attr.grammar]") assume may be applied to a null statement;
|
||||
such a statement is an [*assumption*](#def:assumption "9.13.3 Assumption attribute [dcl.attr.assume]")[.](#assume-1.sentence-1)
|
||||
|
||||
An [*attribute-argument-clause*](#nt:attribute-argument-clause "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]") shall be present and
|
||||
shall have the form:
|
||||
|
||||
( [*conditional-expression*](expr.cond#nt:conditional-expression "7.6.16 Conditional operator [expr.cond]") )
|
||||
|
||||
The expression is contextually converted to bool ([[conv.general]](conv.general "7.3.1 General"))[.](#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.3 One-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.2 Conditional 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.1 Attribute 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.1 Attribute 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.6 Unevaluated strings [lex.string.uneval]") )
|
||||
|
||||
[*Note [2](#deprecated-note-2)*:
|
||||
|
||||
The [*unevaluated-string*](lex.string.uneval#nt:unevaluated-string "5.13.6 Unevaluated strings [lex.string.uneval]") in the [*attribute-argument-clause*](#nt:attribute-argument-clause "9.13.1 Attribute 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.1 Attribute syntax and semantics [dcl.attr.grammar]") or with different[*attribute-argument-clause*](#nt:attribute-argument-clause "9.13.1 Attribute 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.1 Attribute 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.2 Conditional 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.1 Attribute syntax and semantics [dcl.attr.grammar]") fallthrough may be applied to a [null statement](stmt.expr#def:statement,null "8.3 Expression statement [stmt.expr]"); such a statement is a fallthrough statement[.](#fallthrough-1.sentence-1)
|
||||
|
||||
No [*attribute-argument-clause*](#nt:attribute-argument-clause "9.13.1 Attribute 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.3 The 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.2 Conditional 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.1 Attribute 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.6 Functions [dcl.fct]") of a function declaration[.](#indet-1.sentence-1)
|
||||
|
||||
No [*attribute-argument-clause*](#nt:attribute-argument-clause "9.13.1 Attribute 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.5 Indeterminate 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.5 Indeterminate 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.1 Attribute 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.1 Attribute syntax and semantics [dcl.attr.grammar]") shall be present[.](#likelihood-1.sentence-2)
|
||||
|
||||
The [*attribute-token*](#nt:attribute-token "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]") likely shall not appear in an [*attribute-specifier-seq*](#nt:attribute-specifier-seq "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]") that contains the [*attribute-token*](#nt:attribute-token "9.13.1 Attribute 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.2 Conditional 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.1 Attribute 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.1 Attribute 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.2 Referring to the result object")),
|
||||
non-static data member,
|
||||
function,
|
||||
enumeration, or
|
||||
enumerator, or
|
||||
to an [*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]") label ([[stmt.label]](stmt.label "8.2 Label"))[.](#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.2 Conditional 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.1 Attribute 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.1 Attribute 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.6 Unevaluated 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.1 Attribute syntax and semantics [dcl.attr.grammar]") or with different [*attribute-argument-clause*](#nt:attribute-argument-clause "9.13.1 Attribute 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.9 Nodiscard 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.9 Nodiscard attribute [dcl.attr.nodiscard]") is either
|
||||
|
||||
- [(3.1)](#nodiscard-3.1)
|
||||
|
||||
a function call expression ([[expr.call]](expr.call "7.6.1.3 Function 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.4 Explicit type conversion (functional notation)"), [[expr.static.cast]](expr.static.cast "7.6.1.9 Static cast"), [[expr.cast]](expr.cast "7.6.3 Explicit 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.2 Properties 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.2 Conditional 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.6 Unevaluated strings [lex.string.uneval]") in a nodiscard [*attribute-argument-clause*](#nt:attribute-argument-clause "9.13.1 Attribute 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.1 Attribute 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.1 Attribute 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.2 Conditional 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.1 Attribute 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.2 Object model"))[.](#nouniqueaddr-1.sentence-1)
|
||||
|
||||
No [*attribute-argument-clause*](#nt:attribute-argument-clause "9.13.1 Attribute 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.2 Conditional 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.1 General [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.7 Constant 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.12 Annotations [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.1 Attribute 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.1 Attribute 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.18 Annotation 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*]
|
||||
57
cppdraft/dcl/attr/annotation.md
Normal file
57
cppdraft/dcl/attr/annotation.md
Normal 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.1 General [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.7 Constant 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.12 Annotations [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.1 Attribute 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.1 Attribute 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.18 Annotation 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*]
|
||||
57
cppdraft/dcl/attr/assume.md
Normal file
57
cppdraft/dcl/attr/assume.md
Normal 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.1 Attribute syntax and semantics [dcl.attr.grammar]") assume may be applied to a null statement;
|
||||
such a statement is an [*assumption*](#def:assumption "9.13.3 Assumption attribute [dcl.attr.assume]")[.](#1.sentence-1)
|
||||
|
||||
An [*attribute-argument-clause*](dcl.attr.grammar#nt:attribute-argument-clause "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]") shall be present and
|
||||
shall have the form:
|
||||
|
||||
( [*conditional-expression*](expr.cond#nt:conditional-expression "7.6.16 Conditional operator [expr.cond]") )
|
||||
|
||||
The expression is contextually converted to bool ([[conv.general]](conv.general "7.3.1 General"))[.](#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.3 One-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.2 Conditional 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*]
|
||||
82
cppdraft/dcl/attr/deprecated.md
Normal file
82
cppdraft/dcl/attr/deprecated.md
Normal 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.1 Attribute 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.1 Attribute 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.6 Unevaluated strings [lex.string.uneval]") )
|
||||
|
||||
[*Note [2](#note-2)*:
|
||||
|
||||
The [*unevaluated-string*](lex.string.uneval#nt:unevaluated-string "5.13.6 Unevaluated strings [lex.string.uneval]") in the [*attribute-argument-clause*](dcl.attr.grammar#nt:attribute-argument-clause "9.13.1 Attribute 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.1 Attribute syntax and semantics [dcl.attr.grammar]") or with different[*attribute-argument-clause*](dcl.attr.grammar#nt:attribute-argument-clause "9.13.1 Attribute 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.1 Attribute 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.2 Conditional inclusion [cpp.cond]") for the deprecated attribute
|
||||
should be 0 unless the implementation can issue such diagnostic messages[.](#4.sentence-3)
|
||||
49
cppdraft/dcl/attr/fallthrough.md
Normal file
49
cppdraft/dcl/attr/fallthrough.md
Normal 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.1 Attribute syntax and semantics [dcl.attr.grammar]") fallthrough may be applied to a [null statement](stmt.expr#def:statement,null "8.3 Expression 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.1 Attribute 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.3 The 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.2 Conditional 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*]
|
||||
213
cppdraft/dcl/attr/grammar.md
Normal file
213
cppdraft/dcl/attr/grammar.md
Normal 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.1 Attribute syntax and semantics [dcl.attr.grammar]")
|
||||
[*attribute-specifier*](#nt:attribute-specifier "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]") [*attribute-specifier-seq*](#nt:attribute-specifier-seq "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]")opt
|
||||
|
||||
[attribute-specifier:](#nt:attribute-specifier "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]")
|
||||
[ [ [*attribute-using-prefix*](#nt:attribute-using-prefix "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]")opt [*attribute-list*](#nt:attribute-list "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]") ] ]
|
||||
[ [ [*annotation-list*](#nt:annotation-list "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]") ] ]
|
||||
[*alignment-specifier*](#nt:alignment-specifier "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]")
|
||||
|
||||
[alignment-specifier:](#nt:alignment-specifier "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]")
|
||||
alignas ( [*type-id*](dcl.name#nt:type-id "9.3.2 Type names [dcl.name]") ...opt )
|
||||
alignas ( [*constant-expression*](expr.const#nt:constant-expression "7.7 Constant expressions [expr.const]") ...opt )
|
||||
|
||||
[attribute-using-prefix:](#nt:attribute-using-prefix "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]")
|
||||
using [*attribute-namespace*](#nt:attribute-namespace "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]") :
|
||||
|
||||
[attribute-list:](#nt:attribute-list "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]")
|
||||
[*attribute*](#nt:attribute "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]")opt
|
||||
[*attribute-list*](#nt:attribute-list "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]") , [*attribute*](#nt:attribute "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]")opt
|
||||
[*attribute*](#nt:attribute "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]") ...
|
||||
[*attribute-list*](#nt:attribute-list "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]") , [*attribute*](#nt:attribute "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]") ...
|
||||
|
||||
[annotation-list:](#nt:annotation-list "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]")
|
||||
[*annotation*](#nt:annotation "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]") ...opt
|
||||
[*annotation-list*](#nt:annotation-list "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]") , [*annotation*](#nt:annotation "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]") ...opt
|
||||
|
||||
[attribute:](#nt:attribute "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]")
|
||||
[*attribute-token*](#nt:attribute-token "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]") [*attribute-argument-clause*](#nt:attribute-argument-clause "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]")opt
|
||||
|
||||
[annotation:](#nt:annotation "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]")
|
||||
= [*constant-expression*](expr.const#nt:constant-expression "7.7 Constant expressions [expr.const]")
|
||||
|
||||
[attribute-token:](#nt:attribute-token "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]")
|
||||
[*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]")
|
||||
[*attribute-scoped-token*](#nt:attribute-scoped-token "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]")
|
||||
|
||||
[attribute-scoped-token:](#nt:attribute-scoped-token "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]")
|
||||
[*attribute-namespace*](#nt:attribute-namespace "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]") :: [*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]")
|
||||
|
||||
[attribute-namespace:](#nt:attribute-namespace "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]")
|
||||
[*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]")
|
||||
|
||||
[attribute-argument-clause:](#nt:attribute-argument-clause "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]")
|
||||
( [*balanced-token-seq*](#nt:balanced-token-seq "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]")opt )
|
||||
|
||||
[balanced-token-seq:](#nt:balanced-token-seq "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]")
|
||||
[*balanced-token*](#nt:balanced-token "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]") [*balanced-token-seq*](#nt:balanced-token-seq "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]")opt
|
||||
|
||||
[balanced-token:](#nt:balanced-token "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]")
|
||||
( [*balanced-token-seq*](#nt:balanced-token-seq "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]")opt )
|
||||
[ [*balanced-token-seq*](#nt:balanced-token-seq "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]")opt ]
|
||||
{ [*balanced-token-seq*](#nt:balanced-token-seq "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]")opt }
|
||||
[: [*balanced-token-seq*](#nt:balanced-token-seq "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]")opt :]
|
||||
any [*token*](lex.token#nt:token "5.10 Tokens [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.1 Attribute syntax and semantics [dcl.attr.grammar]") contains an [*attribute-using-prefix*](#nt:attribute-using-prefix "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]"),
|
||||
the [*attribute-list*](#nt:attribute-list "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]") following that [*attribute-using-prefix*](#nt:attribute-using-prefix "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]") shall not contain an [*attribute-scoped-token*](#nt:attribute-scoped-token "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]") and every [*attribute-token*](#nt:attribute-token "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]") in that [*attribute-list*](#nt:attribute-list "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]") is treated as if
|
||||
its [*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]") were prefixed with N::,
|
||||
where N is the [*attribute-namespace*](#nt:attribute-namespace "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]") specified in the [*attribute-using-prefix*](#nt:attribute-using-prefix "9.13.1 Attribute 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.1 Attribute syntax and semantics [dcl.attr.grammar]") affects the tokens in an [*attribute-argument-clause*](#nt:attribute-argument-clause "9.13.1 Attribute 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.1 Attribute 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.1 Attribute syntax and semantics [dcl.attr.grammar]"), an ellipsis may appear only if that[*attribute*](#nt:attribute "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]")'s specification permits it[.](#4.sentence-1)
|
||||
|
||||
An [*attribute*](#nt:attribute "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]") followed
|
||||
by an ellipsis is a [pack expansion](temp.variadic#def:pack_expansion "13.7.4 Variadic templates [temp.variadic]")[.](#4.sentence-2)
|
||||
|
||||
An [*attribute-specifier*](#nt:attribute-specifier "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]") that contains
|
||||
an [*attribute-list*](#nt:attribute-list "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]") with no [*attribute*](#nt:attribute "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]")*s* and no [*alignment-specifier*](#nt:alignment-specifier "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]") has no effect[.](#4.sentence-3)
|
||||
|
||||
The order in which the [*attribute-token*](#nt:attribute-token "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]")*s* appear in an[*attribute-list*](#nt:attribute-list "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]") is not significant[.](#4.sentence-4)
|
||||
|
||||
If a[keyword](lex.key "5.12 Keywords [lex.key]") or an [alternative token](lex.digraph "5.9 Alternative tokens [lex.digraph]") that satisfies the syntactic requirements
|
||||
of an [*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]") ([[lex.name]](lex.name "5.11 Identifiers")) is
|
||||
contained in
|
||||
an [*attribute-token*](#nt:attribute-token "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]"), it is considered an identifier[.](#4.sentence-5)
|
||||
|
||||
No[name lookup](basic.lookup "6.5 Name lookup [basic.lookup]") is performed on any of the identifiers contained in an[*attribute-token*](#nt:attribute-token "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]")[.](#4.sentence-6)
|
||||
|
||||
The [*attribute-token*](#nt:attribute-token "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]") determines additional
|
||||
requirements on the [*attribute-argument-clause*](#nt:attribute-argument-clause "9.13.1 Attribute 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.1 Attribute syntax and semantics [dcl.attr.grammar]") followed by an ellipsis
|
||||
is a pack expansion ([[temp.variadic]](temp.variadic "13.7.4 Variadic 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.1 Attribute syntax and semantics [dcl.attr.grammar]") is said to [*appertain*](#def:appertain "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]") to some entity or
|
||||
statement, identified by the syntactic context
|
||||
where it appears ([[stmt]](stmt "8 Statements"), [[dcl]](dcl "9 Declarations"), [[dcl.decl]](dcl.decl "9.3 Declarators"))[.](#6.sentence-1)
|
||||
|
||||
If an [*attribute-specifier-seq*](#nt:attribute-specifier-seq "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]") that appertains to some
|
||||
entity or statement contains an [*attribute*](#nt:attribute "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]") or [*alignment-specifier*](#nt:alignment-specifier "9.13.1 Attribute 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.1 Attribute syntax and semantics [dcl.attr.grammar]") appertains to a friend declaration ([[class.friend]](class.friend "11.8.4 Friends")), that declaration shall be a
|
||||
definition[.](#6.sentence-3)
|
||||
|
||||
[*Note [3](#note-3)*:
|
||||
|
||||
An [*attribute-specifier-seq*](#nt:attribute-specifier-seq "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]") cannot appertain to
|
||||
an explicit instantiation ([[temp.explicit]](temp.explicit "13.9.3 Explicit 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.1 Attribute syntax and semantics [dcl.attr.grammar]") (including an [*attribute-scoped-token*](#nt:attribute-scoped-token "9.13.1 Attribute 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.1 Attribute 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.1 Attribute syntax and semantics [dcl.attr.grammar]") specified in [[dcl.attr]](dcl.attr "9.13 Attributes") 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.1 Attribute syntax and semantics [dcl.attr.grammar]"), if any[.](#7.sentence-2)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[*Note [5](#note-5)*:
|
||||
|
||||
The [*attribute*](#nt:attribute "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]")*s* specified in [[dcl.attr]](dcl.attr "9.13 Attributes") have optional semantics:
|
||||
given a well-formed program,
|
||||
removing all instances of any one of those [*attribute*](#nt:attribute "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]")*s* results in a program whose set of possible executions ([[intro.abstract]](intro.abstract "4.1.2 Abstract 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.1 Attribute syntax and semantics [dcl.attr.grammar]")[.](#7.sentence-3)
|
||||
|
||||
â *end note*]
|
||||
|
||||
An [*attribute-token*](#nt:attribute-token "9.13.1 Attribute 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.1 Attribute 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.1 Attribute syntax and semantics [dcl.attr.grammar]") and
|
||||
its [*attribute-namespace*](#nt:attribute-namespace "9.13.1 Attribute 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.1 Attribute syntax and semantics [dcl.attr.grammar]") in an [*attribute-scoped-token*](#nt:attribute-scoped-token "9.13.1 Attribute 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.1 Attribute syntax and semantics [dcl.attr.grammar]") or
|
||||
within the [*balanced-token-seq*](#nt:balanced-token-seq "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]") of
|
||||
an [*attribute-argument-clause*](#nt:attribute-argument-clause "9.13.1 Attribute 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.1 Attribute 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.1 General [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*]
|
||||
47
cppdraft/dcl/attr/indet.md
Normal file
47
cppdraft/dcl/attr/indet.md
Normal 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.1 Attribute 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.6 Functions [dcl.fct]") of a function declaration[.](#1.sentence-1)
|
||||
|
||||
No [*attribute-argument-clause*](dcl.attr.grammar#nt:attribute-argument-clause "9.13.1 Attribute 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.5 Indeterminate 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.5 Indeterminate 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*]
|
||||
59
cppdraft/dcl/attr/likelihood.md
Normal file
59
cppdraft/dcl/attr/likelihood.md
Normal 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.1 Attribute 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.1 Attribute syntax and semantics [dcl.attr.grammar]") shall be present[.](#1.sentence-2)
|
||||
|
||||
The [*attribute-token*](dcl.attr.grammar#nt:attribute-token "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]") likely shall not appear in an [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]") that contains the [*attribute-token*](dcl.attr.grammar#nt:attribute-token "9.13.1 Attribute 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.2 Conditional 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*]
|
||||
96
cppdraft/dcl/attr/nodiscard.md
Normal file
96
cppdraft/dcl/attr/nodiscard.md
Normal 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.1 Attribute 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.1 Attribute 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.6 Unevaluated 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.1 Attribute syntax and semantics [dcl.attr.grammar]") or with different [*attribute-argument-clause*](dcl.attr.grammar#nt:attribute-argument-clause "9.13.1 Attribute 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.9 Nodiscard 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.9 Nodiscard attribute [dcl.attr.nodiscard]") is either
|
||||
|
||||
- [(3.1)](#3.1)
|
||||
|
||||
a function call expression ([[expr.call]](expr.call "7.6.1.3 Function 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.4 Explicit type conversion (functional notation)"), [[expr.static.cast]](expr.static.cast "7.6.1.9 Static cast"), [[expr.cast]](expr.cast "7.6.3 Explicit 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.2 Properties 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.2 Conditional 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.6 Unevaluated strings [lex.string.uneval]") in a nodiscard [*attribute-argument-clause*](dcl.attr.grammar#nt:attribute-argument-clause "9.13.1 Attribute 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*]
|
||||
55
cppdraft/dcl/attr/noreturn.md
Normal file
55
cppdraft/dcl/attr/noreturn.md
Normal 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.1 Attribute 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.1 Attribute 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.2 Conditional 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*]
|
||||
45
cppdraft/dcl/attr/nouniqueaddr.md
Normal file
45
cppdraft/dcl/attr/nouniqueaddr.md
Normal 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.1 Attribute 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.2 Object model"))[.](#1.sentence-1)
|
||||
|
||||
No [*attribute-argument-clause*](dcl.attr.grammar#nt:attribute-argument-clause "9.13.1 Attribute 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.2 Conditional 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*]
|
||||
73
cppdraft/dcl/attr/unused.md
Normal file
73
cppdraft/dcl/attr/unused.md
Normal 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.1 Attribute 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.1 Attribute 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.2 Referring to the result object")),
|
||||
non-static data member,
|
||||
function,
|
||||
enumeration, or
|
||||
enumerator, or
|
||||
to an [*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]") label ([[stmt.label]](stmt.label "8.2 Label"))[.](#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.2 Conditional 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
136
cppdraft/dcl/constexpr.md
Normal 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.8 The inline specifier"))[.](#1.sentence-3)
|
||||
|
||||
If any declaration of a function or function template has
|
||||
a constexpr or consteval specifier,
|
||||
then all its declarations shall contain the same specifier[.](#1.sentence-4)
|
||||
|
||||
[*Note [1](#note-1)*:
|
||||
|
||||
An explicit specialization can differ from the template declaration
|
||||
with respect to the constexpr or consteval specifier[.](#1.sentence-5)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[*Note [2](#note-2)*:
|
||||
|
||||
Function parameters cannot be declared constexpr[.](#1.sentence-6)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[*Example [1](#example-1)*: constexpr void square(int &x); // OK, declarationconstexpr int bufsz = 1024; // OK, definitionconstexpr struct pixel { // error: pixel is a typeint x; int y; constexpr pixel(int); // OK, declaration};constexpr pixel::pixel(int a): x(a), y(x) // OK, definition{ square(x); }constexpr pixel small(2); // error: square not defined, so small(2)// not constant ([[expr.const]](expr.const "7.7 Constant expressions")) so constexpr not satisfiedconstexpr void square(int &x) { // OK, definition x *= x;}constexpr pixel large(4); // OK, square definedint next(constexpr int x) { // error: not for parametersreturn x + 1;}extern constexpr int memsz; // error: not a definition â *end example*]
|
||||
|
||||
[2](#2)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L934)
|
||||
|
||||
A constexpr or consteval specifier
|
||||
used in the declaration of a function
|
||||
declares that function to be
|
||||
a [*constexpr function*](#def:specifier,constexpr,function "9.2.6 The constexpr and consteval specifiers [dcl.constexpr]")[.](#2.sentence-1)
|
||||
|
||||
[*Note [3](#note-3)*:
|
||||
|
||||
A function or constructor declared with the consteval specifier
|
||||
is an immediate function ([[expr.const]](expr.const "7.7 Constant expressions"))[.](#2.sentence-2)
|
||||
|
||||
â *end note*]
|
||||
|
||||
A destructor, an allocation function, or a deallocation function
|
||||
shall not be declared with the consteval specifier[.](#2.sentence-3)
|
||||
|
||||
[3](#3)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L946)
|
||||
|
||||
A function is [*constexpr-suitable*](#def:constexpr-suitable "9.2.6 The constexpr and consteval specifiers [dcl.constexpr]") if
|
||||
it is not a coroutine ([[dcl.fct.def.coroutine]](dcl.fct.def.coroutine "9.6.4 Coroutine definitions"))[.](#3.sentence-1)
|
||||
|
||||
Except for instantiated constexpr functions,
|
||||
non-templated constexpr functions shall be constexpr-suitable[.](#3.sentence-2)
|
||||
|
||||
[*Example [2](#example-2)*: constexpr int square(int x){ return x * x; } // OKconstexpr long long_max(){ return 2147483647; } // OKconstexpr int abs(int x) {if (x < 0) x = -x; return x; // OK}constexpr int constant_non_42(int n) { // OKif (n == 42) {static int value = n; return value; }return n;}constexpr int uninit() {struct { int a; } s; return s.a; // error: uninitialized read of s.a}constexpr int prev(int x){ return --x; } // OKconstexpr int g(int x, int n) { // OKint r = 1; while (--n > 0) r *= x; return r;} â *end example*]
|
||||
|
||||
[4](#4)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L987)
|
||||
|
||||
An invocation of a constexpr function in a given context
|
||||
produces the same result as
|
||||
an invocation of an equivalent non-constexpr function in the same context
|
||||
in all respects except that
|
||||
|
||||
- [(4.1)](#4.1)
|
||||
|
||||
an invocation of a constexpr function
|
||||
can appear in a constant expression ([[expr.const]](expr.const "7.7 Constant expressions")) and
|
||||
|
||||
- [(4.2)](#4.2)
|
||||
|
||||
copy elision is not performed in a constant expression ([[class.copy.elision]](class.copy.elision "11.9.6 Copy/move elision"))[.](#4.sentence-1)
|
||||
|
||||
[*Note [4](#note-4)*:
|
||||
|
||||
Declaring a function constexpr can change whether an expression
|
||||
is a constant expression[.](#4.sentence-2)
|
||||
|
||||
This can indirectly cause calls to std::is_constant_evaluated within an invocation of the function to produce a different value[.](#4.sentence-3)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[*Note [5](#note-5)*:
|
||||
|
||||
It is possible to write a constexpr function for which
|
||||
no invocation satisfies the requirements of a core constant expression[.](#4.sentence-4)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[5](#5)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L1010)
|
||||
|
||||
The constexpr and consteval specifiers have no
|
||||
effect on the type of a constexpr function[.](#5.sentence-1)
|
||||
|
||||
[*Example [3](#example-3)*: constexpr int bar(int x, int y) // OK{ return x + y + x*y; }// ...int bar(int x, int y) // error: redefinition of bar{ return x * 2 + 3 * y; } â *end example*]
|
||||
|
||||
[6](#6)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L1023)
|
||||
|
||||
A constexpr specifier used in an object declaration
|
||||
declares the object as const[.](#6.sentence-1)
|
||||
|
||||
Such an object
|
||||
shall have literal type and
|
||||
shall be initialized[.](#6.sentence-2)
|
||||
|
||||
A constexpr variable shall be constant-initializable ([[expr.const]](expr.const "7.7 Constant expressions"))[.](#6.sentence-3)
|
||||
|
||||
A constexpr variable that is an object,
|
||||
as well as any temporary to which a constexpr reference is bound,
|
||||
shall have constant destruction[.](#6.sentence-4)
|
||||
|
||||
[*Example [4](#example-4)*: struct pixel {int x, y;};constexpr pixel ur = { 1294, 1024 }; // OKconstexpr pixel origin; // error: initializer missingnamespace N {void f() {int x; constexpr int& ar = x; // OKstatic constexpr int& sr = x; // error: x is not constexpr-representable// at the point indicated below}// immediate scope here is that of N} â *end example*]
|
||||
50
cppdraft/dcl/constinit.md
Normal file
50
cppdraft/dcl/constinit.md
Normal 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.7 Structured 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.3 Dynamic 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.2 Static 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
266
cppdraft/dcl/contract.md
Normal 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.1 General [dcl.contract.func]")
|
||||
[*function-contract-specifier*](#nt:function-contract-specifier "9.4.1 General [dcl.contract.func]") [*function-contract-specifier-seq*](#nt:function-contract-specifier-seq "9.4.1 General [dcl.contract.func]")opt
|
||||
|
||||
[function-contract-specifier:](#nt:function-contract-specifier "9.4.1 General [dcl.contract.func]")
|
||||
[*precondition-specifier*](#nt:precondition-specifier "9.4.1 General [dcl.contract.func]")
|
||||
[*postcondition-specifier*](#nt:postcondition-specifier "9.4.1 General [dcl.contract.func]")
|
||||
|
||||
[precondition-specifier:](#nt:precondition-specifier "9.4.1 General [dcl.contract.func]")
|
||||
pre [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]")opt ( [*conditional-expression*](expr.cond#nt:conditional-expression "7.6.16 Conditional operator [expr.cond]") )
|
||||
|
||||
[postcondition-specifier:](#nt:postcondition-specifier "9.4.1 General [dcl.contract.func]")
|
||||
post [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]")opt ( [*result-name-introducer*](#nt:result-name-introducer "9.4.2 Referring to the result object [dcl.contract.res]")opt [*conditional-expression*](expr.cond#nt:conditional-expression "7.6.16 Conditional 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.1 General [dcl.contract.func]") is a contract assertion ([[basic.contract.general]](basic.contract.general "6.11.1 General"))
|
||||
associated with a function[.](#func-1.sentence-1)
|
||||
|
||||
A [*precondition-specifier*](#nt:precondition-specifier "9.4.1 General [dcl.contract.func]") introduces a [*precondition assertion*](#def:assertion,precondition "9.4.1 General [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.1 General [dcl.contract.func]") introduces a [*postcondition assertion*](#def:assertion,postcondition "9.4.1 General [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.18 Throwing an exception"))
|
||||
or via a call to longjmp ([[csetjmp.syn]](csetjmp.syn "17.14.3 Header <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.1 General"))
|
||||
of a function contract assertion
|
||||
is its [*conditional-expression*](expr.cond#nt:conditional-expression "7.6.16 Conditional 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.1 General [dcl.contract.func]") of a [*function-contract-specifier-seq*](#nt:function-contract-specifier-seq "9.4.1 General [dcl.contract.func]") (if any)
|
||||
of an unspecified first declaration ([[basic.def]](basic.def "6.2 Declarations 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.1 Attribute 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.1 General [dcl.contract.func]") of a [*lambda-declarator*](expr.prim.lambda.general#nt:lambda-declarator "7.5.6.1 General [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.2 Closure 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.1 General [dcl.contract.func]") or the same [*function-contract-specifier-seq*](#nt:function-contract-specifier-seq "9.4.1 General [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.1 General [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.1 General [dcl.contract.func]") S1 is the same as
|
||||
a [*function-contract-specifier-seq*](#nt:function-contract-specifier-seq "9.4.1 General [dcl.contract.func]") S2 if S1 and S2 consist of
|
||||
the same [*function-contract-specifier*](#nt:function-contract-specifier "9.4.1 General [dcl.contract.func]")*s* in the same order[.](#func-5.sentence-1)
|
||||
|
||||
A [*function-contract-specifier*](#nt:function-contract-specifier "9.4.1 General [dcl.contract.func]") C1 on a function declaration D1 is
|
||||
the same as
|
||||
a [*function-contract-specifier*](#nt:function-contract-specifier "9.4.1 General [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.3 One-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.2 Referring 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.2 Referring 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.1 General [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.1 General [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.1 General [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.1 General [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.2 Referring 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.1 General [dcl.contract.func]")*s* differ according to// the one-definition rule ([[basic.def.odr]](basic.def.odr "6.3 One-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.3 Virtual functions")),
|
||||
a deleted function ([[dcl.fct.def.delete]](dcl.fct.def.delete "9.6.3 Deleted definitions")),
|
||||
or a function defaulted on its first declaration ([[dcl.fct.def.default]](dcl.fct.def.default "9.6.2 Explicitly-defaulted functions"))
|
||||
shall not have a [*function-contract-specifier-seq*](#nt:function-contract-specifier-seq "9.4.1 General [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.3 One-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.1 General [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.1 General [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.1 General [dcl.contract.func]") ([[temp.inst]](temp.inst "13.9.2 Implicit instantiation")) when
|
||||
|
||||
- [(9.1)](#func-9.1)
|
||||
|
||||
the function is odr-used ([[basic.def.odr]](basic.def.odr "6.3 One-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.1 General [dcl.contract.func]")*s* ([[temp.deduct]](temp.deduct "13.10.3 Template argument deduction"), [[temp.inst]](temp.inst "13.9.2 Implicit 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.2 Referring to the result object [dcl.contract.res]")
|
||||
[*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]") [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]")opt
|
||||
|
||||
[result-name-introducer:](#nt:result-name-introducer "9.4.2 Referring to the result object [dcl.contract.res]")
|
||||
[*attributed-identifier*](#nt:attributed-identifier "9.4.2 Referring 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.2 Referring to the result object [dcl.contract.res]") of a [*postcondition-specifier*](#nt:postcondition-specifier "9.4.1 General [dcl.contract.func]") is a declaration[.](#res-1.sentence-1)
|
||||
|
||||
The [*result-name-introducer*](#nt:result-name-introducer "9.4.2 Referring to the result object [dcl.contract.res]") introduces the [*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]") as the name of a [*result binding*](#def:result_binding "9.4.2 Referring 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.2 Referring 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.1 Attribute syntax and semantics [dcl.attr.grammar]") of the [*attributed-identifier*](#nt:attributed-identifier "9.4.2 Referring to the result object [dcl.contract.res]") in the [*result-name-introducer*](#nt:result-name-introducer "9.4.2 Referring 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.1 General [expr.prim.id.general]") that names a result binding is a const lvalue ([[expr.prim.id.unqual]](expr.prim.id.unqual "7.5.5.2 Unqualified 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.7 Temporary 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.1 General [dcl.contract.func]") with a [*result-name-introducer*](#nt:result-name-introducer "9.4.2 Referring 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*]
|
||||
215
cppdraft/dcl/contract/func.md
Normal file
215
cppdraft/dcl/contract/func.md
Normal 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.1 General [dcl.contract.func]")
|
||||
[*function-contract-specifier*](#nt:function-contract-specifier "9.4.1 General [dcl.contract.func]") [*function-contract-specifier-seq*](#nt:function-contract-specifier-seq "9.4.1 General [dcl.contract.func]")opt
|
||||
|
||||
[function-contract-specifier:](#nt:function-contract-specifier "9.4.1 General [dcl.contract.func]")
|
||||
[*precondition-specifier*](#nt:precondition-specifier "9.4.1 General [dcl.contract.func]")
|
||||
[*postcondition-specifier*](#nt:postcondition-specifier "9.4.1 General [dcl.contract.func]")
|
||||
|
||||
[precondition-specifier:](#nt:precondition-specifier "9.4.1 General [dcl.contract.func]")
|
||||
pre [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]")opt ( [*conditional-expression*](expr.cond#nt:conditional-expression "7.6.16 Conditional operator [expr.cond]") )
|
||||
|
||||
[postcondition-specifier:](#nt:postcondition-specifier "9.4.1 General [dcl.contract.func]")
|
||||
post [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]")opt ( [*result-name-introducer*](dcl.contract.res#nt:result-name-introducer "9.4.2 Referring to the result object [dcl.contract.res]")opt [*conditional-expression*](expr.cond#nt:conditional-expression "7.6.16 Conditional 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.1 General [dcl.contract.func]") is a contract assertion ([[basic.contract.general]](basic.contract.general "6.11.1 General"))
|
||||
associated with a function[.](#1.sentence-1)
|
||||
|
||||
A [*precondition-specifier*](#nt:precondition-specifier "9.4.1 General [dcl.contract.func]") introduces a [*precondition assertion*](#def:assertion,precondition "9.4.1 General [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.1 General [dcl.contract.func]") introduces a [*postcondition assertion*](#def:assertion,postcondition "9.4.1 General [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.18 Throwing an exception"))
|
||||
or via a call to longjmp ([[csetjmp.syn]](csetjmp.syn "17.14.3 Header <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.1 General"))
|
||||
of a function contract assertion
|
||||
is its [*conditional-expression*](expr.cond#nt:conditional-expression "7.6.16 Conditional 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.1 General [dcl.contract.func]") of a [*function-contract-specifier-seq*](#nt:function-contract-specifier-seq "9.4.1 General [dcl.contract.func]") (if any)
|
||||
of an unspecified first declaration ([[basic.def]](basic.def "6.2 Declarations 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.1 Attribute 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.1 General [dcl.contract.func]") of a [*lambda-declarator*](expr.prim.lambda.general#nt:lambda-declarator "7.5.6.1 General [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.2 Closure 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.1 General [dcl.contract.func]") or the same [*function-contract-specifier-seq*](#nt:function-contract-specifier-seq "9.4.1 General [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.1 General [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.1 General [dcl.contract.func]") S1 is the same as
|
||||
a [*function-contract-specifier-seq*](#nt:function-contract-specifier-seq "9.4.1 General [dcl.contract.func]") S2 if S1 and S2 consist of
|
||||
the same [*function-contract-specifier*](#nt:function-contract-specifier "9.4.1 General [dcl.contract.func]")*s* in the same order[.](#5.sentence-1)
|
||||
|
||||
A [*function-contract-specifier*](#nt:function-contract-specifier "9.4.1 General [dcl.contract.func]") C1 on a function declaration D1 is
|
||||
the same as
|
||||
a [*function-contract-specifier*](#nt:function-contract-specifier "9.4.1 General [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.3 One-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.2 Referring 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.2 Referring 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.1 General [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.1 General [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.1 General [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.1 General [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.2 Referring 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.1 General [dcl.contract.func]")*s* differ according to// the one-definition rule ([[basic.def.odr]](basic.def.odr "6.3 One-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.3 Virtual functions")),
|
||||
a deleted function ([[dcl.fct.def.delete]](dcl.fct.def.delete "9.6.3 Deleted definitions")),
|
||||
or a function defaulted on its first declaration ([[dcl.fct.def.default]](dcl.fct.def.default "9.6.2 Explicitly-defaulted functions"))
|
||||
shall not have a [*function-contract-specifier-seq*](#nt:function-contract-specifier-seq "9.4.1 General [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.3 One-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.1 General [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.1 General [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.1 General [dcl.contract.func]") ([[temp.inst]](temp.inst "13.9.2 Implicit instantiation")) when
|
||||
|
||||
- [(9.1)](#9.1)
|
||||
|
||||
the function is odr-used ([[basic.def.odr]](basic.def.odr "6.3 One-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.1 General [dcl.contract.func]")*s* ([[temp.deduct]](temp.deduct "13.10.3 Template argument deduction"), [[temp.inst]](temp.inst "13.9.2 Implicit 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*]
|
||||
56
cppdraft/dcl/contract/res.md
Normal file
56
cppdraft/dcl/contract/res.md
Normal 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.2 Referring to the result object [dcl.contract.res]")
|
||||
[*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]") [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]")opt
|
||||
|
||||
[result-name-introducer:](#nt:result-name-introducer "9.4.2 Referring to the result object [dcl.contract.res]")
|
||||
[*attributed-identifier*](#nt:attributed-identifier "9.4.2 Referring 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.2 Referring to the result object [dcl.contract.res]") of a [*postcondition-specifier*](dcl.contract.func#nt:postcondition-specifier "9.4.1 General [dcl.contract.func]") is a declaration[.](#1.sentence-1)
|
||||
|
||||
The [*result-name-introducer*](#nt:result-name-introducer "9.4.2 Referring to the result object [dcl.contract.res]") introduces the [*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]") as the name of a [*result binding*](#def:result_binding "9.4.2 Referring 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.2 Referring 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.1 Attribute syntax and semantics [dcl.attr.grammar]") of the [*attributed-identifier*](#nt:attributed-identifier "9.4.2 Referring to the result object [dcl.contract.res]") in the [*result-name-introducer*](#nt:result-name-introducer "9.4.2 Referring 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.1 General [expr.prim.id.general]") that names a result binding is a const lvalue ([[expr.prim.id.unqual]](expr.prim.id.unqual "7.5.5.2 Unqualified 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.7 Temporary 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.1 General [dcl.contract.func]") with a [*result-name-introducer*](#nt:result-name-introducer "9.4.2 Referring 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
1803
cppdraft/dcl/decl.md
Normal file
File diff suppressed because it is too large
Load Diff
143
cppdraft/dcl/decl/general.md
Normal file
143
cppdraft/dcl/decl/general.md
Normal 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.1 General [dcl.decl.general]") appearing in a [*simple-declaration*](dcl.pre#nt:simple-declaration "9.1 Preamble [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.1 General [dcl.decl.general]")
|
||||
[*init-declarator*](#nt:init-declarator "9.3.1 General [dcl.decl.general]")
|
||||
[*init-declarator-list*](#nt:init-declarator-list "9.3.1 General [dcl.decl.general]") , [*init-declarator*](#nt:init-declarator "9.3.1 General [dcl.decl.general]")
|
||||
|
||||
[init-declarator:](#nt:init-declarator "9.3.1 General [dcl.decl.general]")
|
||||
[*declarator*](#nt:declarator "9.3.1 General [dcl.decl.general]") [*initializer*](dcl.init.general#nt:initializer "9.5.1 General [dcl.init.general]")
|
||||
[*declarator*](#nt:declarator "9.3.1 General [dcl.decl.general]") [*requires-clause*](temp.pre#nt:requires-clause "13.1 Preamble [temp.pre]")opt [*function-contract-specifier-seq*](dcl.contract.func#nt:function-contract-specifier-seq "9.4.1 General [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.1 General [dcl.decl.general]") is interpreted as given below[.](#2.sentence-1)
|
||||
|
||||
Where an [*abstract-declarator*](dcl.name#nt:abstract-declarator "9.3.2 Type names [dcl.name]") can be used (or omitted)
|
||||
in place of a [*declarator*](#nt:declarator "9.3.1 General [dcl.decl.general]") ([[dcl.fct]](dcl.fct "9.3.4.6 Functions"), [[except.pre]](except.pre "14.1 Preamble")),
|
||||
it is as if a unique identifier were included in
|
||||
the appropriate place ([[dcl.name]](dcl.name "9.3.2 Type 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.1 General [dcl.decl.general]") can also specify an initializer ([[dcl.init]](dcl.init "9.5 Initializers"))[.](#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.1 General [dcl.decl.general]") or [*member-declarator*](class.mem.general#nt:member-declarator "11.4.1 General [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.1 General [dcl.spec.general]") and each Di is
|
||||
an [*init-declarator*](#nt:init-declarator "9.3.1 General [dcl.decl.general]") or [*member-declarator*](class.mem.general#nt:member-declarator "11.4.1 General [class.mem.general]")[.](#3.sentence-3)
|
||||
|
||||
One exception is when a name introduced by one of the[*declarator*](#nt:declarator "9.3.1 General [dcl.decl.general]")*s* hides a type name used by the[*decl-specifier*](dcl.spec.general#nt:decl-specifier "9.2.1 General [dcl.spec.general]")*s*, so that when the same[*decl-specifier*](dcl.spec.general#nt:decl-specifier "9.2.1 General [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.7 Placeholder 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.1 Preamble [temp.pre]") in an[*init-declarator*](#nt:init-declarator "9.3.1 General [dcl.decl.general]") or [*member-declarator*](class.mem.general#nt:member-declarator "11.4.1 General [class.mem.general]") shall be present only if the declarator declares a
|
||||
templated function ([[temp.pre]](temp.pre "13.1 Preamble"))[.](#4.sentence-1)
|
||||
|
||||
When present after a declarator, the [*requires-clause*](temp.pre#nt:requires-clause "13.1 Preamble [temp.pre]") is called the [*trailing* ](#def:requires-clause,trailing "9.3.1 General [dcl.decl.general]")*[*requires-clause*](temp.pre#nt:requires-clause "13.1 Preamble [temp.pre]")*[.](#4.sentence-2)
|
||||
|
||||
The trailing [*requires-clause*](temp.pre#nt:requires-clause "13.1 Preamble [temp.pre]") introduces the[*constraint-expression*](temp.constr.decl#nt:constraint-expression "13.5.3 Constrained declarations [temp.constr.decl]") that results from interpreting
|
||||
its [*constraint-logical-or-expression*](temp.pre#nt:constraint-logical-or-expression "13.1 Preamble [temp.pre]") as a[*constraint-expression*](temp.constr.decl#nt:constraint-expression "13.5.3 Constrained 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.1 Preamble [temp.pre]") precedes [*trailing-return-type*](#nt:trailing-return-type "9.3.1 General [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.6 Functions [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.1 General [dcl.contract.func]") ([[dcl.contract.func]](dcl.contract.func "9.4.1 General"))
|
||||
in an [*init-declarator*](#nt:init-declarator "9.3.1 General [dcl.decl.general]") shall be present only if
|
||||
the [*declarator*](#nt:declarator "9.3.1 General [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.1 General [dcl.decl.general]")
|
||||
[*ptr-declarator*](#nt:ptr-declarator "9.3.1 General [dcl.decl.general]")
|
||||
[*noptr-declarator*](#nt:noptr-declarator "9.3.1 General [dcl.decl.general]") [*parameters-and-qualifiers*](#nt:parameters-and-qualifiers "9.3.1 General [dcl.decl.general]") [*trailing-return-type*](#nt:trailing-return-type "9.3.1 General [dcl.decl.general]")
|
||||
|
||||
[ptr-declarator:](#nt:ptr-declarator "9.3.1 General [dcl.decl.general]")
|
||||
[*noptr-declarator*](#nt:noptr-declarator "9.3.1 General [dcl.decl.general]")
|
||||
[*ptr-operator*](#nt:ptr-operator "9.3.1 General [dcl.decl.general]") [*ptr-declarator*](#nt:ptr-declarator "9.3.1 General [dcl.decl.general]")
|
||||
|
||||
[noptr-declarator:](#nt:noptr-declarator "9.3.1 General [dcl.decl.general]")
|
||||
[*declarator-id*](#nt:declarator-id "9.3.1 General [dcl.decl.general]") [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]")opt
|
||||
[*noptr-declarator*](#nt:noptr-declarator "9.3.1 General [dcl.decl.general]") [*parameters-and-qualifiers*](#nt:parameters-and-qualifiers "9.3.1 General [dcl.decl.general]")
|
||||
[*noptr-declarator*](#nt:noptr-declarator "9.3.1 General [dcl.decl.general]") [ [*constant-expression*](expr.const#nt:constant-expression "7.7 Constant expressions [expr.const]")opt ] [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]")opt
|
||||
( [*ptr-declarator*](#nt:ptr-declarator "9.3.1 General [dcl.decl.general]") )
|
||||
|
||||
[parameters-and-qualifiers:](#nt:parameters-and-qualifiers "9.3.1 General [dcl.decl.general]")
|
||||
( [*parameter-declaration-clause*](dcl.fct#nt:parameter-declaration-clause "9.3.4.6 Functions [dcl.fct]") ) [*cv-qualifier-seq*](#nt:cv-qualifier-seq "9.3.1 General [dcl.decl.general]")opt
|
||||
[*ref-qualifier*](#nt:ref-qualifier "9.3.1 General [dcl.decl.general]")opt [*noexcept-specifier*](except.spec#nt:noexcept-specifier "14.5 Exception specifications [except.spec]")opt [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]")opt
|
||||
|
||||
[trailing-return-type:](#nt:trailing-return-type "9.3.1 General [dcl.decl.general]")
|
||||
-> [*type-id*](dcl.name#nt:type-id "9.3.2 Type names [dcl.name]")
|
||||
|
||||
[ptr-operator:](#nt:ptr-operator "9.3.1 General [dcl.decl.general]")
|
||||
* [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]")opt [*cv-qualifier-seq*](#nt:cv-qualifier-seq "9.3.1 General [dcl.decl.general]")opt
|
||||
& [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]")opt
|
||||
&& [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]")opt
|
||||
[*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3 Qualified names [expr.prim.id.qual]") * [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]")opt [*cv-qualifier-seq*](#nt:cv-qualifier-seq "9.3.1 General [dcl.decl.general]")opt
|
||||
|
||||
[cv-qualifier-seq:](#nt:cv-qualifier-seq "9.3.1 General [dcl.decl.general]")
|
||||
[*cv-qualifier*](#nt:cv-qualifier "9.3.1 General [dcl.decl.general]") [*cv-qualifier-seq*](#nt:cv-qualifier-seq "9.3.1 General [dcl.decl.general]")opt
|
||||
|
||||
[cv-qualifier:](#nt:cv-qualifier "9.3.1 General [dcl.decl.general]")
|
||||
const
|
||||
volatile
|
||||
|
||||
[ref-qualifier:](#nt:ref-qualifier "9.3.1 General [dcl.decl.general]")
|
||||
&
|
||||
&&
|
||||
|
||||
[declarator-id:](#nt:declarator-id "9.3.1 General [dcl.decl.general]")
|
||||
...opt [*id-expression*](expr.prim.id.general#nt:id-expression "7.5.5.1 General [expr.prim.id.general]")
|
||||
336
cppdraft/dcl/enum.md
Normal file
336
cppdraft/dcl/enum.md
Normal 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.4 Compound types")) with named
|
||||
constants[.](#1.sentence-1)
|
||||
|
||||
Its name becomes an [*enum-name*](#nt:enum-name "9.8.1 Enumeration declarations [dcl.enum]") within its scope[.](#1.sentence-2)
|
||||
|
||||
[enum-name:](#nt:enum-name "9.8.1 Enumeration declarations [dcl.enum]")
|
||||
[*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]")
|
||||
|
||||
[enum-specifier:](#nt:enum-specifier "9.8.1 Enumeration declarations [dcl.enum]")
|
||||
[*enum-head*](#nt:enum-head "9.8.1 Enumeration declarations [dcl.enum]") { [*enumerator-list*](#nt:enumerator-list "9.8.1 Enumeration declarations [dcl.enum]")opt }
|
||||
[*enum-head*](#nt:enum-head "9.8.1 Enumeration declarations [dcl.enum]") { [*enumerator-list*](#nt:enumerator-list "9.8.1 Enumeration declarations [dcl.enum]") , }
|
||||
|
||||
[enum-head:](#nt:enum-head "9.8.1 Enumeration declarations [dcl.enum]")
|
||||
[*enum-key*](#nt:enum-key "9.8.1 Enumeration declarations [dcl.enum]") [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]")opt [*enum-head-name*](#nt:enum-head-name "9.8.1 Enumeration declarations [dcl.enum]")opt [*enum-base*](#nt:enum-base "9.8.1 Enumeration declarations [dcl.enum]")opt
|
||||
|
||||
[enum-head-name:](#nt:enum-head-name "9.8.1 Enumeration declarations [dcl.enum]")
|
||||
[*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3 Qualified names [expr.prim.id.qual]")opt [*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]")
|
||||
|
||||
[opaque-enum-declaration:](#nt:opaque-enum-declaration "9.8.1 Enumeration declarations [dcl.enum]")
|
||||
[*enum-key*](#nt:enum-key "9.8.1 Enumeration declarations [dcl.enum]") [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]")opt [*enum-head-name*](#nt:enum-head-name "9.8.1 Enumeration declarations [dcl.enum]") [*enum-base*](#nt:enum-base "9.8.1 Enumeration declarations [dcl.enum]")opt ;
|
||||
|
||||
[enum-key:](#nt:enum-key "9.8.1 Enumeration declarations [dcl.enum]")
|
||||
enum
|
||||
enum class
|
||||
enum struct
|
||||
|
||||
[enum-base:](#nt:enum-base "9.8.1 Enumeration declarations [dcl.enum]")
|
||||
: [*type-specifier-seq*](dcl.type.general#nt:type-specifier-seq "9.2.9.1 General [dcl.type.general]")
|
||||
|
||||
[enumerator-list:](#nt:enumerator-list "9.8.1 Enumeration declarations [dcl.enum]")
|
||||
[*enumerator-definition*](#nt:enumerator-definition "9.8.1 Enumeration declarations [dcl.enum]")
|
||||
[*enumerator-list*](#nt:enumerator-list "9.8.1 Enumeration declarations [dcl.enum]") , [*enumerator-definition*](#nt:enumerator-definition "9.8.1 Enumeration declarations [dcl.enum]")
|
||||
|
||||
[enumerator-definition:](#nt:enumerator-definition "9.8.1 Enumeration declarations [dcl.enum]")
|
||||
[*enumerator*](#nt:enumerator "9.8.1 Enumeration declarations [dcl.enum]")
|
||||
[*enumerator*](#nt:enumerator "9.8.1 Enumeration declarations [dcl.enum]") = [*constant-expression*](expr.const#nt:constant-expression "7.7 Constant expressions [expr.const]")
|
||||
|
||||
[enumerator:](#nt:enumerator "9.8.1 Enumeration declarations [dcl.enum]")
|
||||
[*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]") [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]")opt
|
||||
|
||||
The optional [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]") in the [*enum-head*](#nt:enum-head "9.8.1 Enumeration declarations [dcl.enum]") and
|
||||
the [*opaque-enum-declaration*](#nt:opaque-enum-declaration "9.8.1 Enumeration declarations [dcl.enum]") appertains to the enumeration; the attributes
|
||||
in that [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1 Attribute 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.3 Qualified names [expr.prim.id.qual]")opt [*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]")â
|
||||
within the [*decl-specifier-seq*](dcl.spec.general#nt:decl-specifier-seq "9.2.1 General [dcl.spec.general]") of a [*member-declaration*](class.mem.general#nt:member-declaration "11.4.1 General [class.mem.general]") is parsed as part of an [*enum-base*](#nt:enum-base "9.8.1 Enumeration 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.1 Enumeration 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.11 Identifiers [lex.name]") in an [*enum-head-name*](#nt:enum-head-name "9.8.1 Enumeration declarations [dcl.enum]") is not looked up and is introduced by
|
||||
the [*enum-specifier*](#nt:enum-specifier "9.8.1 Enumeration declarations [dcl.enum]") or [*opaque-enum-declaration*](#nt:opaque-enum-declaration "9.8.1 Enumeration declarations [dcl.enum]")[.](#1.sentence-6)
|
||||
|
||||
If the [*enum-head-name*](#nt:enum-head-name "9.8.1 Enumeration declarations [dcl.enum]") of an [*opaque-enum-declaration*](#nt:opaque-enum-declaration "9.8.1 Enumeration declarations [dcl.enum]") contains
|
||||
a [*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3 Qualified names [expr.prim.id.qual]"),
|
||||
the declaration shall be an [explicit specialization](temp.expl.spec "13.9.4 Explicit 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.1 Enumeration declarations [dcl.enum]") of only enum is an [*unscoped enumeration*](#def:enumeration,unscoped "9.8.1 Enumeration declarations [dcl.enum]"),
|
||||
and its [*enumerator*](#nt:enumerator "9.8.1 Enumeration declarations [dcl.enum]")*s* are [*unscoped enumerators*](#def:enumerator,unscoped "9.8.1 Enumeration declarations [dcl.enum]")[.](#2.sentence-1)
|
||||
|
||||
The [*enum-key*](#nt:enum-key "9.8.1 Enumeration 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.1 Enumeration declarations [dcl.enum]"),
|
||||
and its [*enumerator*](#nt:enumerator "9.8.1 Enumeration declarations [dcl.enum]")*s* are [*scoped enumerators*](#def:enumerator,scoped "9.8.1 Enumeration declarations [dcl.enum]")[.](#2.sentence-2)
|
||||
|
||||
The optional [*enum-head-name*](#nt:enum-head-name "9.8.1 Enumeration 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.1 General [dcl.type.general]") of an [*enum-base*](#nt:enum-base "9.8.1 Enumeration 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.1 Enumeration declarations [dcl.enum]") declaring an unscoped enumeration shall
|
||||
not omit the [*enum-base*](#nt:enum-base "9.8.1 Enumeration declarations [dcl.enum]")[.](#2.sentence-5)
|
||||
|
||||
The identifiers in an [*enumerator-list*](#nt:enumerator-list "9.8.1 Enumeration 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.1 Enumeration declarations [dcl.enum]")[.](#2.sentence-7)
|
||||
|
||||
An [*enumerator-definition*](#nt:enumerator-definition "9.8.1 Enumeration declarations [dcl.enum]") with = gives the associated[*enumerator*](#nt:enumerator "9.8.1 Enumeration declarations [dcl.enum]") the value indicated by the[*constant-expression*](expr.const#nt:constant-expression "7.7 Constant expressions [expr.const]")[.](#2.sentence-8)
|
||||
|
||||
An [*enumerator-definition*](#nt:enumerator-definition "9.8.1 Enumeration declarations [dcl.enum]") without = gives the associated[*enumerator*](#nt:enumerator "9.8.1 Enumeration declarations [dcl.enum]") the value zero
|
||||
if it is the first [*enumerator-definition*](#nt:enumerator-definition "9.8.1 Enumeration declarations [dcl.enum]"),
|
||||
and the value of the previous [*enumerator*](#nt:enumerator "9.8.1 Enumeration 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.1 Attribute syntax and semantics [dcl.attr.grammar]") in an[*enumerator*](#nt:enumerator "9.8.1 Enumeration 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.1 Enumeration 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.1 Enumeration 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.1 Enumeration 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.1 Enumeration 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.1 Enumeration declarations [dcl.enum]") contains a[*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3 Qualified names [expr.prim.id.qual]"),
|
||||
the enclosing [*enum-specifier*](#nt:enum-specifier "9.8.1 Enumeration declarations [dcl.enum]") or [*opaque-enum-declaration*](#nt:opaque-enum-declaration "9.8.1 Enumeration 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.3 Qualified names [expr.prim.id.qual]") refers ([[basic.scope.scope]](basic.scope.scope "6.4.1 General"))[.](#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.1 Enumeration declarations [dcl.enum]")[.](#5.sentence-2)
|
||||
|
||||
The underlying type can be explicitly specified using an [*enum-base*](#nt:enum-base "9.8.1 Enumeration 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.1 Enumeration declarations [dcl.enum]")[.](#5.sentence-5)
|
||||
|
||||
Following the closing brace of an [*enum-specifier*](#nt:enum-specifier "9.8.1 Enumeration 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.7 Constant expressions [expr.const]") in the [*enumerator-definition*](#nt:enumerator-definition "9.8.1 Enumeration declarations [dcl.enum]") shall be a[converted constant expression](expr.const#def:expression,converted_constant "7.7 Constant 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.7 Constant expressions [expr.const]") shall be an[integral constant expression](expr.const#def:expression,integral_constant "7.7 Constant 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.1 Enumeration 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.1 Enumeration 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.1 Enumeration 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.1 Enumeration 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.3 Alignment"))
|
||||
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.1 Enumeration 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.7 Integral 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.1 Enumeration 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.4 The typedef specifier")) and
|
||||
that has a first enumerator
|
||||
is denoted, for linkage purposes ([[basic.link]](basic.link "6.7 Program 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
563
cppdraft/dcl/fct.md
Normal 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.6 Functions [dcl.fct]") ) [*cv-qualifier-seq*](dcl.decl.general#nt:cv-qualifier-seq "9.3.1 General [dcl.decl.general]")opt
|
||||
[*ref-qualifier*](dcl.decl.general#nt:ref-qualifier "9.3.1 General [dcl.decl.general]")opt [*noexcept-specifier*](except.spec#nt:noexcept-specifier "14.5 Exception specifications [except.spec]")opt [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]")opt [*trailing-return-type*](dcl.decl.general#nt:trailing-return-type "9.3.1 General [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.2 Unqualified names [expr.prim.id.unqual]") of the [*declarator-id*](dcl.decl.general#nt:declarator-id "9.3.1 General [dcl.decl.general]") is a [*conversion-function-id*](class.conv.fct#nt:conversion-function-id "11.4.8.3 Conversion 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.1 General [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.1 General [dcl.decl.general]") is present,T shall be the single [*type-specifier*](dcl.type.general#nt:type-specifier "9.2.9.1 General [dcl.type.general]") auto, andU is the type specified by the [*trailing-return-type*](dcl.decl.general#nt:trailing-return-type "9.3.1 General [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.3 Conversion 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.1 General [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.1 General [dcl.decl.general]")opt [*ref-qualifier*](dcl.decl.general#nt:ref-qualifier "9.3.1 General [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.6 Functions [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.5 Exception specifications")) is non-throwing[.](#1.sentence-3)
|
||||
|
||||
Such a type is a [*function type*](#def:type,function "9.3.4.6 Functions [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.1 Attribute 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.6 Functions [dcl.fct]")
|
||||
...
|
||||
[*parameter-declaration-list*](#nt:parameter-declaration-list "9.3.4.6 Functions [dcl.fct]")opt
|
||||
[*parameter-declaration-list*](#nt:parameter-declaration-list "9.3.4.6 Functions [dcl.fct]") , ...
|
||||
[*parameter-declaration-list*](#nt:parameter-declaration-list "9.3.4.6 Functions [dcl.fct]") ...
|
||||
|
||||
[parameter-declaration-list:](#nt:parameter-declaration-list "9.3.4.6 Functions [dcl.fct]")
|
||||
[*parameter-declaration*](#nt:parameter-declaration "9.3.4.6 Functions [dcl.fct]")
|
||||
[*parameter-declaration-list*](#nt:parameter-declaration-list "9.3.4.6 Functions [dcl.fct]") , [*parameter-declaration*](#nt:parameter-declaration "9.3.4.6 Functions [dcl.fct]")
|
||||
|
||||
[parameter-declaration:](#nt:parameter-declaration "9.3.4.6 Functions [dcl.fct]")
|
||||
[*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]")opt thisopt [*decl-specifier-seq*](dcl.spec.general#nt:decl-specifier-seq "9.2.1 General [dcl.spec.general]") [*declarator*](dcl.decl.general#nt:declarator "9.3.1 General [dcl.decl.general]")
|
||||
[*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]")opt [*decl-specifier-seq*](dcl.spec.general#nt:decl-specifier-seq "9.2.1 General [dcl.spec.general]") [*declarator*](dcl.decl.general#nt:declarator "9.3.1 General [dcl.decl.general]") = [*initializer-clause*](dcl.init.general#nt:initializer-clause "9.5.1 General [dcl.init.general]")
|
||||
[*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]")opt thisopt [*decl-specifier-seq*](dcl.spec.general#nt:decl-specifier-seq "9.2.1 General [dcl.spec.general]") [*abstract-declarator*](dcl.name#nt:abstract-declarator "9.3.2 Type names [dcl.name]")opt
|
||||
[*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]")opt [*decl-specifier-seq*](dcl.spec.general#nt:decl-specifier-seq "9.2.1 General [dcl.spec.general]") [*abstract-declarator*](dcl.name#nt:abstract-declarator "9.3.2 Type names [dcl.name]")opt = [*initializer-clause*](dcl.init.general#nt:initializer-clause "9.5.1 General [dcl.init.general]")
|
||||
|
||||
The optional [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]") in a [*parameter-declaration*](#nt:parameter-declaration "9.3.4.6 Functions [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.6 Functions [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.6 Functions [dcl.fct]") is used to convert the arguments specified on the function call;
|
||||
see [[expr.call]](expr.call "7.6.1.3 Function call")[.](#3.sentence-2)
|
||||
|
||||
â *end note*]
|
||||
|
||||
If the[*parameter-declaration-clause*](#nt:parameter-declaration-clause "9.3.4.6 Functions [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.4 Deprecated volatile types")[.](#3.sentence-6)
|
||||
|
||||
If the[*parameter-declaration-clause*](#nt:parameter-declaration-clause "9.3.4.6 Functions [dcl.fct]")terminates with an ellipsis or a function parameter
|
||||
pack ([[temp.variadic]](temp.variadic "13.7.4 Variadic 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.2 Type names [dcl.name]"),
|
||||
â...â
|
||||
is synonymous with
|
||||
â, ...â[.](#3.sentence-8)
|
||||
|
||||
A [*parameter-declaration-clause*](#nt:parameter-declaration-clause "9.3.4.6 Functions [dcl.fct]") of the form[*parameter-declaration-list*](#nt:parameter-declaration-list "9.3.4.6 Functions [dcl.fct]") ... is deprecated ([[depr.ellipsis.comma]](depr.ellipsis.comma "D.5 Non-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.2 Header <cstdarg> synopsis [cstdarg.syn]") contains a mechanism for accessing arguments passed using the ellipsis
|
||||
(see [[expr.call]](expr.call "7.6.1.3 Function call") and [[support.runtime]](support.runtime "17.14 Other 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.6 Functions [dcl.fct]") ([[dcl.decl]](dcl.decl "9.3 Declarators"))[.](#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.1 General [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.6 Functions [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.6 Functions [dcl.fct]") is
|
||||
a [*parameter-declaration*](#nt:parameter-declaration "9.3.4.6 Functions [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.6 Functions [dcl.fct]") of
|
||||
a [*parameter-declaration-list*](#nt:parameter-declaration-list "9.3.4.6 Functions [dcl.fct]") of one of:
|
||||
|
||||
- [(5.1)](#5.1)
|
||||
|
||||
a declaration of
|
||||
a member function or member function template ([[class.mem]](class.mem "11.4 Class members")), or
|
||||
|
||||
- [(5.2)](#5.2)
|
||||
|
||||
an explicit instantiation ([[temp.explicit]](temp.explicit "13.9.3 Explicit instantiation")) or
|
||||
explicit specialization ([[temp.expl.spec]](temp.expl.spec "13.9.4 Explicit specialization")) of
|
||||
a templated member function, or
|
||||
|
||||
- [(5.3)](#5.3)
|
||||
|
||||
a [*lambda-declarator*](expr.prim.lambda.general#nt:lambda-declarator "7.5.6.1 General [expr.prim.lambda.general]") ([[expr.prim.lambda]](expr.prim.lambda "7.5.6 Lambda expressions"))[.](#5.sentence-2)
|
||||
|
||||
A [*member-declarator*](class.mem.general#nt:member-declarator "11.4.1 General [class.mem.general]") with an explicit-object-parameter-declaration
|
||||
shall not include
|
||||
a [*ref-qualifier*](dcl.decl.general#nt:ref-qualifier "9.3.1 General [dcl.decl.general]") or a [*cv-qualifier-seq*](dcl.decl.general#nt:cv-qualifier-seq "9.3.1 General [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.6 Functions [dcl.fct]")[.](#6.sentence-1)
|
||||
|
||||
An explicit object parameter shall not be
|
||||
a function parameter pack ([[temp.variadic]](temp.variadic "13.7.4 Variadic templates"))[.](#6.sentence-2)
|
||||
|
||||
An [*explicit object member function*](#def:member_function,explicit_object "9.3.4.6 Functions [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.6 Functions [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.6 Functions [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.2 Candidate 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.6 Functions [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.6 Functions [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.1 General [dcl.decl.general]") or a[*ref-qualifier*](dcl.decl.general#nt:ref-qualifier "9.3.1 General [dcl.decl.general]") (including a type denoted by[*typedef-name*](dcl.typedef#nt:typedef-name "9.2.4 The typedef specifier [dcl.typedef]") ([[dcl.typedef]](dcl.typedef "9.2.4 The typedef specifier"), [[temp.param]](temp.param "13.2 Template 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.1 Preamble [dcl.pre]"),
|
||||
|
||||
- [(9.4)](#9.4)
|
||||
|
||||
the [*type-id*](dcl.name#nt:type-id "9.3.2 Type names [dcl.name]") in the default argument of a[*type-parameter*](temp.param#nt:type-parameter "13.2 Template parameters [temp.param]") ([[temp.param]](temp.param "13.2 Template parameters")),
|
||||
|
||||
- [(9.5)](#9.5)
|
||||
|
||||
the [*type-id*](dcl.name#nt:type-id "9.3.2 Type names [dcl.name]") of a [*template-argument*](temp.names#nt:template-argument "13.3 Names of template specializations [temp.names]") for a[*type-parameter*](temp.param#nt:type-parameter "13.2 Template parameters [temp.param]") ([[temp.arg.type]](temp.arg.type "13.4.2 Type template arguments")), or
|
||||
|
||||
- [(9.6)](#9.6)
|
||||
|
||||
the operand of a [*reflect-expression*](expr.reflect#nt:reflect-expression "7.6.2.10 The reflection operator [expr.reflect]") ([[expr.reflect]](expr.reflect "7.6.2.10 The 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.1 General [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.1 General [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.1 General [dcl.decl.general]"),
|
||||
the [*cv-qualifier-seq*](dcl.decl.general#nt:cv-qualifier-seq "9.3.1 General [dcl.decl.general]"), and
|
||||
the exception specification,
|
||||
but not the default arguments ([[dcl.fct.default]](dcl.fct.default "9.3.4.7 Default arguments"))
|
||||
or the trailing [*requires-clause*](temp.pre#nt:requires-clause "13.1 Preamble [temp.pre]") ([[dcl.decl]](dcl.decl "9.3 Declarators")),
|
||||
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.9 Type 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 "12 Overloading"))[.](#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.4 Deprecated 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.6 Function 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.6 Function 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.1 General [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.1 General [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.1 General [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.6 Functions [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.6 Functions [dcl.fct]") is a function declaration that has
|
||||
one or more generic parameter type placeholders ([[dcl.spec.auto]](dcl.spec.auto "9.2.9.7 Placeholder type specifiers"))[.](#21.sentence-1)
|
||||
|
||||
An abbreviated function template is equivalent to
|
||||
a function template ([[temp.fct]](temp.fct "13.7.7 Function templates"))
|
||||
whose [*template-parameter-list*](temp.pre#nt:template-parameter-list "13.1 Preamble [temp.pre]") includes
|
||||
one invented [*type-parameter*](temp.param#nt:type-parameter "13.2 Template 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.1 General [dcl.spec.auto.general]") of the form auto,
|
||||
the invented parameter is
|
||||
an unconstrained [*type-parameter*](temp.param#nt:type-parameter "13.2 Template parameters [temp.param]")[.](#21.sentence-3)
|
||||
|
||||
For a [*placeholder-type-specifier*](dcl.spec.auto.general#nt:placeholder-type-specifier "9.2.9.7.1 General [dcl.spec.auto.general]") of the form[*type-constraint*](temp.param#nt:type-constraint "13.2 Template parameters [temp.param]") auto,
|
||||
the invented parameter is a [*type-parameter*](temp.param#nt:type-parameter "13.2 Template parameters [temp.param]") with
|
||||
that [*type-constraint*](temp.param#nt:type-constraint "13.2 Template parameters [temp.param]")[.](#21.sentence-4)
|
||||
|
||||
The invented [*type-parameter*](temp.param#nt:type-parameter "13.2 Template parameters [temp.param]") declares
|
||||
a template parameter pack
|
||||
if the corresponding [*parameter-declaration*](#nt:parameter-declaration "9.3.4.6 Functions [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.6 Functions [dcl.fct]") by
|
||||
replacing each occurrence of a placeholder with
|
||||
the name of the corresponding invented [*type-parameter*](temp.param#nt:type-parameter "13.2 Template 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.1 Preamble [temp.pre]")[.](#22.sentence-1)
|
||||
|
||||
The invented [*type-parameter*](temp.param#nt:type-parameter "13.2 Template parameters [temp.param]")*s* are
|
||||
appended to the [*template-parameter-list*](temp.pre#nt:template-parameter-list "13.1 Preamble [temp.pre]") after
|
||||
the explicitly declared [*template-parameter*](temp.param#nt:template-parameter "13.2 Template 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.1 General [dcl.decl.general]") or [*abstract-declarator*](dcl.name#nt:abstract-declarator "9.3.2 Type names [dcl.name]") containing an ellipsis shall only
|
||||
be used in a [*parameter-declaration*](#nt:parameter-declaration "9.3.4.6 Functions [dcl.fct]")[.](#24.sentence-1)
|
||||
|
||||
When it is part of a[*parameter-declaration-clause*](#nt:parameter-declaration-clause "9.3.4.6 Functions [dcl.fct]"),
|
||||
the [*parameter-declaration*](#nt:parameter-declaration "9.3.4.6 Functions [dcl.fct]") declares a
|
||||
function parameter pack ([[temp.variadic]](temp.variadic "13.7.4 Variadic templates"))[.](#24.sentence-2)
|
||||
|
||||
Otherwise, the [*parameter-declaration*](#nt:parameter-declaration "9.3.4.6 Functions [dcl.fct]") is part of a[*template-parameter-list*](temp.pre#nt:template-parameter-list "13.1 Preamble [temp.pre]") and declares a
|
||||
template parameter pack; see [[temp.param]](temp.param "13.2 Template parameters")[.](#24.sentence-3)
|
||||
|
||||
A function parameter pack is a pack expansion ([[temp.variadic]](temp.variadic "13.7.4 Variadic 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.6 Functions [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.2 Type 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.6 Functions [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.6 Functions [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.1 General [dcl.decl.general]"))[.](#footnote-76.sentence-1)
|
||||
792
cppdraft/dcl/fct/def.md
Normal file
792
cppdraft/dcl/fct/def.md
Normal 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.1 General [dcl.fct.def.general]")
|
||||
[*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]")opt [*decl-specifier-seq*](dcl.spec.general#nt:decl-specifier-seq "9.2.1 General [dcl.spec.general]")opt [*declarator*](dcl.decl.general#nt:declarator "9.3.1 General [dcl.decl.general]") [*virt-specifier-seq*](class.mem.general#nt:virt-specifier-seq "11.4.1 General [class.mem.general]")opt
|
||||
[*function-contract-specifier-seq*](dcl.contract.func#nt:function-contract-specifier-seq "9.4.1 General [dcl.contract.func]")opt [*function-body*](#nt:function-body "9.6.1 General [dcl.fct.def.general]")
|
||||
[*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]")opt [*decl-specifier-seq*](dcl.spec.general#nt:decl-specifier-seq "9.2.1 General [dcl.spec.general]")opt [*declarator*](dcl.decl.general#nt:declarator "9.3.1 General [dcl.decl.general]") [*requires-clause*](temp.pre#nt:requires-clause "13.1 Preamble [temp.pre]")
|
||||
[*function-contract-specifier-seq*](dcl.contract.func#nt:function-contract-specifier-seq "9.4.1 General [dcl.contract.func]")opt [*function-body*](#nt:function-body "9.6.1 General [dcl.fct.def.general]")
|
||||
|
||||
[function-body:](#nt:function-body "9.6.1 General [dcl.fct.def.general]")
|
||||
[*ctor-initializer*](class.base.init#nt:ctor-initializer "11.9.3 Initializing bases and members [class.base.init]")opt [*compound-statement*](stmt.block#nt:compound-statement "8.4 Compound statement or block [stmt.block]")
|
||||
[*function-try-block*](except.pre#nt:function-try-block "14.1 Preamble [except.pre]")
|
||||
= default ;
|
||||
[*deleted-function-body*](#nt:deleted-function-body "9.6.1 General [dcl.fct.def.general]")
|
||||
|
||||
[deleted-function-body:](#nt:deleted-function-body "9.6.1 General [dcl.fct.def.general]")
|
||||
= delete ;
|
||||
= delete ( [*unevaluated-string*](lex.string.uneval#nt:unevaluated-string "5.13.6 Unevaluated 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.1 General [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.3 Initializing bases and members [class.base.init]") ([[class.base.init]](class.base.init "11.9.3 Initializing bases and members"))[.](#general-1.sentence-2)
|
||||
|
||||
The optional [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]") in a [*function-definition*](#nt:function-definition "9.6.1 General [dcl.fct.def.general]") appertains to the function[.](#general-1.sentence-3)
|
||||
|
||||
A [*function-definition*](#nt:function-definition "9.6.1 General [dcl.fct.def.general]") with a [*virt-specifier-seq*](class.mem.general#nt:virt-specifier-seq "11.4.1 General [class.mem.general]") shall be a [*member-declaration*](class.mem.general#nt:member-declaration "11.4.1 General [class.mem.general]") ([[class.mem]](class.mem "11.4 Class members"))[.](#general-1.sentence-4)
|
||||
|
||||
A [*function-definition*](#nt:function-definition "9.6.1 General [dcl.fct.def.general]") with a [*requires-clause*](temp.pre#nt:requires-clause "13.1 Preamble [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.1 General [dcl.fct.def.general]"),
|
||||
either void [*declarator*](dcl.decl.general#nt:declarator "9.3.1 General [dcl.decl.general]") ; or [*declarator*](dcl.decl.general#nt:declarator "9.3.1 General [dcl.decl.general]") ; shall be a well-formed function declaration
|
||||
as described in [[dcl.fct]](dcl.fct "9.3.4.6 Functions")[.](#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.3 Deleted 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.1 General [dcl.spec.general]");max(inta,intb,intc) is the[*declarator*](dcl.decl.general#nt:declarator "9.3.1 General [dcl.decl.general]");{ /* ... */ } is the[*function-body*](#nt:function-body "9.6.1 General [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.3 Initializing bases and members [class.base.init]") is used only in a constructor; see [[class.ctor]](class.ctor "11.4.5 Constructors") and [[class.init]](class.init "11.9 Initialization")[.](#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.1 General [dcl.decl.general]") affects the type of this in the body of a member function; see [[expr.prim.this]](expr.prim.this "7.5.3 This")[.](#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.1 General [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.11 Identifiers"))[.](#footnote-81.sentence-1)
|
||||
|
||||
If a predefined variable is not
|
||||
odr-used ([[basic.def.odr]](basic.def.odr#term.odr.use "6.3 One-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.1 General [dcl.fct.def.general]") is of the form= default ; is called an [*explicitly-defaulted*](#def:definition,function,explicitly-defaulted "9.6.2 Explicitly-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.4 Special member functions")) or
|
||||
a comparison operator function ([[over.binary]](over.binary "12.4.3 Binary operators"), [[class.compare.default]](class.compare.default "11.10.1 Defaulted comparison operator functions")), and
|
||||
|
||||
- [(1.2)](#default-1.2)
|
||||
|
||||
not have default arguments ([[dcl.fct.default]](dcl.fct.default "9.3.4.7 Default 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.1 General [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.8 The inline specifier")),
|
||||
and is implicitly constexpr ([[dcl.constexpr]](dcl.constexpr "9.2.6 The 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.2 Explicitly-defaulted functions [dcl.fct.def.default]") functions, and the implementation
|
||||
shall provide implicit definitions
|
||||
for them ([[class.ctor]](class.ctor "11.4.5 Constructors"), [[class.dtor]](class.dtor "11.4.7 Destructors"), [[class.copy.ctor]](class.copy.ctor "11.4.5.3 Copy/move constructors"), [[class.copy.assign]](class.copy.assign "11.4.6 Copy/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.7 Destructors"))
|
||||
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.4 Special member functions"))
|
||||
is defined as deleted[.](#default-5.sentence-3)
|
||||
|
||||
A function is[*user-provided*](#def:user-provided "9.6.2 Explicitly-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.3 One-definition rule"))
|
||||
or needed for constant evaluation ([[expr.const]](expr.const "7.7 Constant 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.3 Deleted definitions [dcl.fct.def.delete]") of a function is a function definition
|
||||
whose [*function-body*](#nt:function-body "9.6.1 General [dcl.fct.def.general]") is a [*deleted-function-body*](#nt:deleted-function-body "9.6.1 General [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.3 Deleted 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.10 The reflection operator [expr.reflect]") ([[expr.reflect]](expr.reflect "7.6.2.10 The 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.6 Unevaluated 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.3 One-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.6 Unevaluated 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.8 New [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.8 The inline specifier"))[.](#delete-4.sentence-1)
|
||||
|
||||
[*Note [2](#delete-note-2)*:
|
||||
|
||||
The
|
||||
one-definition rule ([[basic.def.odr]](basic.def.odr "6.3 One-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.5 Dynamic 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.4 Coroutine definitions [dcl.fct.def.coroutine]") if its [*function-body*](#nt:function-body "9.6.1 General [dcl.fct.def.general]") encloses a[*coroutine-return-statement*](stmt.return.coroutine#nt:coroutine-return-statement "8.8.5 The co_return statement [stmt.return.coroutine]") ([[stmt.return.coroutine]](stmt.return.coroutine "8.8.5 The co_return statement")),
|
||||
an [*await-expression*](expr.await#nt:await-expression "7.6.2.4 Await [expr.await]") ([[expr.await]](expr.await "7.6.2.4 Await")),
|
||||
or a [*yield-expression*](expr.yield#nt:yield-expression "7.6.17 Yielding a value [expr.yield]") ([[expr.yield]](expr.yield "7.6.17 Yielding a value"))[.](#coroutine-1.sentence-1)
|
||||
|
||||
The [*parameter-declaration-clause*](dcl.fct#nt:parameter-declaration-clause "9.3.4.6 Functions [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.6 Functions [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.4 Coroutine 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.6 Functions"))
|
||||
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.6 Functions [dcl.fct]")*s* in the declarator
|
||||
of its [*function-definition*](#nt:function-definition "9.6.1 General [dcl.fct.def.general]") were removed and
|
||||
its [*function-body*](#nt:function-body "9.6.1 General [dcl.fct.def.general]") were replaced by
|
||||
the following [*replacement body*](#def:body,replacement "9.6.4 Coroutine definitions [dcl.fct.def.coroutine]"):
|
||||
|
||||
{
|
||||
*promise-type* *promise* *promise-constructor-arguments* ;
|
||||
try {
|
||||
co_await *promise*.initial_suspend() ;
|
||||
[*function-body*](#nt:function-body "9.6.1 General [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.4 Await [expr.await]") containing
|
||||
the call to initial_suspend is the [*initial await expression*](#def:await_expression,initial "9.6.4 Coroutine definitions [dcl.fct.def.coroutine]"), and
|
||||
|
||||
- [(5.2)](#coroutine-5.2)
|
||||
|
||||
the [*await-expression*](expr.await#nt:await-expression "7.6.2.4 Await [expr.await]") containing
|
||||
the call to final_suspend is the [*final await expression*](#def:await_expression,final "9.6.4 Coroutine 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.4 Await"))
|
||||
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.4 Coroutine 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.5 The 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.3 Viable 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.4 Coroutine 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.4 Coroutine 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.1 General"))[.](#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.5 The 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.6 Resumption"))
|
||||
of a coroutine handle ([[coroutine.handle]](coroutine.handle "17.13.4 Class 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.4 Coroutine 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.4 Coroutine 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.2 Allocation 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.3 Viable 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.2 Member 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.5 Exception 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.6 Resumption"))
|
||||
of a coroutine handle ([[coroutine.handle]](coroutine.handle "17.13.4 Class 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.10 Declaration 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.3 Deallocation 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.1 General [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.2 Unqualified 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.5 Exception 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.5 Replaceable 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.5 Replaceable 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.3 One-definition rule"), [[basic.start]](basic.start "6.10.3 Start 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.3 One-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*]
|
||||
352
cppdraft/dcl/fct/def/coroutine.md
Normal file
352
cppdraft/dcl/fct/def/coroutine.md
Normal 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.4 Coroutine definitions [dcl.fct.def.coroutine]") if its [*function-body*](dcl.fct.def.general#nt:function-body "9.6.1 General [dcl.fct.def.general]") encloses a[*coroutine-return-statement*](stmt.return.coroutine#nt:coroutine-return-statement "8.8.5 The co_return statement [stmt.return.coroutine]") ([[stmt.return.coroutine]](stmt.return.coroutine "8.8.5 The co_return statement")),
|
||||
an [*await-expression*](expr.await#nt:await-expression "7.6.2.4 Await [expr.await]") ([[expr.await]](expr.await "7.6.2.4 Await")),
|
||||
or a [*yield-expression*](expr.yield#nt:yield-expression "7.6.17 Yielding a value [expr.yield]") ([[expr.yield]](expr.yield "7.6.17 Yielding a value"))[.](#1.sentence-1)
|
||||
|
||||
The [*parameter-declaration-clause*](dcl.fct#nt:parameter-declaration-clause "9.3.4.6 Functions [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.6 Functions [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.4 Coroutine 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.6 Functions"))
|
||||
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.6 Functions [dcl.fct]")*s* in the declarator
|
||||
of its [*function-definition*](dcl.fct.def.general#nt:function-definition "9.6.1 General [dcl.fct.def.general]") were removed and
|
||||
its [*function-body*](dcl.fct.def.general#nt:function-body "9.6.1 General [dcl.fct.def.general]") were replaced by
|
||||
the following [*replacement body*](#def:body,replacement "9.6.4 Coroutine 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.1 General [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.4 Await [expr.await]") containing
|
||||
the call to initial_suspend is the [*initial await expression*](#def:await_expression,initial "9.6.4 Coroutine definitions [dcl.fct.def.coroutine]"), and
|
||||
|
||||
- [(5.2)](#5.2)
|
||||
|
||||
the [*await-expression*](expr.await#nt:await-expression "7.6.2.4 Await [expr.await]") containing
|
||||
the call to final_suspend is the [*final await expression*](#def:await_expression,final "9.6.4 Coroutine 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.4 Await"))
|
||||
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.4 Coroutine 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.5 The 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.3 Viable 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.4 Coroutine 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.4 Coroutine 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.1 General"))[.](#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.5 The 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.6 Resumption"))
|
||||
of a coroutine handle ([[coroutine.handle]](coroutine.handle "17.13.4 Class 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.4 Coroutine 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.4 Coroutine 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.2 Allocation 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.3 Viable 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.2 Member 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.5 Exception 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.6 Resumption"))
|
||||
of a coroutine handle ([[coroutine.handle]](coroutine.handle "17.13.4 Class 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.10 Declaration 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.3 Deallocation 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.1 General [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.2 Unqualified 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.5 Exception specifications"))[.](#16.sentence-1)
|
||||
158
cppdraft/dcl/fct/def/default.md
Normal file
158
cppdraft/dcl/fct/def/default.md
Normal 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.1 General [dcl.fct.def.general]") is of the form= default ; is called an [*explicitly-defaulted*](#def:definition,function,explicitly-defaulted "9.6.2 Explicitly-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.4 Special member functions")) or
|
||||
a comparison operator function ([[over.binary]](over.binary "12.4.3 Binary operators"), [[class.compare.default]](class.compare.default "11.10.1 Defaulted comparison operator functions")), and
|
||||
|
||||
- [(1.2)](#1.2)
|
||||
|
||||
not have default arguments ([[dcl.fct.default]](dcl.fct.default "9.3.4.7 Default 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.1 General [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.8 The inline specifier")),
|
||||
and is implicitly constexpr ([[dcl.constexpr]](dcl.constexpr "9.2.6 The 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.2 Explicitly-defaulted functions [dcl.fct.def.default]") functions, and the implementation
|
||||
shall provide implicit definitions
|
||||
for them ([[class.ctor]](class.ctor "11.4.5 Constructors"), [[class.dtor]](class.dtor "11.4.7 Destructors"), [[class.copy.ctor]](class.copy.ctor "11.4.5.3 Copy/move constructors"), [[class.copy.assign]](class.copy.assign "11.4.6 Copy/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.7 Destructors"))
|
||||
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.4 Special member functions"))
|
||||
is defined as deleted[.](#5.sentence-3)
|
||||
|
||||
A function is[*user-provided*](#def:user-provided "9.6.2 Explicitly-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.3 One-definition rule"))
|
||||
or needed for constant evaluation ([[expr.const]](expr.const "7.7 Constant 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*]
|
||||
112
cppdraft/dcl/fct/def/delete.md
Normal file
112
cppdraft/dcl/fct/def/delete.md
Normal 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.3 Deleted definitions [dcl.fct.def.delete]") of a function is a function definition
|
||||
whose [*function-body*](dcl.fct.def.general#nt:function-body "9.6.1 General [dcl.fct.def.general]") is a [*deleted-function-body*](dcl.fct.def.general#nt:deleted-function-body "9.6.1 General [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.3 Deleted 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.10 The reflection operator [expr.reflect]") ([[expr.reflect]](expr.reflect "7.6.2.10 The 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.6 Unevaluated 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.3 One-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.6 Unevaluated 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.8 New [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.8 The inline specifier"))[.](#4.sentence-1)
|
||||
|
||||
[*Note [2](#note-2)*:
|
||||
|
||||
The
|
||||
one-definition rule ([[basic.def.odr]](basic.def.odr "6.3 One-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.5 Dynamic 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*]
|
||||
127
cppdraft/dcl/fct/def/general.md
Normal file
127
cppdraft/dcl/fct/def/general.md
Normal 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.1 General [dcl.fct.def.general]")
|
||||
[*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]")opt [*decl-specifier-seq*](dcl.spec.general#nt:decl-specifier-seq "9.2.1 General [dcl.spec.general]")opt [*declarator*](dcl.decl.general#nt:declarator "9.3.1 General [dcl.decl.general]") [*virt-specifier-seq*](class.mem.general#nt:virt-specifier-seq "11.4.1 General [class.mem.general]")opt
|
||||
[*function-contract-specifier-seq*](dcl.contract.func#nt:function-contract-specifier-seq "9.4.1 General [dcl.contract.func]")opt [*function-body*](#nt:function-body "9.6.1 General [dcl.fct.def.general]")
|
||||
[*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]")opt [*decl-specifier-seq*](dcl.spec.general#nt:decl-specifier-seq "9.2.1 General [dcl.spec.general]")opt [*declarator*](dcl.decl.general#nt:declarator "9.3.1 General [dcl.decl.general]") [*requires-clause*](temp.pre#nt:requires-clause "13.1 Preamble [temp.pre]")
|
||||
[*function-contract-specifier-seq*](dcl.contract.func#nt:function-contract-specifier-seq "9.4.1 General [dcl.contract.func]")opt [*function-body*](#nt:function-body "9.6.1 General [dcl.fct.def.general]")
|
||||
|
||||
[function-body:](#nt:function-body "9.6.1 General [dcl.fct.def.general]")
|
||||
[*ctor-initializer*](class.base.init#nt:ctor-initializer "11.9.3 Initializing bases and members [class.base.init]")opt [*compound-statement*](stmt.block#nt:compound-statement "8.4 Compound statement or block [stmt.block]")
|
||||
[*function-try-block*](except.pre#nt:function-try-block "14.1 Preamble [except.pre]")
|
||||
= default ;
|
||||
[*deleted-function-body*](#nt:deleted-function-body "9.6.1 General [dcl.fct.def.general]")
|
||||
|
||||
[deleted-function-body:](#nt:deleted-function-body "9.6.1 General [dcl.fct.def.general]")
|
||||
= delete ;
|
||||
= delete ( [*unevaluated-string*](lex.string.uneval#nt:unevaluated-string "5.13.6 Unevaluated 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.1 General [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.3 Initializing bases and members [class.base.init]") ([[class.base.init]](class.base.init "11.9.3 Initializing bases and members"))[.](#1.sentence-2)
|
||||
|
||||
The optional [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]") in a [*function-definition*](#nt:function-definition "9.6.1 General [dcl.fct.def.general]") appertains to the function[.](#1.sentence-3)
|
||||
|
||||
A [*function-definition*](#nt:function-definition "9.6.1 General [dcl.fct.def.general]") with a [*virt-specifier-seq*](class.mem.general#nt:virt-specifier-seq "11.4.1 General [class.mem.general]") shall be a [*member-declaration*](class.mem.general#nt:member-declaration "11.4.1 General [class.mem.general]") ([[class.mem]](class.mem "11.4 Class members"))[.](#1.sentence-4)
|
||||
|
||||
A [*function-definition*](#nt:function-definition "9.6.1 General [dcl.fct.def.general]") with a [*requires-clause*](temp.pre#nt:requires-clause "13.1 Preamble [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.1 General [dcl.fct.def.general]"),
|
||||
either void [*declarator*](dcl.decl.general#nt:declarator "9.3.1 General [dcl.decl.general]") ; or [*declarator*](dcl.decl.general#nt:declarator "9.3.1 General [dcl.decl.general]") ; shall be a well-formed function declaration
|
||||
as described in [[dcl.fct]](dcl.fct "9.3.4.6 Functions")[.](#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.3 Deleted 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.1 General [dcl.spec.general]");max(inta,intb,intc) is the[*declarator*](dcl.decl.general#nt:declarator "9.3.1 General [dcl.decl.general]");{ /* ... */ } is the[*function-body*](#nt:function-body "9.6.1 General [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.3 Initializing bases and members [class.base.init]") is used only in a constructor; see [[class.ctor]](class.ctor "11.4.5 Constructors") and [[class.init]](class.init "11.9 Initialization")[.](#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.1 General [dcl.decl.general]") affects the type of this in the body of a member function; see [[expr.prim.this]](expr.prim.this "7.5.3 This")[.](#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.1 General [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.11 Identifiers"))[.](#footnote-81.sentence-1)
|
||||
|
||||
If a predefined variable is not
|
||||
odr-used ([[basic.def.odr]](basic.def.odr#term.odr.use "6.3 One-definition rule")), its string value need not be present in the program image[.](#footnote-81.sentence-2)
|
||||
63
cppdraft/dcl/fct/def/replace.md
Normal file
63
cppdraft/dcl/fct/def/replace.md
Normal 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.5 Replaceable 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.5 Replaceable 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.3 One-definition rule"), [[basic.start]](basic.start "6.10.3 Start 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.3 One-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
272
cppdraft/dcl/fct/default.md
Normal 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.1 General [dcl.init.general]") is specified in a[*parameter-declaration*](dcl.fct#nt:parameter-declaration "9.3.4.6 Functions [dcl.fct]") this[*initializer-clause*](dcl.init.general#nt:initializer-clause "9.5.1 General [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.3 Function 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.6 Functions [dcl.fct]") of a function declaration
|
||||
or [*lambda-declarator*](expr.prim.lambda.general#nt:lambda-declarator "7.5.6.1 General [expr.prim.lambda.general]") or in a[*template-parameter*](temp.param#nt:template-parameter "13.2 Template parameters [temp.param]") ([[temp.param]](temp.param "13.2 Template 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.6 Functions [dcl.fct]"),
|
||||
it shall not occur within a[*declarator*](dcl.decl.general#nt:declarator "9.3.1 General [dcl.decl.general]") or[*abstract-declarator*](dcl.name#nt:abstract-declarator "9.3.2 Type names [dcl.name]") of a[*parameter-declaration*](dcl.fct#nt:parameter-declaration "9.3.4.6 Functions [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.3 One-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.5 Initializers"))[.](#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.7 Constant expressions")) that
|
||||
is a potentially-evaluated subexpression ([[intro.execution]](intro.execution "6.10.1 Sequential execution")) of
|
||||
the [*initializer-clause*](dcl.init.general#nt:initializer-clause "9.5.1 General [dcl.init.general]") in a [*parameter-declaration*](dcl.fct#nt:parameter-declaration "9.3.4.6 Functions [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.2 Implicit 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.4 Class members"))[.](#5.sentence-5)
|
||||
|
||||
Access checking applies to names in default arguments as
|
||||
described in [[class.access]](class.access "11.8 Member 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.2 Default constructors")),
|
||||
copy or move constructor ([[class.copy.ctor]](class.copy.ctor "11.4.5.3 Copy/move constructors")), or
|
||||
copy or move assignment operator ([[class.copy.assign]](class.copy.assign "11.4.6 Copy/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.3 One-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.3 This")[.](#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.3 Context 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.1 General [expr.prim.id.general]") or [*splice-expression*](expr.prim.splice#nt:splice-expression "7.5.9 Expression splicing [expr.prim.splice]") of a class member access expression ([[expr.ref]](expr.ref "7.6.1.5 Class 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.2 Unary operators")), or
|
||||
|
||||
- [(9.3)](#9.3)
|
||||
|
||||
it appears as the operand of
|
||||
a [*reflect-expression*](expr.reflect#nt:reflect-expression "7.6.2.10 The reflection operator [expr.reflect]") ([[expr.reflect]](expr.reflect "7.6.2.10 The 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 "11 Classes")[.](#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.3 Viable 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.10 The 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.3 Virtual 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
61
cppdraft/dcl/fct/spec.md
Normal 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.3 Function 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.3 Function 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.1 General [dcl.spec.general]")[.](#1.sentence-2)
|
||||
|
||||
[function-specifier:](#nt:function-specifier "9.2.3 Function specifiers [dcl.fct.spec]")
|
||||
virtual
|
||||
[*explicit-specifier*](#nt:explicit-specifier "9.2.3 Function specifiers [dcl.fct.spec]")
|
||||
|
||||
[explicit-specifier:](#nt:explicit-specifier "9.2.3 Function specifiers [dcl.fct.spec]")
|
||||
explicit ( [*constant-expression*](expr.const#nt:constant-expression "7.7 Constant 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.3 Virtual 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.3 Function 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.2 Conversion by constructor") and [[class.conv.fct]](class.conv.fct "11.4.8.3 Conversion 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.3 Function specifiers [dcl.fct.spec]"),
|
||||
the [*constant-expression*](expr.const#nt:constant-expression "7.7 Constant expressions [expr.const]"), if supplied, shall be a
|
||||
contextually converted constant expression of type bool ([[expr.const]](expr.const "7.7 Constant expressions"))[.](#4.sentence-1)
|
||||
|
||||
The [*explicit-specifier*](#nt:explicit-specifier "9.2.3 Function specifiers [dcl.fct.spec]") explicit without a [*constant-expression*](expr.const#nt:constant-expression "7.7 Constant expressions [expr.const]") is equivalent to
|
||||
the [*explicit-specifier*](#nt:explicit-specifier "9.2.3 Function 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.3 Function 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
14
cppdraft/dcl/friend.md
Normal 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.4 Friends")[.](#1.sentence-1)
|
||||
1693
cppdraft/dcl/init.md
Normal file
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
503
cppdraft/dcl/init/aggr.md
Normal 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.2 Aggregates [dcl.init.aggr]") is an array or a class ([[class]](class "11 Classes")) with
|
||||
|
||||
- [(1.1)](#1.1)
|
||||
|
||||
no user-declared or inherited constructors ([[class.ctor]](class.ctor "11.4.5 Constructors")),
|
||||
|
||||
- [(1.2)](#1.2)
|
||||
|
||||
no private or protected direct non-static data members ([[class.access]](class.access "11.8 Member access control")),
|
||||
|
||||
- [(1.3)](#1.3)
|
||||
|
||||
no private or protected direct base classes ([[class.access.base]](class.access.base "11.8.3 Accessibility of base classes and base class members")), and
|
||||
|
||||
- [(1.4)](#1.4)
|
||||
|
||||
no virtual functions ([[class.virtual]](class.virtual "11.7.3 Virtual functions")) or virtual base classes ([[class.mi]](class.mi "11.7.2 Multiple 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.2 Aggregates [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.4 Class 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.5 List-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.2 Aggregates [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.1 General [dcl.init.general]"),
|
||||
the aggregate shall be of class type,
|
||||
the [*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]") in each [*designator*](dcl.init.general#nt:designator "9.5.1 General [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.1 General [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.1 General [dcl.init.general]"),
|
||||
the element is initialized by the[*braced-init-list*](dcl.init.general#nt:braced-init-list "9.5.1 General [dcl.init.general]") { *D* },
|
||||
where *D* is the [*designated-initializer-clause*](dcl.init.general#nt:designated-initializer-clause "9.5.1 General [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.1 General [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.1 General [dcl.init.general]"),
|
||||
the element is initialized with the [*brace-or-equal-initializer*](dcl.init.general#nt:brace-or-equal-initializer "9.5.1 General [dcl.init.general]") of the corresponding [*designated-initializer-clause*](dcl.init.general#nt:designated-initializer-clause "9.5.1 General [dcl.init.general]")[.](#4.2.sentence-1)
|
||||
If that initializer is of the form= [*assignment-expression*](expr.assign#nt:assignment-expression "7.6.19 Assignment and compound assignment operators [expr.assign]") and
|
||||
a narrowing conversion ([[dcl.init.list]](dcl.init.list "9.5.5 List-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.1 General [dcl.init.general]")[.](#4.3.sentence-1)
|
||||
If an [*initializer-clause*](dcl.init.general#nt:initializer-clause "9.5.1 General [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.1 General [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.1 General [dcl.init.general]") consisting of all of the [*initializer-clause*](dcl.init.general#nt:initializer-clause "9.5.1 General [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.4 Class 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.5 List-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.5 Initializers")[.](#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.7 Destructors"))
|
||||
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.3 Stack 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.5 Arrays")) in an array of unknown bound
|
||||
initialized with a brace-enclosed [*initializer-list*](dcl.init.general#nt:initializer-list "9.5.1 General [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.1 General [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.3 Initializing bases and members [class.base.init]") is present ([[class.base.init]](class.base.init "11.9.3 Initializing 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.1 General [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.5 Arrays"))[.](#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.1 General [dcl.init.general]") in
|
||||
a brace-enclosed [*initializer-list*](dcl.init.general#nt:initializer-list "9.5.1 General [dcl.init.general]") is said to [*appertain*](dcl.attr.grammar#def:appertain "9.13.1 Attribute 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.1 General [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.1 General [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.1 General [dcl.init.general]") begins with a left brace, or
|
||||
|
||||
- [(14.3)](#14.3)
|
||||
|
||||
the [*initializer-clause*](dcl.init.general#nt:initializer-clause "9.5.1 General [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.1 General [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.1 General [dcl.init.general]")*s* have been exhausted[.](#14.sentence-6)
|
||||
|
||||
If any [*initializer-clause*](dcl.init.general#nt:initializer-clause "9.5.1 General [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.1 General [dcl.init.general]") are elided;
|
||||
however the[*initializer-list*](dcl.init.general#nt:initializer-list "9.5.1 General [dcl.init.general]") has the same effect as the completely-braced[*initializer-list*](dcl.init.general#nt:initializer-list "9.5.1 General [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.1 General [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.5 Constructors"))[.](#18.sentence-1)
|
||||
|
||||
Initialization of these aggregate objects is described in [[class.expl.init]](class.expl.init "11.9.2 Explicit 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.2 Static initialization"), [[basic.start.dynamic]](basic.start.dynamic "6.10.3.3 Dynamic initialization of non-block variables"), and [[stmt.dcl]](stmt.dcl "8.10 Declaration 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.1 General [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.1 General [dcl.init.general]")*s*,
|
||||
but nonetheless C++ does not have zero length arrays[.](#footnote-79.sentence-1)
|
||||
593
cppdraft/dcl/init/general.md
Normal file
593
cppdraft/dcl/init/general.md
Normal 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.5 Initializers") applies to
|
||||
all initializations regardless of syntactic context, including the
|
||||
initialization of a function parameter ([[expr.call]](expr.call "7.6.1.3 Function call")), the
|
||||
initialization of a return value ([[stmt.return]](stmt.return "8.8.4 The return statement")), or when an
|
||||
initializer follows a declarator[.](#1.sentence-1)
|
||||
|
||||
[initializer:](#nt:initializer "9.5.1 General [dcl.init.general]")
|
||||
[*brace-or-equal-initializer*](#nt:brace-or-equal-initializer "9.5.1 General [dcl.init.general]")
|
||||
( [*expression-list*](expr.post.general#nt:expression-list "7.6.1.1 General [expr.post.general]") )
|
||||
|
||||
[brace-or-equal-initializer:](#nt:brace-or-equal-initializer "9.5.1 General [dcl.init.general]")
|
||||
= [*initializer-clause*](#nt:initializer-clause "9.5.1 General [dcl.init.general]")
|
||||
[*braced-init-list*](#nt:braced-init-list "9.5.1 General [dcl.init.general]")
|
||||
|
||||
[initializer-clause:](#nt:initializer-clause "9.5.1 General [dcl.init.general]")
|
||||
[*assignment-expression*](expr.assign#nt:assignment-expression "7.6.19 Assignment and compound assignment operators [expr.assign]")
|
||||
[*braced-init-list*](#nt:braced-init-list "9.5.1 General [dcl.init.general]")
|
||||
|
||||
[braced-init-list:](#nt:braced-init-list "9.5.1 General [dcl.init.general]")
|
||||
{ [*initializer-list*](#nt:initializer-list "9.5.1 General [dcl.init.general]") ,opt }
|
||||
{ [*designated-initializer-list*](#nt:designated-initializer-list "9.5.1 General [dcl.init.general]") ,opt }
|
||||
{ }
|
||||
|
||||
[initializer-list:](#nt:initializer-list "9.5.1 General [dcl.init.general]")
|
||||
[*initializer-clause*](#nt:initializer-clause "9.5.1 General [dcl.init.general]") ...opt
|
||||
[*initializer-list*](#nt:initializer-list "9.5.1 General [dcl.init.general]") , [*initializer-clause*](#nt:initializer-clause "9.5.1 General [dcl.init.general]") ...opt
|
||||
|
||||
[designated-initializer-list:](#nt:designated-initializer-list "9.5.1 General [dcl.init.general]")
|
||||
[*designated-initializer-clause*](#nt:designated-initializer-clause "9.5.1 General [dcl.init.general]")
|
||||
[*designated-initializer-list*](#nt:designated-initializer-list "9.5.1 General [dcl.init.general]") , [*designated-initializer-clause*](#nt:designated-initializer-clause "9.5.1 General [dcl.init.general]")
|
||||
|
||||
[designated-initializer-clause:](#nt:designated-initializer-clause "9.5.1 General [dcl.init.general]")
|
||||
[*designator*](#nt:designator "9.5.1 General [dcl.init.general]") [*brace-or-equal-initializer*](#nt:brace-or-equal-initializer "9.5.1 General [dcl.init.general]")
|
||||
|
||||
[designator:](#nt:designator "9.5.1 General [dcl.init.general]")
|
||||
. [*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]")
|
||||
|
||||
[expr-or-braced-init-list:](#nt:expr-or-braced-init-list "9.5.1 General [dcl.init.general]")
|
||||
[*expression*](expr.comma#nt:expression "7.6.20 Comma operator [expr.comma]")
|
||||
[*braced-init-list*](#nt:braced-init-list "9.5.1 General [dcl.init.general]")
|
||||
|
||||
[*Note [1](#note-1)*:
|
||||
|
||||
The rules in [[dcl.init]](dcl.init "9.5 Initializers") apply even if the grammar permits only
|
||||
the [*brace-or-equal-initializer*](#nt:brace-or-equal-initializer "9.5.1 General [dcl.init.general]") form
|
||||
of [*initializer*](#nt:initializer "9.5.1 General [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.6 The constexpr and consteval specifiers"),
|
||||
an [*initializer*](#nt:initializer "9.5.1 General [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.7 Default 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.3 Start and termination") and [[stmt.dcl]](stmt.dcl "8.10 Declaration 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.1 General [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.1 General [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.1 General")),
|
||||
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.1 General")) 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.1 General")) 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.1 General [dcl.init.general]") an object of typeT means:
|
||||
|
||||
- [(7.1)](#7.1)
|
||||
|
||||
IfT is a (possibly cv-qualified) class type ([[class]](class "11 Classes")),
|
||||
constructors are considered[.](#7.1.sentence-1)
|
||||
The applicable constructors are
|
||||
enumerated ([[over.match.ctor]](over.match.ctor "12.2.2.4 Initialization by constructor")), and the best one for the[*initializer*](#nt:initializer "9.5.1 General [dcl.init.general]") () is chosen through
|
||||
overload resolution ([[over.match]](over.match "12.2 Overload 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.1 General [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.1 General [dcl.init.general]") an object of typeT means:
|
||||
|
||||
- [(9.1)](#9.1)
|
||||
|
||||
IfT is a (possibly cv-qualified) class type ([[class]](class "11 Classes")), 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.2 Static 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.1 General [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.1 General [dcl.init.general]") or[*condition*](stmt.pre#nt:condition "8.1 Preamble [stmt.pre]") ([[stmt.select]](stmt.select "8.5 Selection statements")),
|
||||
as well as in argument passing, function return,
|
||||
throwing an exception ([[except.throw]](except.throw "14.2 Throwing an exception")),
|
||||
handling an exception ([[except.handle]](except.handle "14.4 Handling an exception")),
|
||||
and aggregate member initialization other than by a[*designated-initializer-clause*](#nt:designated-initializer-clause "9.5.1 General [dcl.init.general]") ([[dcl.init.aggr]](dcl.init.aggr "9.5.2 Aggregates")),
|
||||
is called[*copy-initialization*](#def:copy-initialization "9.5.1 General [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.3 Copy/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.1 General [dcl.init.general]") that is a
|
||||
parenthesized [*expression-list*](expr.post.general#nt:expression-list "7.6.1.1 General [expr.post.general]") or a [*braced-init-list*](#nt:braced-init-list "9.5.1 General [dcl.init.general]"),
|
||||
|
||||
- [(15.2)](#15.2)
|
||||
|
||||
for a [*new-initializer*](expr.new#nt:new-initializer "7.6.2.8 New [expr.new]") ([[expr.new]](expr.new "7.6.2.8 New")),
|
||||
|
||||
- [(15.3)](#15.3)
|
||||
|
||||
in a static_cast expression ([[expr.static.cast]](expr.static.cast "7.6.1.9 Static cast")),
|
||||
|
||||
- [(15.4)](#15.4)
|
||||
|
||||
in a functional notation type conversion ([[expr.type.conv]](expr.type.conv "7.6.1.4 Explicit type conversion (functional notation)")), and
|
||||
|
||||
- [(15.5)](#15.5)
|
||||
|
||||
in the [*braced-init-list*](#nt:braced-init-list "9.5.1 General [dcl.init.general]") form of a [*condition*](stmt.pre#nt:condition "8.1 Preamble [stmt.pre]")
|
||||
|
||||
is called[*direct-initialization*](#def:direct-initialization "9.5.1 General [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.1 General [dcl.init.general]") or is = [*braced-init-list*](#nt:braced-init-list "9.5.1 General [dcl.init.general]"), the object or reference
|
||||
is list-initialized ([[dcl.init.list]](dcl.init.list "9.5.5 List-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.4 References")[.](#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.5 String literals [lex.string]"), see [[dcl.init.string]](dcl.init.string "9.5.3 Character 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.1 General [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.8 New"), [[expr.type.conv]](expr.type.conv "7.6.1.4 Explicit type conversion (functional notation)"), [[class.base.init]](class.base.init "11.9.3 Initializing 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.1 General [dcl.init.general]") shall be of the form( [*expression-list*](expr.post.general#nt:expression-list "7.6.1.1 General [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.1 General [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<iâ¤n[.](#16.5.sentence-7)
|
||||
For each 1â¤i<jâ¤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.4 Initialization by constructor")), and the best one is chosen
|
||||
through overload resolution ([[over.match]](over.match "12.2 Overload 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.1 General [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.1 General [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.2 Aggregates"))[.](#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.1 General [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 1â¤i<jâ¤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.5 List-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.7 Temporary 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.5 Copy-initialization of class by user-defined conversion"),
|
||||
and the best one is chosen through overload resolution ([[over.match]](over.match "12.2 Overload 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.6 Initialization by conversion function")),
|
||||
and the best one is chosen through overload
|
||||
resolution ([[over.match]](over.match "12.2 Overload 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.3 Standard 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* Tâ
|
||||
can initialize an object of type
|
||||
â*cv2* Tâ
|
||||
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.7 Constant expressions")) that is not evaluated where
|
||||
it appears ([[dcl.fct.default]](dcl.fct.default "9.3.4.7 Default arguments"), [[class.mem.general]](class.mem.general "11.4.1 General"))
|
||||
is evaluated and checked for whether it is
|
||||
a constant expression at the point where
|
||||
the enclosing [*initializer*](#nt:initializer "9.5.1 General [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.1 General [dcl.init.general]") followed by an ellipsis is a
|
||||
pack expansion ([[temp.variadic]](temp.variadic "13.7.4 Variadic 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.1 General [dcl.init.general]") of
|
||||
the initializer (possibly nested within [*braced-init-list*](#nt:braced-init-list "9.5.1 General [dcl.init.general]")*s*) and
|
||||
the creation of any temporary objects for
|
||||
function arguments or return values ([[class.temporary]](class.temporary "6.8.7 Temporary 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.1 General [expr.post.general]"),
|
||||
the expressions are evaluated in the order
|
||||
specified for function calls ([[expr.call]](expr.call "7.6.1.3 Function 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.11 Identifiers [lex.name]") shall not appear in multiple [*designator*](#nt:designator "9.5.1 General [dcl.init.general]")*s* of a[*designated-initializer-list*](#nt:designated-initializer-list "9.5.1 General [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.2 Aggregates"))
|
||||
or by an inherited constructor ([[class.inhctor.init]](class.inhctor.init "11.9.4 Initialization 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.4 Lifetime"))[.](#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.1 General [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.2 Declarations 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.3 Static 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.12 Pointer 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
368
cppdraft/dcl/init/list.md
Normal 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.5 List-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.1 General [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.1 General [dcl.init.general]")*s* of the [*initializer-list*](dcl.init.general#nt:initializer-list "9.5.1 General [dcl.init.general]") or[*designated-initializer-clause*](dcl.init.general#nt:designated-initializer-clause "9.5.1 General [dcl.init.general]")*s* of the [*designated-initializer-list*](dcl.init.general#nt:designated-initializer-list "9.5.1 General [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.5 List-initialization [dcl.init.list]") and list-initialization in a
|
||||
copy-initialization context is called [*copy-list-initialization*](#def:copy-list-initialization "9.5.5 List-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.5 List-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.5 Initializers")),
|
||||
|
||||
- [(1.2)](#1.2)
|
||||
|
||||
as the initializer in a [*new-expression*](expr.new#nt:new-expression "7.6.2.8 New [expr.new]") ([[expr.new]](expr.new "7.6.2.8 New")),
|
||||
|
||||
- [(1.3)](#1.3)
|
||||
|
||||
in a return statement ([[stmt.return]](stmt.return "8.8.4 The return statement")),
|
||||
|
||||
- [(1.4)](#1.4)
|
||||
|
||||
as a [*for-range-initializer*](stmt.pre#nt:for-range-initializer "8.1 Preamble [stmt.pre]") ([[stmt.iter]](stmt.iter "8.6 Iteration statements")),
|
||||
|
||||
- [(1.5)](#1.5)
|
||||
|
||||
as a function argument ([[expr.call]](expr.call "7.6.1.3 Function call")),
|
||||
|
||||
- [(1.6)](#1.6)
|
||||
|
||||
as a template argument ([[temp.arg.nontype]](temp.arg.nontype "13.4.3 Constant template arguments")),
|
||||
|
||||
- [(1.7)](#1.7)
|
||||
|
||||
as a subscript ([[expr.sub]](expr.sub "7.6.1.2 Subscripting")),
|
||||
|
||||
- [(1.8)](#1.8)
|
||||
|
||||
as an argument to a constructor invocation ([[dcl.init]](dcl.init "9.5 Initializers"), [[expr.type.conv]](expr.type.conv "7.6.1.4 Explicit type conversion (functional notation)")),
|
||||
|
||||
- [(1.9)](#1.9)
|
||||
|
||||
as an initializer for a non-static data member ([[class.mem]](class.mem "11.4 Class members")),
|
||||
|
||||
- [(1.10)](#1.10)
|
||||
|
||||
in a [*mem-initializer*](class.base.init#nt:mem-initializer "11.9.3 Initializing bases and members [class.base.init]") ([[class.base.init]](class.base.init "11.9.3 Initializing bases and members")), or
|
||||
|
||||
- [(1.11)](#1.11)
|
||||
|
||||
on the right-hand side of an assignment ([[expr.assign]](expr.assign "7.6.19 Assignment 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.5 List-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.7 Default 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.8 Initialization 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.2 Deducing 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.2 Header <initializer_list> synopsis"), [[std.modules]](std.modules "16.4.2.4 Modules"))
|
||||
of std::initializer_list is not reachable from ([[module.reach]](module.reach "10.7 Reachability"))
|
||||
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.7 Placeholder 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.1 General [dcl.init.general]") contains a [*designated-initializer-list*](dcl.init.general#nt:designated-initializer-list "9.5.1 General [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.11 Identifiers [lex.name]")*s* in the [*designator*](dcl.init.general#nt:designator "9.5.1 General [dcl.init.general]")*s* of the [*designated-initializer-list*](dcl.init.general#nt:designated-initializer-list "9.5.1 General [dcl.init.general]") shall form a subsequence
|
||||
of the ordered [*identifier*](lex.name#nt:identifier "5.11 Identifiers [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.2 Aggregates"))[.](#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.5 String literals [lex.string]") ([[dcl.init.string]](dcl.init.string "9.5.3 Character 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.2 Aggregates"))[.](#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.2 Overload resolution"), [[over.match.list]](over.match.list "12.2.2.8 Initialization 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.1 Enumeration declarations")) U,
|
||||
the [*initializer-list*](dcl.init.general#nt:initializer-list "9.5.1 General [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.4 Explicit 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.1 General [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.1 General [dcl.init.general]") of a [*braced-init-list*](dcl.init.general#nt:braced-init-list "9.5.1 General [dcl.init.general]"),
|
||||
the [*initializer-clause*](dcl.init.general#nt:initializer-clause "9.5.1 General [dcl.init.general]")*s*, including any that result from pack
|
||||
expansions ([[temp.variadic]](temp.variadic "13.7.4 Variadic 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.1 General [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.1 General [dcl.init.general]") that follows it in the comma-separated list of the [*initializer-list*](dcl.init.general#nt:initializer-list "9.5.1 General [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.1 General [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.5 Temporary 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.5 List-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.8 Member 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.2 Object 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.7 Temporary 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.3 Initializing 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.3 Initializing 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.5 List-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
188
cppdraft/dcl/init/ref.md
Normal 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.3 References"))
|
||||
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.19 Assignment and compound assignment operators"))[.](#2.sentence-2)
|
||||
|
||||
â *end note*]
|
||||
|
||||
Argument passing ([[expr.call]](expr.call "7.6.1.3 Function call"))and function value return ([[stmt.return]](stmt.return "8.8.4 The 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.6 Functions")),
|
||||
in the declaration of a function return type, in the declaration of
|
||||
a class member within its class definition ([[class.mem]](class.mem "11.4 Class 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.4 References [dcl.init.ref]") to
|
||||
â*cv2* T2â ifT1 is similar ([[conv.qual]](conv.qual "7.3.6 Qualification conversions")) to T2, orT1 is a base class of T2[.](#4.sentence-1)
|
||||
|
||||
â*cv1* T1â is [*reference-compatible*](#def:reference-compatible "9.5.4 References [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.3 Standard 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.7 Initialization by conversion function for direct reference binding")) and choosing the best one through [overload
|
||||
resolution](over.match "12.2 Overload 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.2 Lvalue-to-rvalue conversion [conv.lval]"), [array-to-pointer](conv.array "7.3.3 Array-to-pointer conversion [conv.array]"),
|
||||
and [function-to-pointer](conv.func "7.3.4 Function-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.7 Initialization 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.5 Temporary materialization conversion")) is applied,
|
||||
considering the type of the prvalue to be
|
||||
â*cv1* T4â ([[conv.qual]](conv.qual "7.3.6 Qualification 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.5 Initializers"), [[over.match.copy]](over.match.copy "12.2.2.5 Copy-initialization of class by user-defined conversion"), [[over.match.conv]](over.match.conv "12.2.2.6 Initialization 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.4 References [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.7 Temporary 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.3 Conversion functions")) returning a reference type[.](#footnote-80.sentence-1)
|
||||
61
cppdraft/dcl/init/string.md
Normal file
61
cppdraft/dcl/init/string.md
Normal 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.2 Fundamental 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.5 String literals [lex.string]") enclosed in
|
||||
braces ([[lex.string]](lex.string "5.13.5 String 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.5 String literals [lex.string]") initialize the elements of the array,
|
||||
with an integral conversion ([[conv.integral]](conv.integral "7.3.9 Integral 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.5 String 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.5 Initializers"))[.](#3.sentence-1)
|
||||
112
cppdraft/dcl/inline.md
Normal file
112
cppdraft/dcl/inline.md
Normal 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.6 Functions"), [[class.mfct]](class.mfct "11.4.2 Member functions"), [[class.friend]](class.friend "11.8.4 Friends"))
|
||||
with an inline specifier declares an[*inline function*](#def:function,inline "9.2.8 The 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.7 Program 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.8 The 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.3 One-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.6 The 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.2 Member functions"), [[class.friend]](class.friend "11.8.4 Friends"))[.](#7.sentence-3)
|
||||
|
||||
â *end note*]
|
||||
180
cppdraft/dcl/link.md
Normal file
180
cppdraft/dcl/link.md
Normal 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.12 Linkage 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.7 Program and linkage [basic.link]") between C++ and non-C++ code fragments can
|
||||
be achieved using a [*linkage-specification*](#nt:linkage-specification "9.12 Linkage specifications [dcl.link]"):
|
||||
|
||||
[linkage-specification:](#nt:linkage-specification "9.12 Linkage specifications [dcl.link]")
|
||||
extern [*unevaluated-string*](lex.string.uneval#nt:unevaluated-string "5.13.6 Unevaluated strings [lex.string.uneval]") { [*declaration-seq*](dcl.pre#nt:declaration-seq "9.1 Preamble [dcl.pre]")opt }
|
||||
extern [*unevaluated-string*](lex.string.uneval#nt:unevaluated-string "5.13.6 Unevaluated strings [lex.string.uneval]") [*name-declaration*](dcl.pre#nt:name-declaration "9.1 Preamble [dcl.pre]")
|
||||
|
||||
The [*unevaluated-string*](lex.string.uneval#nt:unevaluated-string "5.13.6 Unevaluated 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.2 Universal character names [lex.universal.char]")*s* have been replaced ([[lex.string.uneval]](lex.string.uneval "5.13.6 Unevaluated strings"))[.](#2.sentence-3)
|
||||
|
||||
â *end note*]
|
||||
|
||||
This document specifies the semantics for the[*unevaluated-string*](lex.string.uneval#nt:unevaluated-string "5.13.6 Unevaluated strings [lex.string.uneval]")*s* "C" and "C++"[.](#2.sentence-4)
|
||||
|
||||
Use of an [*unevaluated-string*](lex.string.uneval#nt:unevaluated-string "5.13.6 Unevaluated 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.12 Linkage 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.3 Import 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.12 Linkage specifications [dcl.link]") shall inhabit a namespace scope[.](#5.sentence-4)
|
||||
|
||||
In a [*linkage-specification*](#nt:linkage-specification "9.12 Linkage 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.1 Preamble [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.12 Linkage specifications [dcl.link]") is treated as if it contains theextern specifier ([[dcl.stc]](dcl.stc "9.2.2 Storage 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.2 Storage 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
1520
cppdraft/dcl/meaning.md
Normal file
File diff suppressed because it is too large
Load Diff
185
cppdraft/dcl/meaning/general.md
Normal file
185
cppdraft/dcl/meaning/general.md
Normal 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.1 General [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.2 Unqualified names [expr.prim.id.unqual]") occurring in a [*declarator-id*](dcl.decl.general#nt:declarator-id "9.3.1 General [dcl.decl.general]") is a [*template-id*](temp.names#nt:template-id "13.3 Names of template specializations [temp.names]"),
|
||||
the declarator shall appear in the [*declaration*](dcl.pre#nt:declaration "9.1 Preamble [dcl.pre]") of a[*template-declaration*](temp.pre#nt:template-declaration "13.1 Preamble [temp.pre]") ([[temp.decls]](temp.decls "13.7 Template declarations")),[*explicit-specialization*](temp.expl.spec#nt:explicit-specialization "13.9.4 Explicit specialization [temp.expl.spec]") ([[temp.expl.spec]](temp.expl.spec "13.9.4 Explicit specialization")), or[*explicit-instantiation*](temp.explicit#nt:explicit-instantiation "13.9.3 Explicit instantiation [temp.explicit]") ([[temp.explicit]](temp.explicit "13.9.3 Explicit instantiation"))[.](#1.sentence-2)
|
||||
|
||||
[*Note [1](#note-1)*:
|
||||
|
||||
An [*unqualified-id*](expr.prim.id.unqual#nt:unqualified-id "7.5.5.2 Unqualified names [expr.prim.id.unqual]") that is not an [*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]") is used to declare
|
||||
certain functions ([[class.conv.fct]](class.conv.fct "11.4.8.3 Conversion functions"), [[class.dtor]](class.dtor "11.4.7 Destructors"), [[over.oper]](over.oper "12.4 Overloaded operators"), [[over.literal]](over.literal "12.6 User-defined literals"))[.](#1.sentence-3)
|
||||
|
||||
â *end note*]
|
||||
|
||||
The optional [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]") following a [*declarator-id*](dcl.decl.general#nt:declarator-id "9.3.1 General [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.1 General [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.1 General [expr.prim.id.general]") E in
|
||||
the [*declarator-id*](dcl.decl.general#nt:declarator-id "9.3.1 General [dcl.decl.general]") of the [*declarator*](dcl.decl.general#nt:declarator "9.3.1 General [dcl.decl.general]") is
|
||||
a [*qualified-id*](expr.prim.id.qual#nt:qualified-id "7.5.5.3 Qualified names [expr.prim.id.qual]") or a [*template-id*](temp.names#nt:template-id "13.3 Names 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.2 Unqualified names [expr.prim.id.unqual]") in E is a [*template-id*](temp.names#nt:template-id "13.3 Names 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.1 General [dcl.decl.general]") corresponds ([[basic.scope.scope]](basic.scope.scope "6.4.1 General")) 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.7 Deducing 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.1 General [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.1 General [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.7 Reachability")) 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.1 General [expr.prim.id.general]") in
|
||||
the [*declarator-id*](dcl.decl.general#nt:declarator-id "9.3.1 General [dcl.decl.general]") of the [*declarator*](dcl.decl.general#nt:declarator "9.3.1 General [dcl.decl.general]") is
|
||||
a [*qualified-id*](expr.prim.id.qual#nt:qualified-id "7.5.5.3 Qualified names [expr.prim.id.qual]") Q,
|
||||
let S be its lookup context ([[basic.lookup.qual]](basic.lookup.qual "6.5.5 Qualified 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.1 General [dcl.decl.general]")[.](#3.2.sentence-1)
|
||||
|
||||
- [(3.3)](#3.3)
|
||||
|
||||
If the [*declarator*](dcl.decl.general#nt:declarator "9.3.1 General [dcl.decl.general]") declares
|
||||
an explicit instantiation or a partial or explicit specialization,
|
||||
the [*declarator*](dcl.decl.general#nt:declarator "9.3.1 General [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.1 General [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.7 Deducing 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.1 General [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.1 General [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.1 General [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.6 Functions")) or uses the extern specifier,
|
||||
the declaration shall not be attached to a named module ([[module.unit]](module.unit "10.1 Module 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.3 Qualified 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.3 Function specifiers [dcl.fct.spec]") applies directly to each [*declarator-id*](dcl.decl.general#nt:declarator-id "9.3.1 General [dcl.decl.general]") in a declaration;
|
||||
the type specified for each [*declarator-id*](dcl.decl.general#nt:declarator-id "9.3.1 General [dcl.decl.general]") depends on
|
||||
both the [*decl-specifier-seq*](dcl.spec.general#nt:decl-specifier-seq "9.2.1 General [dcl.spec.general]") and its [*declarator*](dcl.decl.general#nt:declarator "9.3.1 General [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.1 General [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.1 Attribute syntax and semantics [dcl.attr.grammar]")opt[*decl-specifier-seq*](dcl.spec.general#nt:decl-specifier-seq "9.2.1 General [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.1 General [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.1 General [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.1 General [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.3 Simple 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.1 Attribute syntax and semantics [dcl.attr.grammar]")optTD whereD is an unadorned [*declarator-id*](dcl.decl.general#nt:declarator-id "9.3.1 General [dcl.decl.general]"),
|
||||
the type of the declared entity is
|
||||
âTâ[.](#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.1 General [dcl.decl.general]") is the same as that of the contained[*declarator-id*](dcl.decl.general#nt:declarator-id "9.3.1 General [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.1 General [dcl.decl.general]"),
|
||||
but they can alter the binding of complex declarators[.](#8.sentence-2)
|
||||
79
cppdraft/dcl/mptr.md
Normal file
79
cppdraft/dcl/mptr.md
Normal 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.1 General [dcl.decl.general]") are
|
||||
those of its [*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3 Qualified 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.3 Qualified names [expr.prim.id.qual]") * [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]")opt [*cv-qualifier-seq*](dcl.decl.general#nt:cv-qualifier-seq "9.3.1 General [dcl.decl.general]")opt D1
|
||||
|
||||
and the[*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3 Qualified names [expr.prim.id.qual]") designates a class,
|
||||
and the type of the contained [*declarator-id*](dcl.decl.general#nt:declarator-id "9.3.1 General [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.1 General [dcl.decl.general]") inD is â*derived-declarator-type-list* [*cv-qualifier-seq*](dcl.decl.general#nt:cv-qualifier-seq "9.3.1 General [dcl.decl.general]") pointer to member of class[*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3 Qualified names [expr.prim.id.qual]") of typeTâ[.](#2.sentence-1)
|
||||
|
||||
The optional [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]") ([[dcl.attr.grammar]](dcl.attr.grammar "9.13.1 Attribute 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.3 Qualified 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.9 Static 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.2 Unary expressions") and [[expr.mptr.oper]](expr.mptr.oper "7.6.4 Pointer-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
79
cppdraft/dcl/name.md
Normal 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.2 Type names [dcl.name]") or [*new-type-id*](expr.new#nt:new-type-id "7.6.2.8 New [expr.new]") ([[expr.new]](expr.new "7.6.2.8 New")),
|
||||
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.2 Type names [dcl.name]")
|
||||
[*type-specifier-seq*](dcl.type.general#nt:type-specifier-seq "9.2.9.1 General [dcl.type.general]") [*abstract-declarator*](#nt:abstract-declarator "9.3.2 Type names [dcl.name]")opt
|
||||
|
||||
[defining-type-id:](#nt:defining-type-id "9.3.2 Type names [dcl.name]")
|
||||
[*defining-type-specifier-seq*](dcl.type.general#nt:defining-type-specifier-seq "9.2.9.1 General [dcl.type.general]") [*abstract-declarator*](#nt:abstract-declarator "9.3.2 Type names [dcl.name]")opt
|
||||
|
||||
[abstract-declarator:](#nt:abstract-declarator "9.3.2 Type names [dcl.name]")
|
||||
[*ptr-abstract-declarator*](#nt:ptr-abstract-declarator "9.3.2 Type names [dcl.name]")
|
||||
[*noptr-abstract-declarator*](#nt:noptr-abstract-declarator "9.3.2 Type names [dcl.name]")opt [*parameters-and-qualifiers*](dcl.decl.general#nt:parameters-and-qualifiers "9.3.1 General [dcl.decl.general]") [*trailing-return-type*](dcl.decl.general#nt:trailing-return-type "9.3.1 General [dcl.decl.general]")
|
||||
[*abstract-pack-declarator*](#nt:abstract-pack-declarator "9.3.2 Type names [dcl.name]")
|
||||
|
||||
[ptr-abstract-declarator:](#nt:ptr-abstract-declarator "9.3.2 Type names [dcl.name]")
|
||||
[*noptr-abstract-declarator*](#nt:noptr-abstract-declarator "9.3.2 Type names [dcl.name]")
|
||||
[*ptr-operator*](dcl.decl.general#nt:ptr-operator "9.3.1 General [dcl.decl.general]") [*ptr-abstract-declarator*](#nt:ptr-abstract-declarator "9.3.2 Type names [dcl.name]")opt
|
||||
|
||||
[noptr-abstract-declarator:](#nt:noptr-abstract-declarator "9.3.2 Type names [dcl.name]")
|
||||
[*noptr-abstract-declarator*](#nt:noptr-abstract-declarator "9.3.2 Type names [dcl.name]")opt [*parameters-and-qualifiers*](dcl.decl.general#nt:parameters-and-qualifiers "9.3.1 General [dcl.decl.general]")
|
||||
[*noptr-abstract-declarator*](#nt:noptr-abstract-declarator "9.3.2 Type names [dcl.name]")opt [ [*constant-expression*](expr.const#nt:constant-expression "7.7 Constant expressions [expr.const]")opt ] [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]")opt
|
||||
( [*ptr-abstract-declarator*](#nt:ptr-abstract-declarator "9.3.2 Type names [dcl.name]") )
|
||||
|
||||
[abstract-pack-declarator:](#nt:abstract-pack-declarator "9.3.2 Type names [dcl.name]")
|
||||
[*noptr-abstract-pack-declarator*](#nt:noptr-abstract-pack-declarator "9.3.2 Type names [dcl.name]")
|
||||
[*ptr-operator*](dcl.decl.general#nt:ptr-operator "9.3.1 General [dcl.decl.general]") [*abstract-pack-declarator*](#nt:abstract-pack-declarator "9.3.2 Type names [dcl.name]")
|
||||
|
||||
[noptr-abstract-pack-declarator:](#nt:noptr-abstract-pack-declarator "9.3.2 Type names [dcl.name]")
|
||||
[*noptr-abstract-pack-declarator*](#nt:noptr-abstract-pack-declarator "9.3.2 Type names [dcl.name]") [*parameters-and-qualifiers*](dcl.decl.general#nt:parameters-and-qualifiers "9.3.1 General [dcl.decl.general]")
|
||||
...
|
||||
|
||||
It is possible to identify uniquely the location in the[*abstract-declarator*](#nt:abstract-declarator "9.3.2 Type 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.4 The typedef specifier [dcl.typedef]"),
|
||||
which is introduced by a typedef declaration
|
||||
or [*alias-declaration*](dcl.pre#nt:alias-declaration "9.1 Preamble [dcl.pre]") ([[dcl.typedef]](dcl.typedef "9.2.4 The typedef specifier"))[.](#2.sentence-1)
|
||||
|
||||
â *end note*]
|
||||
390
cppdraft/dcl/pre.md
Normal file
390
cppdraft/dcl/pre.md
Normal 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.1 Preamble [dcl.pre]")
|
||||
[*declaration*](#nt:declaration "9.1 Preamble [dcl.pre]") [*declaration-seq*](#nt:declaration-seq "9.1 Preamble [dcl.pre]")opt
|
||||
|
||||
[declaration:](#nt:declaration "9.1 Preamble [dcl.pre]")
|
||||
[*name-declaration*](#nt:name-declaration "9.1 Preamble [dcl.pre]")
|
||||
[*special-declaration*](#nt:special-declaration "9.1 Preamble [dcl.pre]")
|
||||
|
||||
[name-declaration:](#nt:name-declaration "9.1 Preamble [dcl.pre]")
|
||||
[*block-declaration*](#nt:block-declaration "9.1 Preamble [dcl.pre]")
|
||||
[*nodeclspec-function-declaration*](#nt:nodeclspec-function-declaration "9.1 Preamble [dcl.pre]")
|
||||
[*function-definition*](dcl.fct.def.general#nt:function-definition "9.6.1 General [dcl.fct.def.general]")
|
||||
[*friend-type-declaration*](class.mem.general#nt:friend-type-declaration "11.4.1 General [class.mem.general]")
|
||||
[*template-declaration*](temp.pre#nt:template-declaration "13.1 Preamble [temp.pre]")
|
||||
[*deduction-guide*](temp.deduct.guide#nt:deduction-guide "13.7.2.3 Deduction guides [temp.deduct.guide]")
|
||||
[*linkage-specification*](dcl.link#nt:linkage-specification "9.12 Linkage specifications [dcl.link]")
|
||||
[*namespace-definition*](namespace.def.general#nt:namespace-definition "9.9.2.1 General [namespace.def.general]")
|
||||
[*empty-declaration*](#nt:empty-declaration "9.1 Preamble [dcl.pre]")
|
||||
[*attribute-declaration*](#nt:attribute-declaration "9.1 Preamble [dcl.pre]")
|
||||
[*module-import-declaration*](module.import#nt:module-import-declaration "10.3 Import declaration [module.import]")
|
||||
|
||||
[special-declaration:](#nt:special-declaration "9.1 Preamble [dcl.pre]")
|
||||
[*explicit-instantiation*](temp.explicit#nt:explicit-instantiation "13.9.3 Explicit instantiation [temp.explicit]")
|
||||
[*explicit-specialization*](temp.expl.spec#nt:explicit-specialization "13.9.4 Explicit specialization [temp.expl.spec]")
|
||||
[*export-declaration*](module.interface#nt:export-declaration "10.2 Export declaration [module.interface]")
|
||||
|
||||
[block-declaration:](#nt:block-declaration "9.1 Preamble [dcl.pre]")
|
||||
[*simple-declaration*](#nt:simple-declaration "9.1 Preamble [dcl.pre]")
|
||||
[*asm-declaration*](dcl.asm#nt:asm-declaration "9.11 The asm declaration [dcl.asm]")
|
||||
[*namespace-alias-definition*](namespace.alias#nt:namespace-alias-definition "9.9.3 Namespace alias [namespace.alias]")
|
||||
[*using-declaration*](namespace.udecl#nt:using-declaration "9.10 The using declaration [namespace.udecl]")
|
||||
[*using-enum-declaration*](enum.udecl#nt:using-enum-declaration "9.8.2 The using enum declaration [enum.udecl]")
|
||||
[*using-directive*](namespace.udir#nt:using-directive "9.9.4 Using namespace directive [namespace.udir]")
|
||||
[*static_assert-declaration*](#nt:static_assert-declaration "9.1 Preamble [dcl.pre]")
|
||||
[*consteval-block-declaration*](#nt:consteval-block-declaration "9.1 Preamble [dcl.pre]")
|
||||
[*alias-declaration*](#nt:alias-declaration "9.1 Preamble [dcl.pre]")
|
||||
[*opaque-enum-declaration*](dcl.enum#nt:opaque-enum-declaration "9.8.1 Enumeration declarations [dcl.enum]")
|
||||
|
||||
[nodeclspec-function-declaration:](#nt:nodeclspec-function-declaration "9.1 Preamble [dcl.pre]")
|
||||
[*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]")opt [*declarator*](dcl.decl.general#nt:declarator "9.3.1 General [dcl.decl.general]") ;
|
||||
|
||||
[alias-declaration:](#nt:alias-declaration "9.1 Preamble [dcl.pre]")
|
||||
using [*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]") [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]")opt = [*defining-type-id*](dcl.name#nt:defining-type-id "9.3.2 Type names [dcl.name]") ;
|
||||
|
||||
[sb-identifier:](#nt:sb-identifier "9.1 Preamble [dcl.pre]")
|
||||
...opt [*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]") [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]")opt
|
||||
|
||||
[sb-identifier-list:](#nt:sb-identifier-list "9.1 Preamble [dcl.pre]")
|
||||
[*sb-identifier*](#nt:sb-identifier "9.1 Preamble [dcl.pre]")
|
||||
[*sb-identifier-list*](#nt:sb-identifier-list "9.1 Preamble [dcl.pre]") , [*sb-identifier*](#nt:sb-identifier "9.1 Preamble [dcl.pre]")
|
||||
|
||||
[structured-binding-declaration:](#nt:structured-binding-declaration "9.1 Preamble [dcl.pre]")
|
||||
[*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]")opt [*decl-specifier-seq*](dcl.spec.general#nt:decl-specifier-seq "9.2.1 General [dcl.spec.general]") [*ref-qualifier*](dcl.decl.general#nt:ref-qualifier "9.3.1 General [dcl.decl.general]")opt [ [*sb-identifier-list*](#nt:sb-identifier-list "9.1 Preamble [dcl.pre]") ]
|
||||
|
||||
[simple-declaration:](#nt:simple-declaration "9.1 Preamble [dcl.pre]")
|
||||
[*decl-specifier-seq*](dcl.spec.general#nt:decl-specifier-seq "9.2.1 General [dcl.spec.general]") [*init-declarator-list*](dcl.decl.general#nt:init-declarator-list "9.3.1 General [dcl.decl.general]")opt ;
|
||||
[*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]") [*decl-specifier-seq*](dcl.spec.general#nt:decl-specifier-seq "9.2.1 General [dcl.spec.general]") [*init-declarator-list*](dcl.decl.general#nt:init-declarator-list "9.3.1 General [dcl.decl.general]") ;
|
||||
[*structured-binding-declaration*](#nt:structured-binding-declaration "9.1 Preamble [dcl.pre]") [*initializer*](dcl.init.general#nt:initializer "9.5.1 General [dcl.init.general]") ;
|
||||
|
||||
[static_assert-message:](#nt:static_assert-message "9.1 Preamble [dcl.pre]")
|
||||
[*unevaluated-string*](lex.string.uneval#nt:unevaluated-string "5.13.6 Unevaluated strings [lex.string.uneval]")
|
||||
[*constant-expression*](expr.const#nt:constant-expression "7.7 Constant expressions [expr.const]")
|
||||
|
||||
[static_assert-declaration:](#nt:static_assert-declaration "9.1 Preamble [dcl.pre]")
|
||||
static_assert ( [*constant-expression*](expr.const#nt:constant-expression "7.7 Constant expressions [expr.const]") ) ;
|
||||
static_assert ( [*constant-expression*](expr.const#nt:constant-expression "7.7 Constant expressions [expr.const]") , [*static_assert-message*](#nt:static_assert-message "9.1 Preamble [dcl.pre]") ) ;
|
||||
|
||||
[consteval-block-declaration:](#nt:consteval-block-declaration "9.1 Preamble [dcl.pre]")
|
||||
consteval [*compound-statement*](stmt.block#nt:compound-statement "8.4 Compound statement or block [stmt.block]")
|
||||
|
||||
[empty-declaration:](#nt:empty-declaration "9.1 Preamble [dcl.pre]")
|
||||
;
|
||||
|
||||
[attribute-declaration:](#nt:attribute-declaration "9.1 Preamble [dcl.pre]")
|
||||
[*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]") ;
|
||||
|
||||
[*Note [1](#note-1)*:
|
||||
|
||||
[*asm-declaration*](dcl.asm#nt:asm-declaration "9.11 The asm declaration [dcl.asm]")*s* are described in [[dcl.asm]](dcl.asm "9.11 The asm declaration"), and[*linkage-specification*](dcl.link#nt:linkage-specification "9.12 Linkage specifications [dcl.link]")*s* are described in [[dcl.link]](dcl.link "9.12 Linkage specifications");[*function-definition*](dcl.fct.def.general#nt:function-definition "9.6.1 General [dcl.fct.def.general]")*s* are described in [[dcl.fct.def]](dcl.fct.def "9.6 Function definitions") and[*template-declaration*](temp.pre#nt:template-declaration "13.1 Preamble [temp.pre]")*s* and[*deduction-guide*](temp.deduct.guide#nt:deduction-guide "13.7.2.3 Deduction guides [temp.deduct.guide]")*s* are described in [[temp.deduct.guide]](temp.deduct.guide "13.7.2.3 Deduction guides");[*namespace-definition*](namespace.def.general#nt:namespace-definition "9.9.2.1 General [namespace.def.general]")*s* are described in [[namespace.def]](namespace.def "9.9.2 Namespace definition"),[*using-declaration*](namespace.udecl#nt:using-declaration "9.10 The using declaration [namespace.udecl]")*s* are described in [[namespace.udecl]](namespace.udecl "9.10 The using declaration") and[*using-directive*](namespace.udir#nt:using-directive "9.9.4 Using namespace directive [namespace.udir]")*s* are described in [[namespace.udir]](namespace.udir "9.9.4 Using 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.1 General"))[.](#2.sentence-1)
|
||||
|
||||
Unless otherwise stated, utterances in[[dcl]](dcl "9 Declarations") 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.1 Preamble [dcl.pre]") matches
|
||||
the syntactic requirements of [*friend-type-declaration*](class.mem.general#nt:friend-type-declaration "11.4.1 General [class.mem.general]"),
|
||||
it is a [*friend-type-declaration*](class.mem.general#nt:friend-type-declaration "11.4.1 General [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.1 Preamble [dcl.pre]") or[*nodeclspec-function-declaration*](#nt:nodeclspec-function-declaration "9.1 Preamble [dcl.pre]") of the form
|
||||
|
||||
[*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]")opt [*decl-specifier-seq*](dcl.spec.general#nt:decl-specifier-seq "9.2.1 General [dcl.spec.general]")opt [*init-declarator-list*](dcl.decl.general#nt:init-declarator-list "9.3.1 General [dcl.decl.general]")opt ;
|
||||
|
||||
is divided into three parts[.](#4.sentence-1)
|
||||
|
||||
Attributes are described in [[dcl.attr]](dcl.attr "9.13 Attributes")[.](#4.sentence-2)
|
||||
|
||||
[*decl-specifier*](dcl.spec.general#nt:decl-specifier "9.2.1 General [dcl.spec.general]")*s*, the principal components of
|
||||
a [*decl-specifier-seq*](dcl.spec.general#nt:decl-specifier-seq "9.2.1 General [dcl.spec.general]"), are described in [[dcl.spec]](dcl.spec "9.2 Specifiers")[.](#4.sentence-3)
|
||||
|
||||
[*declarator*](dcl.decl.general#nt:declarator "9.3.1 General [dcl.decl.general]")*s*, the components of an[*init-declarator-list*](dcl.decl.general#nt:init-declarator-list "9.3.1 General [dcl.decl.general]"), are described in [[dcl.decl]](dcl.decl "9.3 Declarators")[.](#4.sentence-4)
|
||||
|
||||
The [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]") appertains to each of the entities declared by
|
||||
the [*declarator*](dcl.decl.general#nt:declarator "9.3.1 General [dcl.decl.general]")*s* of the [*init-declarator-list*](dcl.decl.general#nt:init-declarator-list "9.3.1 General [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.1 General [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.1 General [dcl.decl.general]") is a name, the[*init-declarator*](dcl.decl.general#nt:init-declarator "9.3.1 General [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.1 General [dcl.decl.general]") is
|
||||
a [*qualified-id*](expr.prim.id.qual#nt:qualified-id "7.5.5.3 Qualified names [expr.prim.id.qual]") or
|
||||
names a destructor or
|
||||
its [*unqualified-id*](expr.prim.id.unqual#nt:unqualified-id "7.5.5.2 Unqualified names [expr.prim.id.unqual]") is a [*template-id*](temp.names#nt:template-id "13.3 Names 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.1 General [dcl.type.general]")*s* ([[dcl.type]](dcl.type "9.2.9 Type specifiers")) in
|
||||
the [*decl-specifier-seq*](dcl.spec.general#nt:decl-specifier-seq "9.2.1 General [dcl.spec.general]") and
|
||||
the recursive [*declarator*](dcl.decl.general#nt:declarator "9.3.1 General [dcl.decl.general]") structure
|
||||
describe a type ([[dcl.meaning]](dcl.meaning "9.3.4 Meaning of declarators")),
|
||||
which is then associated with the [*declarator-id*](dcl.decl.general#nt:declarator-id "9.3.1 General [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.1 Preamble [dcl.pre]"), the optional[*init-declarator-list*](dcl.decl.general#nt:init-declarator-list "9.3.1 General [dcl.decl.general]") can be omitted only when declaring a
|
||||
class ([[class.pre]](class.pre "11.1 Preamble")) or enumeration ([[dcl.enum]](dcl.enum "9.8.1 Enumeration declarations")), that is,
|
||||
when the [*decl-specifier-seq*](dcl.spec.general#nt:decl-specifier-seq "9.2.1 General [dcl.spec.general]") contains either a[*class-specifier*](class.pre#nt:class-specifier "11.1 Preamble [class.pre]"), an [*elaborated-type-specifier*](dcl.type.elab#nt:elaborated-type-specifier "9.2.9.5 Elaborated type specifiers [dcl.type.elab]") with
|
||||
a [*class-key*](class.pre#nt:class-key "11.1 Preamble [class.pre]") ([[class.name]](class.name "11.3 Class names")), or an[*enum-specifier*](dcl.enum#nt:enum-specifier "9.8.1 Enumeration declarations [dcl.enum]")[.](#6.sentence-1)
|
||||
|
||||
In these cases and whenever a[*class-specifier*](class.pre#nt:class-specifier "11.1 Preamble [class.pre]") or [*enum-specifier*](dcl.enum#nt:enum-specifier "9.8.1 Enumeration declarations [dcl.enum]") is present in
|
||||
the [*decl-specifier-seq*](dcl.spec.general#nt:decl-specifier-seq "9.2.1 General [dcl.spec.general]"), the identifiers in these specifiers
|
||||
are also declared (as[*class-name*](class.pre#nt:class-name "11.1 Preamble [class.pre]")*s*, [*enum-name*](dcl.enum#nt:enum-name "9.8.1 Enumeration declarations [dcl.enum]")*s*, or[*enumerator*](dcl.enum#nt:enumerator "9.8.1 Enumeration 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.1 General [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.1 Preamble [dcl.pre]") or a [*condition*](stmt.pre#nt:condition "8.1 Preamble [stmt.pre]") with a [*structured-binding-declaration*](#nt:structured-binding-declaration "9.1 Preamble [dcl.pre]") is called
|
||||
a [*structured binding declaration*](#def:structured_binding_declaration "9.1 Preamble [dcl.pre]") ([[dcl.struct.bind]](dcl.struct.bind "9.7 Structured binding declarations"))[.](#7.sentence-1)
|
||||
|
||||
Each [*decl-specifier*](dcl.spec.general#nt:decl-specifier "9.2.1 General [dcl.spec.general]") in the [*decl-specifier-seq*](dcl.spec.general#nt:decl-specifier-seq "9.2.1 General [dcl.spec.general]") shall beconstexpr,constinit,static,thread_local,auto ([[dcl.spec.auto]](dcl.spec.auto "9.2.9.7 Placeholder type specifiers")), or
|
||||
a [*cv-qualifier*](dcl.decl.general#nt:cv-qualifier "9.3.1 General [dcl.decl.general]")[.](#7.sentence-2)
|
||||
|
||||
The declaration shall contain at most one [*sb-identifier*](#nt:sb-identifier "9.1 Preamble [dcl.pre]") whose [*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]") is preceded by an ellipsis[.](#7.sentence-3)
|
||||
|
||||
If the declaration contains any such [*sb-identifier*](#nt:sb-identifier "9.1 Preamble [dcl.pre]"),
|
||||
it shall declare a templated entity ([[temp.pre]](temp.pre "13.1 Preamble"))[.](#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.1 General [dcl.spec.auto.general]")// not permitted for structured bindings â *end example*]
|
||||
|
||||
The [*initializer*](dcl.init.general#nt:initializer "9.5.1 General [dcl.init.general]") shall be
|
||||
of the form â= [*assignment-expression*](expr.assign#nt:assignment-expression "7.6.19 Assignment and compound assignment operators [expr.assign]")â,
|
||||
of the form â{ [*assignment-expression*](expr.assign#nt:assignment-expression "7.6.19 Assignment and compound assignment operators [expr.assign]") }â,
|
||||
or
|
||||
of the form â( [*assignment-expression*](expr.assign#nt:assignment-expression "7.6.19 Assignment and compound assignment operators [expr.assign]") )â[.](#7.sentence-5)
|
||||
|
||||
If the [*structured-binding-declaration*](#nt:structured-binding-declaration "9.1 Preamble [dcl.pre]") appears as
|
||||
a [*condition*](stmt.pre#nt:condition "8.1 Preamble [stmt.pre]"),
|
||||
the [*assignment-expression*](expr.assign#nt:assignment-expression "7.6.19 Assignment 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.19 Assignment 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.1 General [dcl.spec.general]") contains the typedef specifier, the declaration is a [*typedef declaration*](#def:declaration,typedef "9.1 Preamble [dcl.pre]") and each [*declarator-id*](dcl.decl.general#nt:declarator-id "9.3.1 General [dcl.decl.general]") is declared to be a [*typedef-name*](dcl.typedef#nt:typedef-name "9.2.4 The typedef specifier [dcl.typedef]") ([[dcl.typedef]](dcl.typedef "9.2.4 The typedef specifier"))[.](#8.sentence-1)
|
||||
|
||||
[*Note [4](#note-4)*:
|
||||
|
||||
Such a [*declarator-id*](dcl.decl.general#nt:declarator-id "9.3.1 General [dcl.decl.general]") is
|
||||
an [*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]") ([[class.conv.fct]](class.conv.fct "11.4.8.3 Conversion functions"))[.](#8.sentence-2)
|
||||
|
||||
â *end note*]
|
||||
|
||||
Otherwise, if the type associated with a [*declarator-id*](dcl.decl.general#nt:declarator-id "9.3.1 General [dcl.decl.general]") is a function type ([[dcl.fct]](dcl.fct "9.3.4.6 Functions")),
|
||||
the declaration is a [*function declaration*](#def:declaration,function "9.1 Preamble [dcl.pre]")[.](#8.sentence-3)
|
||||
|
||||
Otherwise, if the type associated with a [*declarator-id*](dcl.decl.general#nt:declarator-id "9.3.1 General [dcl.decl.general]") is an object or reference type, the declaration is
|
||||
an [*object declaration*](#def:declaration,object "9.1 Preamble [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.5 Initializers")) 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.1 Preamble [dcl.pre]") are added to a function declaration to make a[*function-definition*](dcl.fct.def.general#nt:function-definition "9.6.1 General [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.1 General [dcl.fct.def.general]") ([[dcl.fct.def.general]](dcl.fct.def.general "9.6.1 General"))
|
||||
if the type of the [*declarator-id*](dcl.decl.general#nt:declarator-id "9.3.1 General [dcl.decl.general]") ([[dcl.meaning.general]](dcl.meaning.general "9.3.4.1 General"))
|
||||
is a function type, and
|
||||
is otherwise
|
||||
treated as a [*brace-or-equal-initializer*](dcl.init.general#nt:brace-or-equal-initializer "9.5.1 General [dcl.init.general]") ([[dcl.init.general]](dcl.init.general "9.5.1 General"))[.](#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.1 General")[.](#10.sentence-3)
|
||||
|
||||
The function type of a function definition
|
||||
cannot be specified with a [*typedef-name*](dcl.typedef#nt:typedef-name "9.2.4 The typedef specifier [dcl.typedef]") ([[dcl.fct]](dcl.fct "9.3.4.6 Functions"))[.](#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.1 Preamble [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.2 Member functions")), a [*nodeclspec-function-declaration*](#nt:nodeclspec-function-declaration "9.1 Preamble [dcl.pre]") can only be used in a [*template-declaration*](temp.pre#nt:template-declaration "13.1 Preamble [temp.pre]") ([[temp.pre]](temp.pre "13.1 Preamble")),[*explicit-instantiation*](temp.explicit#nt:explicit-instantiation "13.9.3 Explicit instantiation [temp.explicit]") ([[temp.explicit]](temp.explicit "13.9.3 Explicit instantiation")), or[*explicit-specialization*](temp.expl.spec#nt:explicit-specialization "13.9.4 Explicit specialization [temp.expl.spec]") ([[temp.expl.spec]](temp.expl.spec "13.9.4 Explicit 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.1 Preamble [dcl.pre]") matches the syntactic requirements of [*unevaluated-string*](lex.string.uneval#nt:unevaluated-string "5.13.6 Unevaluated strings [lex.string.uneval]"),
|
||||
it is an [*unevaluated-string*](lex.string.uneval#nt:unevaluated-string "5.13.6 Unevaluated strings [lex.string.uneval]") and
|
||||
the text of the [*static_assert-message*](#nt:static_assert-message "9.1 Preamble [dcl.pre]") is
|
||||
the text of the [*unevaluated-string*](lex.string.uneval#nt:unevaluated-string "5.13.6 Unevaluated strings [lex.string.uneval]")[.](#12.sentence-1)
|
||||
|
||||
Otherwise, a [*static_assert-message*](#nt:static_assert-message "9.1 Preamble [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.1 Preamble [dcl.pre]"),
|
||||
the [*constant-expression*](expr.const#nt:constant-expression "7.7 Constant expressions [expr.const]") E is contextually converted to bool and
|
||||
the converted expression shall be a constant expression ([[expr.const]](expr.const "7.7 Constant 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.1 Preamble [dcl.pre]") is
|
||||
an unevaluated operand ([[expr.context]](expr.context#term.unevaluated.operand "7.2.3 Context dependence"))[.](#13.sentence-2)
|
||||
|
||||
Otherwise,
|
||||
the [*static_assert-declaration*](#nt:static_assert-declaration "9.1 Preamble [dcl.pre]") [*fails*](#def:static_assert,failed "9.1 Preamble [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.1 Preamble [dcl.pre]") is
|
||||
a [*constant-expression*](expr.const#nt:constant-expression "7.7 Constant 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.1 Preamble [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.1 Character 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.1 Preamble [dcl.pre]") fails,
|
||||
the resulting diagnostic message should include the text of
|
||||
the [*static_assert-message*](#nt:static_assert-message "9.1 Preamble [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.1 Preamble [dcl.pre]") D,
|
||||
the expression E corresponding to D is: [] -> void static consteval [*compound-statement*](stmt.block#nt:compound-statement "8.4 Compound statement or block [stmt.block]") ()E shall be a constant expression ([[expr.const]](expr.const "7.7 Constant expressions"))[.](#15.sentence-1)
|
||||
|
||||
[*Note [7](#note-7)*:
|
||||
|
||||
The evaluation of the expression
|
||||
corresponding to a [*consteval-block-declaration*](#nt:consteval-block-declaration "9.1 Preamble [dcl.pre]") ([[lex.phases]](lex.phases "5.2 Phases 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.1 Preamble [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.1 Preamble [dcl.pre]") is implementation-defined[.](#17.sentence-1)
|
||||
79
cppdraft/dcl/ptr.md
Normal file
79
cppdraft/dcl/ptr.md
Normal 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.1 Attribute syntax and semantics [dcl.attr.grammar]")opt [*cv-qualifier-seq*](dcl.decl.general#nt:cv-qualifier-seq "9.3.1 General [dcl.decl.general]")opt D1
|
||||
|
||||
and the type of the contained [*declarator-id*](dcl.decl.general#nt:declarator-id "9.3.1 General [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.1 General [dcl.decl.general]") inD is â*derived-declarator-type-list* [*cv-qualifier-seq*](dcl.decl.general#nt:cv-qualifier-seq "9.3.1 General [dcl.decl.general]") pointer toTâ[.](#1.sentence-1)
|
||||
|
||||
The[*cv-qualifier*](dcl.decl.general#nt:cv-qualifier "9.3.1 General [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.1 Attribute syntax and semantics [dcl.attr.grammar]") ([[dcl.attr.grammar]](dcl.attr.grammar "9.13.1 Attribute 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.19 Assignment and compound assignment operators") and [[dcl.init]](dcl.init "9.5 Initializers")[.](#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.3 References")[.](#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.1 General [dcl.decl.general]")*s* or a [*ref-qualifier*](dcl.decl.general#nt:ref-qualifier "9.3.1 General [dcl.decl.general]");
|
||||
see [[dcl.fct]](dcl.fct "9.3.4.6 Functions")[.](#4.sentence-2)
|
||||
|
||||
Since the address of a bit-field ([[class.bit]](class.bit "11.4.10 Bit-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
168
cppdraft/dcl/ref.md
Normal 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.1 Attribute syntax and semantics [dcl.attr.grammar]")opt D1
|
||||
&& [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]")opt D1
|
||||
|
||||
and the type of the contained [*declarator-id*](dcl.decl.general#nt:declarator-id "9.3.1 General [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.1 General [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.1 Attribute 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.4 The typedef specifier [dcl.typedef]") ([[dcl.typedef]](dcl.typedef "9.2.4 The typedef specifier"), [[temp.param]](temp.param "13.2 Template parameters")) or[*decltype-specifier*](dcl.type.decltype#nt:decltype-specifier "9.2.9.6 Decltype specifiers [dcl.type.decltype]") ([[dcl.type.decltype]](dcl.type.decltype "9.2.9.6 Decltype 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.3 References [dcl.ref]"), and a reference type that
|
||||
is declared using && is called an[*rvalue reference*](#def:rvalue_reference "9.3.4.3 References [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.4 References")[.](#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.6 Storage 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.1 General [dcl.init.general]") ([[dcl.init.ref]](dcl.init.ref "9.5.4 References"))
|
||||
except when the declaration contains an explicitextern specifier ([[dcl.stc]](dcl.stc "9.2.2 Storage class specifiers")),
|
||||
is a class member ([[class.mem]](class.mem "11.4 Class members")) declaration within a class definition,
|
||||
or is the declaration of a parameter or a return type ([[dcl.fct]](dcl.fct "9.3.4.6 Functions")); see [[basic.def]](basic.def "6.2 Declarations 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.3 Function 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.1 Value 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.4 Lifetime"))[.](#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.2 Unary operators")[.](#6.sentence-4)
|
||||
|
||||
As described in [[class.bit]](class.bit "11.4.10 Bit-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.5 Names"), [[expr.ref]](expr.ref "7.6.1.5 Class member access")) that
|
||||
does not happen after ([[intro.races]](intro.races "6.10.2.2 Data 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.4 The typedef specifier [dcl.typedef]") ([[dcl.typedef]](dcl.typedef "9.2.4 The typedef specifier"), [[temp.param]](temp.param "13.2 Template parameters"))
|
||||
or a [*decltype-specifier*](dcl.type.decltype#nt:decltype-specifier "9.2.9.6 Decltype specifiers [dcl.type.decltype]") ([[dcl.type.decltype]](dcl.type.decltype "9.2.9.6 Decltype 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.1 General [dcl.decl.general]")*s* or a [*ref-qualifier*](dcl.decl.general#nt:ref-qualifier "9.3.1 General [dcl.decl.general]");
|
||||
see [[dcl.fct]](dcl.fct "9.3.4.6 Functions")[.](#8.sentence-1)
|
||||
|
||||
â *end note*]
|
||||
1814
cppdraft/dcl/spec.md
Normal file
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
412
cppdraft/dcl/spec/auto.md
Normal 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.1 General [dcl.spec.auto.general]")
|
||||
[*type-constraint*](temp.param#nt:type-constraint "13.2 Template parameters [temp.param]")opt auto
|
||||
[*type-constraint*](temp.param#nt:type-constraint "13.2 Template 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.1 General [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.6 Functions [dcl.fct]") of a
|
||||
|
||||
- [(2.1)](#general-2.1)
|
||||
|
||||
function declaration ([[dcl.fct]](dcl.fct "9.3.4.6 Functions")),
|
||||
|
||||
- [(2.2)](#general-2.2)
|
||||
|
||||
[*lambda-expression*](expr.prim.lambda.general#nt:lambda-expression "7.5.6.1 General [expr.prim.lambda.general]") ([[expr.prim.lambda]](expr.prim.lambda "7.5.6 Lambda expressions")), or
|
||||
|
||||
- [(2.3)](#general-2.3)
|
||||
|
||||
[*template-parameter*](temp.param#nt:template-parameter "13.2 Template parameters [temp.param]") ([[temp.param]](temp.param "13.2 Template parameters"))
|
||||
|
||||
can be declared using
|
||||
a [*placeholder-type-specifier*](#nt:placeholder-type-specifier "9.2.9.7.1 General [dcl.spec.auto.general]") of the form[*type-constraint*](temp.param#nt:type-constraint "13.2 Template 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.1 General [dcl.spec.general]")*s* in
|
||||
the [*decl-specifier-seq*](dcl.spec.general#nt:decl-specifier-seq "9.2.1 General [dcl.spec.general]") or
|
||||
as one of the [*type-specifier*](dcl.type.general#nt:type-specifier "9.2.9.1 General [dcl.type.general]")*s* in
|
||||
a [*trailing-return-type*](dcl.decl.general#nt:trailing-return-type "9.3.1 General [dcl.decl.general]") that specifies the type that replaces such
|
||||
a [*decl-specifier*](dcl.spec.general#nt:decl-specifier "9.2.1 General [dcl.spec.general]") (see below);
|
||||
the placeholder type
|
||||
is a [*generic parameter type placeholder*](#def:generic_parameter_type_placeholder "9.2.9.7.1 General [dcl.spec.auto.general]") of the
|
||||
function declaration,[*lambda-expression*](expr.prim.lambda.general#nt:lambda-expression "7.5.6.1 General [expr.prim.lambda.general]"), or[*template-parameter*](temp.param#nt:template-parameter "13.2 Template 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.6 Functions")) or
|
||||
the lambda is a generic lambda ([[expr.prim.lambda]](expr.prim.lambda "7.5.6 Lambda 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.1 General [dcl.spec.general]") for a function declarator
|
||||
that includes a [*trailing-return-type*](dcl.decl.general#nt:trailing-return-type "9.3.1 General [dcl.decl.general]") ([[dcl.fct]](dcl.fct "9.3.4.6 Functions"))[.](#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.1 General [dcl.spec.general]") or [*type-specifier-seq*](dcl.type.general#nt:type-specifier-seq "9.2.9.1 General [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.2 The 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.5 Initializers")) 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.1 General [dcl.spec.general]")*s* in the [*decl-specifier-seq*](dcl.spec.general#nt:decl-specifier-seq "9.2.1 General [dcl.spec.general]") or as one of the[*type-specifier*](dcl.type.general#nt:type-specifier "9.2.9.1 General [dcl.type.general]")*s* in a [*trailing-return-type*](dcl.decl.general#nt:trailing-return-type "9.3.1 General [dcl.decl.general]") that specifies the type that replaces such a [*decl-specifier*](dcl.spec.general#nt:decl-specifier "9.2.1 General [dcl.spec.general]");
|
||||
the [*decl-specifier-seq*](dcl.spec.general#nt:decl-specifier-seq "9.2.1 General [dcl.spec.general]") shall be followed by one or more[*declarator*](dcl.decl.general#nt:declarator "9.3.1 General [dcl.decl.general]")*s*,
|
||||
each of which shall
|
||||
be followed by a non-empty[*initializer*](dcl.init.general#nt:initializer "9.5.1 General [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.2 Storage 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.1 General [dcl.type.general]") can also be used to introduce
|
||||
a structured binding declaration ([[dcl.struct.bind]](dcl.struct.bind "9.7 Structured 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.1 General [dcl.type.general]") of
|
||||
the [*new-type-id*](expr.new#nt:new-type-id "7.6.2.8 New [expr.new]") or
|
||||
in the [*type-id*](dcl.name#nt:type-id "9.3.2 Type names [dcl.name]") of a[*new-expression*](expr.new#nt:new-expression "7.6.2.8 New [expr.new]") ([[expr.new]](expr.new "7.6.2.8 New"))[.](#general-6.sentence-1)
|
||||
|
||||
In such a [*type-id*](dcl.name#nt:type-id "9.3.2 Type names [dcl.name]"),
|
||||
the placeholder type shall appear
|
||||
as one of the [*type-specifier*](dcl.type.general#nt:type-specifier "9.2.9.1 General [dcl.type.general]")*s* in
|
||||
the [*type-specifier-seq*](dcl.type.general#nt:type-specifier-seq "9.2.9.1 General [dcl.type.general]") or
|
||||
as one of the [*type-specifier*](dcl.type.general#nt:type-specifier "9.2.9.1 General [dcl.type.general]")*s* in
|
||||
a [*trailing-return-type*](dcl.decl.general#nt:trailing-return-type "9.3.1 General [dcl.decl.general]") that specifies the type that replaces such a [*type-specifier*](dcl.type.general#nt:type-specifier "9.2.9.1 General [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.1 General [dcl.type.general]") can also be used
|
||||
as the [*simple-type-specifier*](dcl.type.simple#nt:simple-type-specifier "9.2.9.3 Simple type specifiers [dcl.type.simple]") in an explicit type conversion (functional notation) ([[expr.type.conv]](expr.type.conv "7.6.1.4 Explicit 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.1 General [dcl.decl.general]") contains more than one[*init-declarator*](dcl.decl.general#nt:init-declarator "9.3.1 General [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.2 Placeholder 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.5 Private 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.7 Program 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.3 One-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.2 Referring 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.3 Template 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.3 Virtual 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.4 Coroutine 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.3 Explicit 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.2 Placeholder 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.1 General [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.1 General [dcl.init.general]") ([[dcl.init.list]](dcl.init.list "9.5.5 List-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.20 Comma operator [expr.comma]") X that is not an [*assignment-expression*](expr.assign#nt:assignment-expression "7.6.19 Assignment 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.20 Comma operator")) is not
|
||||
an [*assignment-expression*](expr.assign#nt:assignment-expression "7.6.19 Assignment 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.2 Template parameters [temp.param]")opt decltype(auto) orcv [*type-constraint*](temp.param#nt:type-constraint "13.2 Template 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.1 General [dcl.init.general]") of the form = [*initializer-clause*](dcl.init.general#nt:initializer-clause "9.5.1 General [dcl.init.general]"),E is the [*initializer-clause*](dcl.init.general#nt:initializer-clause "9.5.1 General [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.1 General [dcl.init.general]"),
|
||||
it shall consist of a single brace-enclosed [*assignment-expression*](expr.assign#nt:assignment-expression "7.6.19 Assignment and compound assignment operators [expr.assign]") and E is the [*assignment-expression*](expr.assign#nt:assignment-expression "7.6.19 Assignment 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.1 General [expr.post.general]"),
|
||||
the [*expression-list*](expr.post.general#nt:expression-list "7.6.1.1 General [expr.post.general]") shall be
|
||||
a single [*assignment-expression*](expr.assign#nt:assignment-expression "7.6.19 Assignment and compound assignment operators [expr.assign]") and E is the [*assignment-expression*](expr.assign#nt:assignment-expression "7.6.19 Assignment 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.4 Explicit 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.1 General [dcl.init.general]"),
|
||||
it shall consist of a single brace-enclosed [*assignment-expression*](expr.assign#nt:assignment-expression "7.6.19 Assignment and compound assignment operators [expr.assign]") and E is the [*assignment-expression*](expr.assign#nt:assignment-expression "7.6.19 Assignment 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.1 General [expr.post.general]"),
|
||||
the [*expression-list*](expr.post.general#nt:expression-list "7.6.1.1 General [expr.post.general]") shall be
|
||||
a single [*assignment-expression*](expr.assign#nt:assignment-expression "7.6.19 Assignment and compound assignment operators [expr.assign]") and E is the [*assignment-expression*](expr.assign#nt:assignment-expression "7.6.19 Assignment 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.1 General [dcl.spec.auto.general]") is of the form[*type-constraint*](temp.param#nt:type-constraint "13.2 Template 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.1 General"))
|
||||
the [*placeholder-type-specifier*](#nt:placeholder-type-specifier "9.2.9.7.1 General [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.2 Template 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.2 Deducing 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.1 General [dcl.spec.auto.general]") is of the form[*type-constraint*](temp.param#nt:type-constraint "13.2 Template 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.6 Decltype 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.1 General [dcl.spec.auto.general]") with a [*type-constraint*](temp.param#nt:type-constraint "13.2 Template parameters [temp.param]"),
|
||||
the immediately-declared constraint ([[temp.param]](temp.param "13.2 Template parameters"))
|
||||
of the [*type-constraint*](temp.param#nt:type-constraint "13.2 Template parameters [temp.param]") for the type deduced for the placeholder
|
||||
shall be satisfied[.](#dcl.type.auto.deduct-5.sentence-1)
|
||||
264
cppdraft/dcl/spec/auto/general.md
Normal file
264
cppdraft/dcl/spec/auto/general.md
Normal 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.1 General [dcl.spec.auto.general]")
|
||||
[*type-constraint*](temp.param#nt:type-constraint "13.2 Template parameters [temp.param]")opt auto
|
||||
[*type-constraint*](temp.param#nt:type-constraint "13.2 Template 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.1 General [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.6 Functions [dcl.fct]") of a
|
||||
|
||||
- [(2.1)](#2.1)
|
||||
|
||||
function declaration ([[dcl.fct]](dcl.fct "9.3.4.6 Functions")),
|
||||
|
||||
- [(2.2)](#2.2)
|
||||
|
||||
[*lambda-expression*](expr.prim.lambda.general#nt:lambda-expression "7.5.6.1 General [expr.prim.lambda.general]") ([[expr.prim.lambda]](expr.prim.lambda "7.5.6 Lambda expressions")), or
|
||||
|
||||
- [(2.3)](#2.3)
|
||||
|
||||
[*template-parameter*](temp.param#nt:template-parameter "13.2 Template parameters [temp.param]") ([[temp.param]](temp.param "13.2 Template parameters"))
|
||||
|
||||
can be declared using
|
||||
a [*placeholder-type-specifier*](#nt:placeholder-type-specifier "9.2.9.7.1 General [dcl.spec.auto.general]") of the form[*type-constraint*](temp.param#nt:type-constraint "13.2 Template 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.1 General [dcl.spec.general]")*s* in
|
||||
the [*decl-specifier-seq*](dcl.spec.general#nt:decl-specifier-seq "9.2.1 General [dcl.spec.general]") or
|
||||
as one of the [*type-specifier*](dcl.type.general#nt:type-specifier "9.2.9.1 General [dcl.type.general]")*s* in
|
||||
a [*trailing-return-type*](dcl.decl.general#nt:trailing-return-type "9.3.1 General [dcl.decl.general]") that specifies the type that replaces such
|
||||
a [*decl-specifier*](dcl.spec.general#nt:decl-specifier "9.2.1 General [dcl.spec.general]") (see below);
|
||||
the placeholder type
|
||||
is a [*generic parameter type placeholder*](#def:generic_parameter_type_placeholder "9.2.9.7.1 General [dcl.spec.auto.general]") of the
|
||||
function declaration,[*lambda-expression*](expr.prim.lambda.general#nt:lambda-expression "7.5.6.1 General [expr.prim.lambda.general]"), or[*template-parameter*](temp.param#nt:template-parameter "13.2 Template 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.6 Functions")) or
|
||||
the lambda is a generic lambda ([[expr.prim.lambda]](expr.prim.lambda "7.5.6 Lambda 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.1 General [dcl.spec.general]") for a function declarator
|
||||
that includes a [*trailing-return-type*](dcl.decl.general#nt:trailing-return-type "9.3.1 General [dcl.decl.general]") ([[dcl.fct]](dcl.fct "9.3.4.6 Functions"))[.](#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.1 General [dcl.spec.general]") or [*type-specifier-seq*](dcl.type.general#nt:type-specifier-seq "9.2.9.1 General [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.2 The 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.5 Initializers")) 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.1 General [dcl.spec.general]")*s* in the [*decl-specifier-seq*](dcl.spec.general#nt:decl-specifier-seq "9.2.1 General [dcl.spec.general]") or as one of the[*type-specifier*](dcl.type.general#nt:type-specifier "9.2.9.1 General [dcl.type.general]")*s* in a [*trailing-return-type*](dcl.decl.general#nt:trailing-return-type "9.3.1 General [dcl.decl.general]") that specifies the type that replaces such a [*decl-specifier*](dcl.spec.general#nt:decl-specifier "9.2.1 General [dcl.spec.general]");
|
||||
the [*decl-specifier-seq*](dcl.spec.general#nt:decl-specifier-seq "9.2.1 General [dcl.spec.general]") shall be followed by one or more[*declarator*](dcl.decl.general#nt:declarator "9.3.1 General [dcl.decl.general]")*s*,
|
||||
each of which shall
|
||||
be followed by a non-empty[*initializer*](dcl.init.general#nt:initializer "9.5.1 General [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.2 Storage 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.1 General [dcl.type.general]") can also be used to introduce
|
||||
a structured binding declaration ([[dcl.struct.bind]](dcl.struct.bind "9.7 Structured 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.1 General [dcl.type.general]") of
|
||||
the [*new-type-id*](expr.new#nt:new-type-id "7.6.2.8 New [expr.new]") or
|
||||
in the [*type-id*](dcl.name#nt:type-id "9.3.2 Type names [dcl.name]") of a[*new-expression*](expr.new#nt:new-expression "7.6.2.8 New [expr.new]") ([[expr.new]](expr.new "7.6.2.8 New"))[.](#6.sentence-1)
|
||||
|
||||
In such a [*type-id*](dcl.name#nt:type-id "9.3.2 Type names [dcl.name]"),
|
||||
the placeholder type shall appear
|
||||
as one of the [*type-specifier*](dcl.type.general#nt:type-specifier "9.2.9.1 General [dcl.type.general]")*s* in
|
||||
the [*type-specifier-seq*](dcl.type.general#nt:type-specifier-seq "9.2.9.1 General [dcl.type.general]") or
|
||||
as one of the [*type-specifier*](dcl.type.general#nt:type-specifier "9.2.9.1 General [dcl.type.general]")*s* in
|
||||
a [*trailing-return-type*](dcl.decl.general#nt:trailing-return-type "9.3.1 General [dcl.decl.general]") that specifies the type that replaces such a [*type-specifier*](dcl.type.general#nt:type-specifier "9.2.9.1 General [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.1 General [dcl.type.general]") can also be used
|
||||
as the [*simple-type-specifier*](dcl.type.simple#nt:simple-type-specifier "9.2.9.3 Simple type specifiers [dcl.type.simple]") in an explicit type conversion (functional notation) ([[expr.type.conv]](expr.type.conv "7.6.1.4 Explicit 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.7 Placeholder 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.1 General [dcl.decl.general]") contains more than one[*init-declarator*](dcl.decl.general#nt:init-declarator "9.3.1 General [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.2 Placeholder 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.5 Private 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.7 Program 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.3 One-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.2 Referring 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.3 Template 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.3 Virtual 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.4 Coroutine 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.3 Explicit 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*]
|
||||
82
cppdraft/dcl/spec/general.md
Normal file
82
cppdraft/dcl/spec/general.md
Normal 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.1 General [dcl.spec.general]")
|
||||
[*storage-class-specifier*](dcl.stc#nt:storage-class-specifier "9.2.2 Storage class specifiers [dcl.stc]")
|
||||
[*defining-type-specifier*](dcl.type.general#nt:defining-type-specifier "9.2.9.1 General [dcl.type.general]")
|
||||
[*function-specifier*](dcl.fct.spec#nt:function-specifier "9.2.3 Function specifiers [dcl.fct.spec]")
|
||||
friend
|
||||
typedef
|
||||
constexpr
|
||||
consteval
|
||||
constinit
|
||||
inline
|
||||
|
||||
[decl-specifier-seq:](#nt:decl-specifier-seq "9.2.1 General [dcl.spec.general]")
|
||||
[*decl-specifier*](#nt:decl-specifier "9.2.1 General [dcl.spec.general]") [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]")opt
|
||||
[*decl-specifier*](#nt:decl-specifier "9.2.1 General [dcl.spec.general]") [*decl-specifier-seq*](#nt:decl-specifier-seq "9.2.1 General [dcl.spec.general]")
|
||||
|
||||
The optional [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]") in a [*decl-specifier-seq*](#nt:decl-specifier-seq "9.2.1 General [dcl.spec.general]") appertains to the type determined by the preceding[*decl-specifier*](#nt:decl-specifier "9.2.1 General [dcl.spec.general]")*s* ([[dcl.meaning]](dcl.meaning "9.3.4 Meaning of declarators"))[.](#1.sentence-2)
|
||||
|
||||
The [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1 Attribute 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.1 General [dcl.spec.general]")*s*friend, typedef, or inline shall appear in a [*decl-specifier-seq*](#nt:decl-specifier-seq "9.2.1 General [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.1 General [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.3 Simple type specifiers [dcl.type.simple]") is encountered while parsing a [*decl-specifier-seq*](#nt:decl-specifier-seq "9.2.1 General [dcl.spec.general]"),
|
||||
it is interpreted as part of the [*decl-specifier-seq*](#nt:decl-specifier-seq "9.2.1 General [dcl.spec.general]") if and only if there is no
|
||||
previous [*defining-type-specifier*](dcl.type.general#nt:defining-type-specifier "9.2.9.1 General [dcl.type.general]") other than a [*cv-qualifier*](dcl.decl.general#nt:cv-qualifier "9.3.1 General [dcl.decl.general]") in the[*decl-specifier-seq*](#nt:decl-specifier-seq "9.2.1 General [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.1 General [dcl.type.general]") (other thanconst or volatile) has to be present to indicate that
|
||||
the [*typedef-name*](dcl.typedef#nt:typedef-name "9.2.4 The typedef specifier [dcl.typedef]") Pc is the name being (re)declared,
|
||||
rather than being part of the [*decl-specifier*](#nt:decl-specifier "9.2.1 General [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.3 Simple 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
157
cppdraft/dcl/stc.md
Normal 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.2 Storage class specifiers [dcl.stc]")
|
||||
static
|
||||
thread_local
|
||||
extern
|
||||
mutable
|
||||
|
||||
At most one [*storage-class-specifier*](#nt:storage-class-specifier "9.2.2 Storage class specifiers [dcl.stc]") shall appear in a given[*decl-specifier-seq*](dcl.spec.general#nt:decl-specifier-seq "9.2.1 General [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.2 Storage class specifiers [dcl.stc]") appears in a [*decl-specifier-seq*](dcl.spec.general#nt:decl-specifier-seq "9.2.1 General [dcl.spec.general]"), there can be notypedef specifier in the same [*decl-specifier-seq*](dcl.spec.general#nt:decl-specifier-seq "9.2.1 General [dcl.spec.general]") and
|
||||
the [*init-declarator-list*](dcl.decl.general#nt:init-declarator-list "9.3.1 General [dcl.decl.general]") or [*member-declarator-list*](class.mem.general#nt:member-declarator-list "11.4.1 General [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.2 Anonymous unions")))[.](#1.sentence-4)
|
||||
|
||||
The[*storage-class-specifier*](#nt:storage-class-specifier "9.2.2 Storage class specifiers [dcl.stc]") applies to the name declared by each[*init-declarator*](dcl.decl.general#nt:init-declarator "9.3.1 General [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.4 Explicit specialization") and [[temp.explicit]](temp.explicit "13.9.3 Explicit 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.2 Storage 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.4 Automatic 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.3 Thread 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.7 Structured 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.2 Storage class specifiers [dcl.stc]") static is implied if no other[*storage-class-specifier*](#nt:storage-class-specifier "9.2.2 Storage class specifiers [dcl.stc]") appears in the[*decl-specifier-seq*](dcl.spec.general#nt:decl-specifier-seq "9.2.1 General [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.7 Structured binding declarations")), or
|
||||
to the declaration of an anonymous union ([[class.union.anon]](class.union.anon "11.5.2 Anonymous 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.2 Static 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.3 Thread storage duration"))[.](#4.sentence-3)
|
||||
|
||||
A static specifier can be
|
||||
used in declarations of class members; [[class.static]](class.static "11.4.9 Static members") describes its
|
||||
effect[.](#4.sentence-4)
|
||||
|
||||
For the linkage of a name declared with a static specifier,
|
||||
see [[basic.link]](basic.link "6.7 Program 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.7 Program 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.3 Explicit instantiation [temp.explicit]")*s* and[*linkage-specification*](dcl.link#nt:linkage-specification "9.12 Linkage specifications [dcl.link]")*s*, but it is not a[*storage-class-specifier*](#nt:storage-class-specifier "9.2.2 Storage 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.4 Class 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.5 CV-qualifiers"), [[dcl.type.cv]](dcl.type.cv "9.2.9.2 The cv-qualifiers"))[.](#9.sentence-1)
|
||||
|
||||
â *end note*]
|
||||
215
cppdraft/dcl/struct/bind.md
Normal file
215
cppdraft/dcl/struct/bind.md
Normal 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.11 Identifiers [lex.name]")*s*v0, v1, v2,â¦,vNâ1 of the[*sb-identifier-list*](dcl.pre#nt:sb-identifier-list "9.1 Preamble [dcl.pre]") as names[.](#1.sentence-1)
|
||||
|
||||
An [*sb-identifier*](dcl.pre#nt:sb-identifier "9.1 Preamble [dcl.pre]") that contains an ellipsis
|
||||
introduces a structured binding pack ([[temp.variadic]](temp.variadic "13.7.4 Variadic templates"))[.](#1.sentence-2)
|
||||
|
||||
A [*structured binding*](#def:structured_binding "9.7 Structured binding declarations [dcl.struct.bind]") is either
|
||||
an [*sb-identifier*](dcl.pre#nt:sb-identifier "9.1 Preamble [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.1 Attribute syntax and semantics [dcl.attr.grammar]") of
|
||||
an [*sb-identifier*](dcl.pre#nt:sb-identifier "9.1 Preamble [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.1 General [dcl.decl.general]")*s* in
|
||||
the [*decl-specifier-seq*](dcl.spec.general#nt:decl-specifier-seq "9.2.1 General [dcl.spec.general]") and*S* consist of
|
||||
each [*decl-specifier*](dcl.spec.general#nt:decl-specifier "9.2.1 General [dcl.spec.general]") of the [*decl-specifier-seq*](dcl.spec.general#nt:decl-specifier-seq "9.2.1 General [dcl.spec.general]") that is constexpr, constinit, or
|
||||
a [*storage-class-specifier*](dcl.stc#nt:storage-class-specifier "9.2.2 Storage class specifiers [dcl.stc]")[.](#1.sentence-5)
|
||||
|
||||
A cv that includes volatile is deprecated;
|
||||
see [[depr.volatile.type]](depr.volatile.type "D.4 Deprecated 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.19 Assignment and compound assignment operators [expr.assign]") in the [*initializer*](dcl.init.general#nt:initializer "9.5.1 General [dcl.init.general]") has array type *cv1* A and no [*ref-qualifier*](dcl.decl.general#nt:ref-qualifier "9.3.1 General [dcl.decl.general]") is present,*e* is defined by
|
||||
|
||||
[*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1 Attribute 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.19 Assignment and compound assignment operators [expr.assign]") as specified
|
||||
by the form of the [*initializer*](dcl.init.general#nt:initializer "9.5.1 General [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.1 Attribute syntax and semantics [dcl.attr.grammar]")opt [*decl-specifier-seq*](dcl.spec.general#nt:decl-specifier-seq "9.2.1 General [dcl.spec.general]") [*ref-qualifier*](dcl.decl.general#nt:ref-qualifier "9.3.1 General [dcl.decl.general]")opt *e* [*initializer*](dcl.init.general#nt:initializer "9.5.1 General [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.1 General [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.1 General [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.2 Properties 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.7 Structured 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.1 Preamble [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.1 Preamble [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.1 Preamble [stmt.pre]"),
|
||||
the decision variable ([[stmt.pre]](stmt.pre "8.1 Preamble")) 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.1 General [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.3 Qualified 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.2 Member 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.4 Argument-dependent name lookup"))[.](#7.sentence-4)
|
||||
|
||||
In either case, get<i> is interpreted as a [*template-id*](temp.names#nt:template-id "13.3 Names of template specializations [temp.names]")[.](#7.sentence-5)
|
||||
|
||||
[*Note [4](#note-4)*:
|
||||
|
||||
Ordinary [unqualified lookup](basic.lookup.unqual "6.5.3 Unqualified 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.1 General [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.1 Preamble"))
|
||||
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.5 Class 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.1 General [expr.prim.id.general]") x is âintâ,
|
||||
the type of the [*id-expression*](expr.prim.id.general#nt:id-expression "7.5.5.1 General [expr.prim.id.general]") y is âconst volatile doubleâ[.](#8.sentence-4)
|
||||
|
||||
â *end example*]
|
||||
1121
cppdraft/dcl/type.md
Normal file
1121
cppdraft/dcl/type.md
Normal file
File diff suppressed because it is too large
Load Diff
157
cppdraft/dcl/type/auto/deduct.md
Normal file
157
cppdraft/dcl/type/auto/deduct.md
Normal 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.2 Placeholder 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.1 General [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.1 General [dcl.init.general]") ([[dcl.init.list]](dcl.init.list "9.5.5 List-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.20 Comma operator [expr.comma]") X that is not an [*assignment-expression*](expr.assign#nt:assignment-expression "7.6.19 Assignment 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.20 Comma operator")) is not
|
||||
an [*assignment-expression*](expr.assign#nt:assignment-expression "7.6.19 Assignment 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.2 Template parameters [temp.param]")opt decltype(auto) orcv [*type-constraint*](temp.param#nt:type-constraint "13.2 Template 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.1 General [dcl.init.general]") of the form = [*initializer-clause*](dcl.init.general#nt:initializer-clause "9.5.1 General [dcl.init.general]"),E is the [*initializer-clause*](dcl.init.general#nt:initializer-clause "9.5.1 General [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.1 General [dcl.init.general]"),
|
||||
it shall consist of a single brace-enclosed [*assignment-expression*](expr.assign#nt:assignment-expression "7.6.19 Assignment and compound assignment operators [expr.assign]") and E is the [*assignment-expression*](expr.assign#nt:assignment-expression "7.6.19 Assignment 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.1 General [expr.post.general]"),
|
||||
the [*expression-list*](expr.post.general#nt:expression-list "7.6.1.1 General [expr.post.general]") shall be
|
||||
a single [*assignment-expression*](expr.assign#nt:assignment-expression "7.6.19 Assignment and compound assignment operators [expr.assign]") and E is the [*assignment-expression*](expr.assign#nt:assignment-expression "7.6.19 Assignment 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.4 Explicit 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.1 General [dcl.init.general]"),
|
||||
it shall consist of a single brace-enclosed [*assignment-expression*](expr.assign#nt:assignment-expression "7.6.19 Assignment and compound assignment operators [expr.assign]") and E is the [*assignment-expression*](expr.assign#nt:assignment-expression "7.6.19 Assignment 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.1 General [expr.post.general]"),
|
||||
the [*expression-list*](expr.post.general#nt:expression-list "7.6.1.1 General [expr.post.general]") shall be
|
||||
a single [*assignment-expression*](expr.assign#nt:assignment-expression "7.6.19 Assignment and compound assignment operators [expr.assign]") and E is the [*assignment-expression*](expr.assign#nt:assignment-expression "7.6.19 Assignment 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.1 General [dcl.spec.auto.general]") is of the form[*type-constraint*](temp.param#nt:type-constraint "13.2 Template 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.1 General"))
|
||||
the [*placeholder-type-specifier*](dcl.spec.auto.general#nt:placeholder-type-specifier "9.2.9.7.1 General [dcl.spec.auto.general]")[.](#3.sentence-2)
|
||||
|
||||
Obtain P fromT by replacing the occurrence of[*type-constraint*](temp.param#nt:type-constraint "13.2 Template 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.2 Deducing 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.1 General [dcl.spec.auto.general]") is of the form[*type-constraint*](temp.param#nt:type-constraint "13.2 Template 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.6 Decltype 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.1 General [dcl.spec.auto.general]") with a [*type-constraint*](temp.param#nt:type-constraint "13.2 Template parameters [temp.param]"),
|
||||
the immediately-declared constraint ([[temp.param]](temp.param "13.2 Template parameters"))
|
||||
of the [*type-constraint*](temp.param#nt:type-constraint "13.2 Template parameters [temp.param]") for the type deduced for the placeholder
|
||||
shall be satisfied[.](#5.sentence-1)
|
||||
51
cppdraft/dcl/type/class/deduct.md
Normal file
51
cppdraft/dcl/type/class/deduct.md
Normal 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.1 General [dcl.spec.general]") in the [*decl-specifier-seq*](dcl.spec.general#nt:decl-specifier-seq "9.2.1 General [dcl.spec.general]") of an initializing declaration ([[dcl.init]](dcl.init "9.5 Initializers")) 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.9 Class template argument deduction"))[.](#1.sentence-2)
|
||||
|
||||
If the [*decl-specifier-seq*](dcl.spec.general#nt:decl-specifier-seq "9.2.1 General [dcl.spec.general]") is followed by an [*init-declarator-list*](dcl.decl.general#nt:init-declarator-list "9.3.1 General [dcl.decl.general]") or [*member-declarator-list*](class.mem.general#nt:member-declarator-list "11.4.1 General [class.mem.general]") containing more than one [*declarator*](dcl.decl.general#nt:declarator "9.3.1 General [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.1 General [dcl.type.general]") in the [*new-type-id*](expr.new#nt:new-type-id "7.6.2.8 New [expr.new]") or [*type-id*](dcl.name#nt:type-id "9.3.2 Type names [dcl.name]") of a [*new-expression*](expr.new#nt:new-expression "7.6.2.8 New [expr.new]") ([[expr.new]](expr.new "7.6.2.8 New")),
|
||||
as the [*simple-type-specifier*](dcl.type.simple#nt:simple-type-specifier "9.2.9.3 Simple type specifiers [dcl.type.simple]") in an [explicit type conversion (functional notation)](expr.type.conv "7.6.1.4 Explicit type conversion (functional notation) [expr.type.conv]"),
|
||||
or
|
||||
as the [*type-specifier*](dcl.type.general#nt:type-specifier "9.2.9.1 General [dcl.type.general]") in the [*parameter-declaration*](dcl.fct#nt:parameter-declaration "9.3.4.6 Functions [dcl.fct]") of a [*template-parameter*](temp.param#nt:template-parameter "13.2 Template parameters [temp.param]") ([[temp.param]](temp.param "13.2 Template 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
120
cppdraft/dcl/type/cv.md
Normal 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.1 General [dcl.decl.general]")*s*, const andvolatile[.](#1.sentence-1)
|
||||
|
||||
Each [*cv-qualifier*](dcl.decl.general#nt:cv-qualifier "9.3.1 General [dcl.decl.general]") shall appear at most once in
|
||||
a [*cv-qualifier-seq*](dcl.decl.general#nt:cv-qualifier-seq "9.3.1 General [dcl.decl.general]")[.](#1.sentence-2)
|
||||
|
||||
If a [*cv-qualifier*](dcl.decl.general#nt:cv-qualifier "9.3.1 General [dcl.decl.general]") appears in a[*decl-specifier-seq*](dcl.spec.general#nt:decl-specifier-seq "9.2.1 General [dcl.spec.general]"), the [*init-declarator-list*](dcl.decl.general#nt:init-declarator-list "9.3.1 General [dcl.decl.general]") or [*member-declarator-list*](class.mem.general#nt:member-declarator-list "11.4.1 General [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.5 CV-qualifiers") and [[dcl.fct]](dcl.fct "9.3.4.6 Functions") 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.2 Storage class specifiers"))
|
||||
and its usability in constant expressions ([[expr.const]](expr.const "7.7 Constant expressions"))[.](#2.sentence-1)
|
||||
|
||||
As
|
||||
described in [[dcl.init]](dcl.init "9.5 Initializers"), 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.11 Const 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.19 Assignment and compound assignment operators"), [[expr.post.incr]](expr.post.incr "7.6.1.6 Increment and decrement"), [[expr.pre.incr]](expr.pre.incr "7.6.2.3 Increment and decrement")) a
|
||||
const object ([[basic.type.qualifier]](basic.type.qualifier "6.9.5 CV-qualifiers")) during its
|
||||
lifetime ([[basic.life]](basic.life "6.8.4 Lifetime")) 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.1 Sequential 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*]
|
||||
106
cppdraft/dcl/type/decltype.md
Normal file
106
cppdraft/dcl/type/decltype.md
Normal 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.6 Decltype specifiers [dcl.type.decltype]")
|
||||
decltype ( [*expression*](expr.comma#nt:expression "7.6.20 Comma 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.1 General [expr.prim.id.general]") naming a structured binding ([[dcl.struct.bind]](dcl.struct.bind "9.7 Structured 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.1 General [expr.prim.id.general]") naming a constant template parameter ([[temp.param]](temp.param "13.2 Template 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.7 Placeholder type specifiers"), [[dcl.type.class.deduct]](dcl.type.class.deduct "9.2.9.8 Deduced 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.1 General [expr.prim.id.general]") or
|
||||
an unparenthesized
|
||||
class
|
||||
member access ([[expr.ref]](expr.ref "7.6.1.5 Class 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.9 Expression 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.6 Splice 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.3 Context 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.7 Placeholder 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.6 Decltype specifiers [dcl.type.decltype]") is a prvalue
|
||||
and is not a (possibly parenthesized) immediate invocation ([[expr.const]](expr.const "7.7 Constant expressions")),
|
||||
the temporary materialization conversion is not applied ([[conv.rval]](conv.rval "7.3.5 Temporary 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.6 Decltype specifiers [dcl.type.decltype]") is analogous to a use of a [*typedef-name*](dcl.typedef#nt:typedef-name "9.2.4 The 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.3 Template argument deduction")) because A<int>::~A() is implicitly used in its// [*decltype-specifier*](#nt:decltype-specifier "9.2.9.6 Decltype 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.6 Decltype 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
134
cppdraft/dcl/type/elab.md
Normal 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.5 Elaborated type specifiers [dcl.type.elab]")
|
||||
[*class-key*](class.pre#nt:class-key "11.1 Preamble [class.pre]") [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]")opt [*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3 Qualified names [expr.prim.id.qual]")opt [*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]")
|
||||
[*class-key*](class.pre#nt:class-key "11.1 Preamble [class.pre]") [*simple-template-id*](temp.names#nt:simple-template-id "13.3 Names of template specializations [temp.names]")
|
||||
[*class-key*](class.pre#nt:class-key "11.1 Preamble [class.pre]") [*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3 Qualified names [expr.prim.id.qual]") templateopt [*simple-template-id*](temp.names#nt:simple-template-id "13.3 Names of template specializations [temp.names]")
|
||||
enum [*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3 Qualified names [expr.prim.id.qual]")opt [*identifier*](lex.name#nt:identifier "5.11 Identifiers [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.5 Elaborated type specifiers [dcl.type.elab]") are
|
||||
its [*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]") (if any) and
|
||||
those of its [*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3 Qualified names [expr.prim.id.qual]") and[*simple-template-id*](temp.names#nt:simple-template-id "13.3 Names 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.5 Elaborated 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.4 Explicit specialization")),
|
||||
a partial specialization ([[temp.spec.partial]](temp.spec.partial "13.7.6 Partial specialization")),
|
||||
an explicit
|
||||
instantiation ([[temp.explicit]](temp.explicit "13.9.3 Explicit instantiation")), or it has one of the following
|
||||
forms:
|
||||
|
||||
[*class-key*](class.pre#nt:class-key "11.1 Preamble [class.pre]") [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]")opt [*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]") ;
|
||||
[*class-key*](class.pre#nt:class-key "11.1 Preamble [class.pre]") [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]")opt [*simple-template-id*](temp.names#nt:simple-template-id "13.3 Names of template specializations [temp.names]") ;
|
||||
|
||||
In the first case,
|
||||
the [*elaborated-type-specifier*](#nt:elaborated-type-specifier "9.2.9.5 Elaborated type specifiers [dcl.type.elab]") declares
|
||||
the [*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]") as a [*class-name*](class.pre#nt:class-name "11.1 Preamble [class.pre]")[.](#2.sentence-2)
|
||||
|
||||
The second case shall appear only
|
||||
in an [*explicit-specialization*](temp.expl.spec#nt:explicit-specialization "13.9.4 Explicit specialization [temp.expl.spec]") ([[temp.expl.spec]](temp.expl.spec "13.9.4 Explicit specialization")) or
|
||||
in a [*template-declaration*](temp.pre#nt:template-declaration "13.1 Preamble [temp.pre]") (where it declares a partial specialization)[.](#2.sentence-3)
|
||||
|
||||
The [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1 Attribute 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.5 Elaborated type specifiers [dcl.type.elab]") E shall not have
|
||||
an [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]")[.](#3.sentence-1)
|
||||
|
||||
If E contains an [*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]") but no [*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3 Qualified names [expr.prim.id.qual]") and
|
||||
(unqualified) lookup for the [*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]") finds nothing,E shall not be introduced by the enum keyword and
|
||||
declares the [*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]") as a [*class-name*](class.pre#nt:class-name "11.1 Preamble [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.1 General [class.mem.general]") that is an [*elaborated-type-specifier*](#nt:elaborated-type-specifier "9.2.9.5 Elaborated type specifiers [dcl.type.elab]") shall have one of the following forms:
|
||||
|
||||
[*class-key*](class.pre#nt:class-key "11.1 Preamble [class.pre]") [*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3 Qualified names [expr.prim.id.qual]")opt [*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]")
|
||||
[*class-key*](class.pre#nt:class-key "11.1 Preamble [class.pre]") [*simple-template-id*](temp.names#nt:simple-template-id "13.3 Names of template specializations [temp.names]")
|
||||
[*class-key*](class.pre#nt:class-key "11.1 Preamble [class.pre]") [*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3 Qualified names [expr.prim.id.qual]") templateopt [*simple-template-id*](temp.names#nt:simple-template-id "13.3 Names of template specializations [temp.names]")
|
||||
|
||||
Any unqualified lookup for the [*identifier*](lex.name#nt:identifier "5.11 Identifiers [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.4 Using 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.6 Elaborated type specifiers") describes how name lookup proceeds
|
||||
in an [*elaborated-type-specifier*](#nt:elaborated-type-specifier "9.2.9.5 Elaborated type specifiers [dcl.type.elab]")[.](#5.sentence-1)
|
||||
|
||||
An [*elaborated-type-specifier*](#nt:elaborated-type-specifier "9.2.9.5 Elaborated type specifiers [dcl.type.elab]") can be used to refer to
|
||||
a previously declared [*class-name*](class.pre#nt:class-name "11.1 Preamble [class.pre]") or [*enum-name*](dcl.enum#nt:enum-name "9.8.1 Enumeration 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.11 Identifiers [lex.name]") or [*simple-template-id*](temp.names#nt:simple-template-id "13.3 Names of template specializations [temp.names]") in an [*elaborated-type-specifier*](#nt:elaborated-type-specifier "9.2.9.5 Elaborated type specifiers [dcl.type.elab]") resolves to a [*class-name*](class.pre#nt:class-name "11.1 Preamble [class.pre]") or[*enum-name*](dcl.enum#nt:enum-name "9.8.1 Enumeration declarations [dcl.enum]"), the [*elaborated-type-specifier*](#nt:elaborated-type-specifier "9.2.9.5 Elaborated 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.3 Simple type specifiers [dcl.type.simple]") introduces
|
||||
its [*type-name*](dcl.type.simple#nt:type-name "9.2.9.3 Simple type specifiers [dcl.type.simple]") ([[dcl.type.simple]](dcl.type.simple "9.2.9.3 Simple type specifiers"))[.](#6.sentence-1)
|
||||
|
||||
If the [*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]") or [*simple-template-id*](temp.names#nt:simple-template-id "13.3 Names of template specializations [temp.names]") resolves to a[*typedef-name*](dcl.typedef#nt:typedef-name "9.2.4 The typedef specifier [dcl.typedef]") ([[dcl.typedef]](dcl.typedef "9.2.4 The typedef specifier"), [[temp.names]](temp.names "13.3 Names of template specializations")),
|
||||
the [*elaborated-type-specifier*](#nt:elaborated-type-specifier "9.2.9.5 Elaborated 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.2 Template 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.4 Friends"))[.](#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.1 Preamble [class.pre]") or enum keyword
|
||||
present in an[*elaborated-type-specifier*](#nt:elaborated-type-specifier "9.2.9.5 Elaborated 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.5 Elaborated 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.5 Elaborated type specifiers [dcl.type.elab]") that declares a[*class-name*](class.pre#nt:class-name "11.1 Preamble [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.5 Elaborated type specifiers [dcl.type.elab]"), the enum keyword
|
||||
shall be
|
||||
used to refer to an enumeration ([[dcl.enum]](dcl.enum "9.8.1 Enumeration declarations")), the union[*class-key*](class.pre#nt:class-key "11.1 Preamble [class.pre]") shall be used to refer to a union ([[class.union]](class.union "11.5 Unions")),
|
||||
and either the class or struct[*class-key*](class.pre#nt:class-key "11.1 Preamble [class.pre]") shall be used to refer to a non-union class ([[class.pre]](class.pre "11.1 Preamble"))[.](#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*]
|
||||
103
cppdraft/dcl/type/general.md
Normal file
103
cppdraft/dcl/type/general.md
Normal 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.1 General [dcl.type.general]")
|
||||
[*simple-type-specifier*](dcl.type.simple#nt:simple-type-specifier "9.2.9.3 Simple type specifiers [dcl.type.simple]")
|
||||
[*elaborated-type-specifier*](dcl.type.elab#nt:elaborated-type-specifier "9.2.9.5 Elaborated type specifiers [dcl.type.elab]")
|
||||
[*typename-specifier*](temp.res.general#nt:typename-specifier "13.8.1 General [temp.res.general]")
|
||||
[*cv-qualifier*](dcl.decl.general#nt:cv-qualifier "9.3.1 General [dcl.decl.general]")
|
||||
|
||||
[type-specifier-seq:](#nt:type-specifier-seq "9.2.9.1 General [dcl.type.general]")
|
||||
[*type-specifier*](#nt:type-specifier "9.2.9.1 General [dcl.type.general]") [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]")opt
|
||||
[*type-specifier*](#nt:type-specifier "9.2.9.1 General [dcl.type.general]") [*type-specifier-seq*](#nt:type-specifier-seq "9.2.9.1 General [dcl.type.general]")
|
||||
|
||||
[defining-type-specifier:](#nt:defining-type-specifier "9.2.9.1 General [dcl.type.general]")
|
||||
[*type-specifier*](#nt:type-specifier "9.2.9.1 General [dcl.type.general]")
|
||||
[*class-specifier*](class.pre#nt:class-specifier "11.1 Preamble [class.pre]")
|
||||
[*enum-specifier*](dcl.enum#nt:enum-specifier "9.8.1 Enumeration declarations [dcl.enum]")
|
||||
|
||||
[defining-type-specifier-seq:](#nt:defining-type-specifier-seq "9.2.9.1 General [dcl.type.general]")
|
||||
[*defining-type-specifier*](#nt:defining-type-specifier "9.2.9.1 General [dcl.type.general]") [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]")opt
|
||||
[*defining-type-specifier*](#nt:defining-type-specifier "9.2.9.1 General [dcl.type.general]") [*defining-type-specifier-seq*](#nt:defining-type-specifier-seq "9.2.9.1 General [dcl.type.general]")
|
||||
|
||||
The optional [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]") in a [*type-specifier-seq*](#nt:type-specifier-seq "9.2.9.1 General [dcl.type.general]") or a [*defining-type-specifier-seq*](#nt:defining-type-specifier-seq "9.2.9.1 General [dcl.type.general]") appertains
|
||||
to the type denoted by the preceding [*type-specifier*](#nt:type-specifier "9.2.9.1 General [dcl.type.general]")*s* or [*defining-type-specifier*](#nt:defining-type-specifier "9.2.9.1 General [dcl.type.general]")*s* ([[dcl.meaning]](dcl.meaning "9.3.4 Meaning of declarators"))[.](#1.sentence-2)
|
||||
|
||||
The[*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1 Attribute 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.1 General [dcl.type.general]") is allowed in the complete[*decl-specifier-seq*](dcl.spec.general#nt:decl-specifier-seq "9.2.1 General [dcl.spec.general]") of a [*declaration*](dcl.pre#nt:declaration "9.1 Preamble [dcl.pre]") or in a[*defining-type-specifier-seq*](#nt:defining-type-specifier-seq "9.2.9.1 General [dcl.type.general]"),
|
||||
and at most one[*type-specifier*](#nt:type-specifier "9.2.9.1 General [dcl.type.general]") is allowed in a[*type-specifier-seq*](#nt:type-specifier-seq "9.2.9.1 General [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.1 General [dcl.type.general]") that is not a[*cv-qualifier*](dcl.decl.general#nt:cv-qualifier "9.3.1 General [dcl.decl.general]") shall appear in a complete[*type-specifier-seq*](#nt:type-specifier-seq "9.2.9.1 General [dcl.type.general]") or a complete[*decl-specifier-seq*](dcl.spec.general#nt:decl-specifier-seq "9.2.1 General [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.1 Enumeration declarations [dcl.enum]")*s*,[*class-specifier*](class.pre#nt:class-specifier "11.1 Preamble [class.pre]")*s*,
|
||||
and[*typename-specifier*](temp.res.general#nt:typename-specifier "13.8.1 General [temp.res.general]")*s* are discussed
|
||||
in[[dcl.enum]](dcl.enum "9.8.1 Enumeration declarations"),[[class]](class "11 Classes"),
|
||||
and[[temp.res]](temp.res "13.8 Name resolution"), respectively[.](#4.sentence-1)
|
||||
|
||||
The remaining[*type-specifier*](#nt:type-specifier "9.2.9.1 General [dcl.type.general]")*s* are discussed in the rest of [[dcl.type]](dcl.type "9.2.9 Type 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.1 General [dcl.spec.general]") that
|
||||
lacks a [*type-specifier*](#nt:type-specifier "9.2.9.1 General [dcl.type.general]") or that has a[*type-specifier*](#nt:type-specifier "9.2.9.1 General [dcl.type.general]") that only specifies [*cv-qualifier*](dcl.decl.general#nt:cv-qualifier "9.3.1 General [dcl.decl.general]")*s*[.](#footnote-74.sentence-1)
|
||||
|
||||
The âimplicit intâ rule of C is no longer supported[.](#footnote-74.sentence-2)
|
||||
43
cppdraft/dcl/type/pack/index.md
Normal file
43
cppdraft/dcl/type/pack/index.md
Normal 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.4 Pack indexing specifier [dcl.type.pack.index]")
|
||||
[*typedef-name*](dcl.typedef#nt:typedef-name "9.2.4 The typedef specifier [dcl.typedef]") ... [ [*constant-expression*](expr.const#nt:constant-expression "7.7 Constant 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.4 The typedef specifier [dcl.typedef]") P in a [*pack-index-specifier*](#nt:pack-index-specifier "9.2.9.4 Pack 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.7 Constant expressions [expr.const]") shall be
|
||||
a converted constant expression ([[expr.const]](expr.const "7.7 Constant 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.4 Pack indexing specifier [dcl.type.pack.index]") is a pack expansion ([[temp.variadic]](temp.variadic "13.7.4 Variadic 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.4 Pack 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
162
cppdraft/dcl/type/simple.md
Normal 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.3 Simple type specifiers [dcl.type.simple]")
|
||||
[*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3 Qualified names [expr.prim.id.qual]")opt [*type-name*](#nt:type-name "9.2.9.3 Simple type specifiers [dcl.type.simple]")
|
||||
[*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3 Qualified names [expr.prim.id.qual]") template [*simple-template-id*](temp.names#nt:simple-template-id "13.3 Names of template specializations [temp.names]")
|
||||
[*computed-type-specifier*](#nt:computed-type-specifier "9.2.9.3 Simple type specifiers [dcl.type.simple]")
|
||||
[*placeholder-type-specifier*](dcl.spec.auto.general#nt:placeholder-type-specifier "9.2.9.7.1 General [dcl.spec.auto.general]")
|
||||
[*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3 Qualified names [expr.prim.id.qual]")opt [*template-name*](temp.names#nt:template-name "13.3 Names 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.3 Simple type specifiers [dcl.type.simple]")
|
||||
[*class-name*](class.pre#nt:class-name "11.1 Preamble [class.pre]")
|
||||
[*enum-name*](dcl.enum#nt:enum-name "9.8.1 Enumeration declarations [dcl.enum]")
|
||||
[*typedef-name*](dcl.typedef#nt:typedef-name "9.2.4 The typedef specifier [dcl.typedef]")
|
||||
|
||||
[computed-type-specifier:](#nt:computed-type-specifier "9.2.9.3 Simple type specifiers [dcl.type.simple]")
|
||||
[*decltype-specifier*](dcl.type.decltype#nt:decltype-specifier "9.2.9.6 Decltype specifiers [dcl.type.decltype]")
|
||||
[*pack-index-specifier*](dcl.type.pack.index#nt:pack-index-specifier "9.2.9.4 Pack indexing specifier [dcl.type.pack.index]")
|
||||
[*splice-type-specifier*](dcl.type.splice#nt:splice-type-specifier "9.2.9.9 Type 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.3 Simple type specifiers [dcl.type.simple]") are those of its[*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3 Qualified names [expr.prim.id.qual]"),[*type-name*](#nt:type-name "9.2.9.3 Simple type specifiers [dcl.type.simple]"),[*simple-template-id*](temp.names#nt:simple-template-id "13.3 Names of template specializations [temp.names]"),[*template-name*](temp.names#nt:template-name "13.3 Names of template specializations [temp.names]"), and/or[*type-constraint*](temp.param#nt:type-constraint "13.2 Template parameters [temp.param]") (if it is a [*placeholder-type-specifier*](dcl.spec.auto.general#nt:placeholder-type-specifier "9.2.9.7.1 General [dcl.spec.auto.general]"))[.](#2.sentence-1)
|
||||
|
||||
The component name of a [*type-name*](#nt:type-name "9.2.9.3 Simple 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.1 General [dcl.spec.auto.general]") is a placeholder for
|
||||
a type to be deduced ([[dcl.spec.auto]](dcl.spec.auto "9.2.9.7 Placeholder type specifiers"))[.](#3.sentence-1)
|
||||
|
||||
A [*type-specifier*](dcl.type.general#nt:type-specifier "9.2.9.1 General [dcl.type.general]") is a placeholder for
|
||||
a deduced class type ([[dcl.type.class.deduct]](dcl.type.class.deduct "9.2.9.8 Deduced 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.3 Qualified names [expr.prim.id.qual]")opt [*template-name*](temp.names#nt:template-name "13.3 Names of template specializations [temp.names]") or
|
||||
|
||||
- [(3.2)](#3.2)
|
||||
|
||||
it is of the form typenameopt [*splice-specifier*](basic.splice#nt:splice-specifier "6.6 Splice specifiers [basic.splice]") and
|
||||
the [*splice-specifier*](basic.splice#nt:splice-specifier "6.6 Splice 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.3 Qualified names [expr.prim.id.qual]") or [*splice-specifier*](basic.splice#nt:splice-specifier "6.6 Splice specifiers [basic.splice]"),
|
||||
if any, shall be non-dependent and
|
||||
the [*template-name*](temp.names#nt:template-name "13.3 Names of template specializations [temp.names]") or [*splice-specifier*](basic.splice#nt:splice-specifier "6.6 Splice specifiers [basic.splice]") shall designate a deducible template[.](#3.sentence-3)
|
||||
|
||||
A [*deducible template*](#def:template,deducible "9.2.9.3 Simple 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.2 Type names [dcl.name]") is of the form
|
||||
|
||||
typenameopt [*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3 Qualified names [expr.prim.id.qual]")opt templateopt [*simple-template-id*](temp.names#nt:simple-template-id "13.3 Names of template specializations [temp.names]")
|
||||
|
||||
where the [*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3 Qualified names [expr.prim.id.qual]") (if any) is non-dependent and
|
||||
the [*template-name*](temp.names#nt:template-name "13.3 Names of template specializations [temp.names]") of the [*simple-template-id*](temp.names#nt:simple-template-id "13.3 Names 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.3 Names of template specializations [temp.names]") in contexts where class template argument deduction would be performed ([[temp.local]](temp.local "13.8.2 Locally declared names"))[.](#3.sentence-6)
|
||||
|
||||
â *end note*]
|
||||
|
||||
The other[*simple-type-specifier*](#nt:simple-type-specifier "9.2.9.3 Simple 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.2 Fundamental 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.3 Simple 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.3 Simple 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.3 Simple 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.3 Names of template specializations [temp.names]") | the type as defined in [[temp.names]](temp.names "13.3 Names of template specializations") |
|
||||
| [ð](#tab:dcl.type.simple-row-4)<br>[*decltype-specifier*](dcl.type.decltype#nt:decltype-specifier "9.2.9.6 Decltype specifiers [dcl.type.decltype]") | the type as defined in [[dcl.type.decltype]](dcl.type.decltype "9.2.9.6 Decltype specifiers") |
|
||||
| [ð](#tab:dcl.type.simple-row-5)<br>[*pack-index-specifier*](dcl.type.pack.index#nt:pack-index-specifier "9.2.9.4 Pack indexing specifier [dcl.type.pack.index]") | the type as defined in [[dcl.type.pack.index]](dcl.type.pack.index "9.2.9.4 Pack indexing specifier") |
|
||||
| [ð](#tab:dcl.type.simple-row-6)<br>[*placeholder-type-specifier*](dcl.spec.auto.general#nt:placeholder-type-specifier "9.2.9.7.1 General [dcl.spec.auto.general]") | the type as defined in [[dcl.spec.auto]](dcl.spec.auto "9.2.9.7 Placeholder type specifiers") |
|
||||
| [ð](#tab:dcl.type.simple-row-7)<br>[*template-name*](temp.names#nt:template-name "13.3 Names of template specializations [temp.names]") | the type as defined in [[dcl.type.class.deduct]](dcl.type.class.deduct "9.2.9.8 Deduced class template specialization types") |
|
||||
| [ð](#tab:dcl.type.simple-row-8)<br>[*splice-type-specifier*](dcl.type.splice#nt:splice-type-specifier "9.2.9.9 Type splicing [dcl.type.splice]") | the type as defined in [[dcl.type.splice]](dcl.type.splice "9.2.9.9 Type 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.3 Simple 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.1 General [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*]
|
||||
46
cppdraft/dcl/type/splice.md
Normal file
46
cppdraft/dcl/type/splice.md
Normal 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.9 Type splicing [dcl.type.splice]")
|
||||
typenameopt [*splice-specifier*](basic.splice#nt:splice-specifier "6.6 Splice specifiers [basic.splice]")
|
||||
typenameopt [*splice-specialization-specifier*](basic.splice#nt:splice-specialization-specifier "6.6 Splice 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.6 Splice specifiers [basic.splice]") or[*splice-specialization-specifier*](basic.splice#nt:splice-specialization-specifier "6.6 Splice specifiers [basic.splice]") immediately followed by :: is never interpreted as part of a [*splice-type-specifier*](#nt:splice-type-specifier "9.2.9.9 Type splicing [dcl.type.splice]")[.](#1.sentence-1)
|
||||
|
||||
A [*splice-specifier*](basic.splice#nt:splice-specifier "6.6 Splice specifiers [basic.splice]") or[*splice-specialization-specifier*](basic.splice#nt:splice-specialization-specifier "6.6 Splice specifiers [basic.splice]") not preceded by typename is only interpreted as a [*splice-type-specifier*](#nt:splice-type-specifier "9.2.9.9 Type splicing [dcl.type.splice]") within a type-only context ([[temp.res.general]](temp.res.general "13.8.1 General"))[.](#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.9 Type splicing [dcl.type.splice]") of the formtypenameopt [*splice-specifier*](basic.splice#nt:splice-specifier "6.6 Splice specifiers [basic.splice]"),
|
||||
the [*splice-specifier*](basic.splice#nt:splice-specifier "6.6 Splice 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.9 Type splicing [dcl.type.splice]") designates
|
||||
the same entity as the [*splice-specifier*](basic.splice#nt:splice-specifier "6.6 Splice 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.9 Type splicing [dcl.type.splice]") of the formtypenameopt [*splice-specialization-specifier*](basic.splice#nt:splice-specialization-specifier "6.6 Splice specifiers [basic.splice]"),
|
||||
the [*splice-specifier*](basic.splice#nt:splice-specifier "6.6 Splice specifiers [basic.splice]") of
|
||||
the [*splice-specialization-specifier*](basic.splice#nt:splice-specialization-specifier "6.6 Splice 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.9 Type 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.6 Splice specifiers [basic.splice]")[.](#3.sentence-2)
|
||||
121
cppdraft/dcl/typedef.md
Normal file
121
cppdraft/dcl/typedef.md
Normal 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.1 General [dcl.spec.general]") typedef declare [*type aliases*](#def:alias,type "9.2.4 The 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.1 General [dcl.spec.general]") with any other kind of
|
||||
specifier except a [*defining-type-specifier*](dcl.type.general#nt:defining-type-specifier "9.2.9.1 General [dcl.type.general]"), and it shall not be used in the[*decl-specifier-seq*](dcl.spec.general#nt:decl-specifier-seq "9.2.1 General [dcl.spec.general]") of a[*parameter-declaration*](dcl.fct#nt:parameter-declaration "9.3.4.6 Functions [dcl.fct]") ([[dcl.fct]](dcl.fct "9.3.4.6 Functions")) nor in the[*decl-specifier-seq*](dcl.spec.general#nt:decl-specifier-seq "9.2.1 General [dcl.spec.general]") of a[*function-definition*](dcl.fct.def.general#nt:function-definition "9.6.1 General [dcl.fct.def.general]") ([[dcl.fct.def]](dcl.fct.def "9.6 Function definitions"))[.](#1.sentence-2)
|
||||
|
||||
If a typedef specifier appears in a declaration without a [*declarator*](dcl.decl.general#nt:declarator "9.3.1 General [dcl.decl.general]"),
|
||||
the program is ill-formed[.](#1.sentence-3)
|
||||
|
||||
[typedef-name:](#nt:typedef-name "9.2.4 The typedef specifier [dcl.typedef]")
|
||||
[*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]")
|
||||
[*simple-template-id*](temp.names#nt:simple-template-id "13.3 Names of template specializations [temp.names]")
|
||||
|
||||
A name declared with the typedef specifier becomes a[*typedef-name*](#nt:typedef-name "9.2.4 The 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.11 Identifiers [lex.name]") ([[dcl.decl]](dcl.decl "9.3 Declarators"))
|
||||
or [*simple-template-id*](temp.names#nt:simple-template-id "13.3 Names of template specializations [temp.names]") ([[temp.pre]](temp.pre "13.1 Preamble"))[.](#1.sentence-5)
|
||||
|
||||
A [*typedef-name*](#nt:typedef-name "9.2.4 The typedef specifier [dcl.typedef]") does not introduce a new type the way a class
|
||||
declaration ([[class.name]](class.name "11.3 Class names")) or enum declaration ([[dcl.enum]](dcl.enum "9.8.1 Enumeration 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.1 Preamble [dcl.pre]")[.](#2.sentence-1)
|
||||
|
||||
The [*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]") following theusing keyword is not looked up;
|
||||
it becomes the [*typedef-name*](#nt:typedef-name "9.2.4 The typedef specifier [dcl.typedef]") of a type alias
|
||||
and the optional [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]") following the[*identifier*](lex.name#nt:identifier "5.11 Identifiers [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.2 Point of declaration")) â *end example*]
|
||||
|
||||
The [*defining-type-specifier-seq*](dcl.type.general#nt:defining-type-specifier-seq "9.2.9.1 General [dcl.type.general]") of the [*defining-type-id*](dcl.name#nt:defining-type-id "9.3.2 Type names [dcl.name]") shall not define
|
||||
a class or enumeration if the [*alias-declaration*](dcl.pre#nt:alias-declaration "9.1 Preamble [dcl.pre]") is the [*declaration*](dcl.pre#nt:declaration "9.1 Preamble [dcl.pre]") of a [*template-declaration*](temp.pre#nt:template-declaration "13.1 Preamble [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.3 Names of template specializations [temp.names]") is only a [*typedef-name*](#nt:typedef-name "9.2.4 The typedef specifier [dcl.typedef]") if its [*template-name*](temp.names#nt:template-name "13.3 Names 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.3 Names of template specializations [temp.names]") that names a class template specialization
|
||||
is a [*class-name*](class.pre#nt:class-name "11.1 Preamble [class.pre]") ([[class.name]](class.name "11.3 Class names"))[.](#3.sentence-2)
|
||||
|
||||
If a [*typedef-name*](#nt:typedef-name "9.2.4 The 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.5 Elaborated type specifiers [dcl.type.elab]") ([[dcl.type.elab]](dcl.type.elab "9.2.9.5 Elaborated type specifiers")), a [class
|
||||
definition](class "11 Classes [class]"), a [constructor
|
||||
declaration](class.ctor "11.4.5 Constructors [class.ctor]"), or a [destructor
|
||||
declaration](class.dtor "11.4.7 Destructors [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.4 The 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.4 The typedef specifier [dcl.typedef]") ([[basic.link]](basic.link "6.7 Program 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.1 General [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.1 General [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*]
|
||||
Reference in New Issue
Block a user