Init
This commit is contained in:
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)
|
||||
Reference in New Issue
Block a user