tmp/tmp2e7gq8hg/{from.md → to.md}
RENAMED
|
@@ -7,27 +7,29 @@ or *designated-initializer-clause*s of the *designated-initializer-list*
|
|
| 7 |
are called the *elements* of the initializer list. An initializer list
|
| 8 |
may be empty. List-initialization can occur in direct-initialization or
|
| 9 |
copy-initialization contexts; list-initialization in a
|
| 10 |
direct-initialization context is called *direct-list-initialization* and
|
| 11 |
list-initialization in a copy-initialization context is called
|
| 12 |
-
*copy-list-initialization*.
|
|
|
|
| 13 |
|
| 14 |
[*Note 1*:
|
| 15 |
|
| 16 |
List-initialization can be used
|
| 17 |
|
| 18 |
-
- as the initializer in a variable definition [[dcl.init]]
|
| 19 |
-
- as the initializer in a *new-expression* [[expr.new]]
|
| 20 |
-
- in a `return` statement [[stmt.return]]
|
| 21 |
-
- as a *for-range-initializer* [[stmt.iter]]
|
| 22 |
-
- as a function argument [[expr.call]]
|
| 23 |
-
- as a
|
|
|
|
| 24 |
- as an argument to a constructor invocation
|
| 25 |
-
[[dcl.init]], [[expr.type.conv]]
|
| 26 |
-
- as an initializer for a non-static data member [[class.mem]]
|
| 27 |
-
- in a *mem-initializer* [[class.base.init]]
|
| 28 |
-
- on the right-hand side of an assignment [[expr.
|
| 29 |
|
| 30 |
[*Example 1*:
|
| 31 |
|
| 32 |
``` cpp
|
| 33 |
int a = {1};
|
|
@@ -62,29 +64,29 @@ The template `std::initializer_list` is not predefined; if a standard
|
|
| 62 |
library declaration [[initializer.list.syn]], [[std.modules]] of
|
| 63 |
`std::initializer_list` is not reachable from [[module.reach]] a use of
|
| 64 |
`std::initializer_list` — even an implicit use in which the type is not
|
| 65 |
named [[dcl.spec.auto]] — the program is ill-formed.
|
| 66 |
|
| 67 |
-
List-initialization of an object or reference of type `T` is
|
| 68 |
-
follows:
|
| 69 |
|
| 70 |
-
- If the *braced-init-list* contains a *designated-initializer-list*
|
| 71 |
-
`T` shall be an aggregate class. The
|
| 72 |
-
*
|
| 73 |
-
|
| 74 |
-
members of `T`. Aggregate
|
| 75 |
-
[[dcl.init.aggr]].
|
| 76 |
\[*Example 2*:
|
| 77 |
``` cpp
|
| 78 |
struct A { int x; int y; int z; };
|
| 79 |
A a{.y = 2, .x = 1}; // error: designator order does not match declaration order
|
| 80 |
A b{.x = 1, .z = 2}; // OK, b.y initialized to 0
|
| 81 |
```
|
| 82 |
|
| 83 |
— *end example*]
|
| 84 |
- If `T` is an aggregate class and the initializer list has a single
|
| 85 |
-
element of type *
|
| 86 |
`T`, the object is initialized from that element (by
|
| 87 |
copy-initialization for copy-list-initialization, or by
|
| 88 |
direct-initialization for direct-list-initialization).
|
| 89 |
- Otherwise, if `T` is a character array and the initializer list has a
|
| 90 |
single element that is an appropriately-typed *string-literal*
|
|
@@ -107,28 +109,30 @@ follows:
|
|
| 107 |
```
|
| 108 |
|
| 109 |
— *end example*]
|
| 110 |
- Otherwise, if the initializer list has no elements and `T` is a class
|
| 111 |
type with a default constructor, the object is value-initialized.
|
| 112 |
-
- Otherwise, if `T` is a specialization of `std::initializer_list
|
| 113 |
-
|
| 114 |
- Otherwise, if `T` is a class type, constructors are considered. The
|
| 115 |
applicable constructors are enumerated and the best one is chosen
|
| 116 |
through overload resolution [[over.match]], [[over.match.list]]. If a
|
| 117 |
narrowing conversion (see below) is required to convert any of the
|
| 118 |
arguments, the program is ill-formed.
|
| 119 |
\[*Example 4*:
|
| 120 |
``` cpp
|
| 121 |
struct S {
|
| 122 |
S(std::initializer_list<double>); // #1
|
| 123 |
S(std::initializer_list<int>); // #2
|
| 124 |
-
S();
|
|
|
|
| 125 |
// ...
|
| 126 |
};
|
| 127 |
S s1 = { 1.0, 2.0, 3.0 }; // invoke #1
|
| 128 |
S s2 = { 1, 2, 3 }; // invoke #2
|
| 129 |
-
S s3
|
|
|
|
| 130 |
```
|
| 131 |
|
| 132 |
— *end example*]
|
| 133 |
\[*Example 5*:
|
| 134 |
``` cpp
|
|
@@ -152,15 +156,16 @@ follows:
|
|
| 152 |
S s3 { }; // OK, invoke #2
|
| 153 |
```
|
| 154 |
|
| 155 |
— *end example*]
|
| 156 |
- Otherwise, if `T` is an enumeration with a fixed underlying type
|
| 157 |
-
[[dcl.enum]] `U`, the *initializer-list* has a single element `v`
|
| 158 |
-
can be implicitly converted to `U`, and the
|
| 159 |
-
direct-list-initialization, the object is
|
| 160 |
-
`T(v)` [[expr.type.conv]]; if a narrowing
|
| 161 |
-
convert `v` to `U`, the program is
|
|
|
|
| 162 |
\[*Example 7*:
|
| 163 |
``` cpp
|
| 164 |
enum byte : unsigned char { };
|
| 165 |
byte b { 42 }; // OK
|
| 166 |
byte c = { 42 }; // error
|
|
@@ -177,12 +182,13 @@ follows:
|
|
| 177 |
enum class Handle : uint32_t { Invalid = 0 };
|
| 178 |
Handle h { 42 }; // OK
|
| 179 |
```
|
| 180 |
|
| 181 |
— *end example*]
|
| 182 |
-
- Otherwise, if the initializer list
|
| 183 |
-
and
|
|
|
|
| 184 |
reference-related to `E`, the object or reference is initialized from
|
| 185 |
that element (by copy-initialization for copy-list-initialization, or
|
| 186 |
by direct-initialization for direct-list-initialization); if a
|
| 187 |
narrowing conversion (see below) is required to convert the element to
|
| 188 |
`T`, the program is ill-formed.
|
|
@@ -218,10 +224,13 @@ follows:
|
|
| 218 |
const int (&iar)[2] = { 1, 2 }; // OK, iar is bound to temporary array
|
| 219 |
|
| 220 |
struct A { } a;
|
| 221 |
struct B { explicit B(const A&); };
|
| 222 |
const B& b2{a}; // error: cannot copy-list-initialize B temporary from A
|
|
|
|
|
|
|
|
|
|
| 223 |
```
|
| 224 |
|
| 225 |
— *end example*]
|
| 226 |
- Otherwise, if the initializer list has no elements, the object is
|
| 227 |
value-initialized.
|
|
@@ -269,49 +278,75 @@ even though ordinarily there are no sequencing constraints on the
|
|
| 269 |
arguments of a call. — *end note*]
|
| 270 |
|
| 271 |
An object of type `std::initializer_list<E>` is constructed from an
|
| 272 |
initializer list as if the implementation generated and materialized
|
| 273 |
[[conv.rval]] a prvalue of type “array of N `const E`”, where N is the
|
| 274 |
-
number of elements in the initializer list
|
| 275 |
-
|
| 276 |
-
|
| 277 |
-
to
|
|
|
|
| 278 |
|
| 279 |
[*Note 5*: A constructor or conversion function selected for the copy
|
| 280 |
-
|
| 281 |
initializer list. — *end note*]
|
| 282 |
|
| 283 |
If a narrowing conversion is required to initialize any of the elements,
|
| 284 |
the program is ill-formed.
|
| 285 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 286 |
[*Example 12*:
|
| 287 |
|
| 288 |
``` cpp
|
| 289 |
-
|
| 290 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 291 |
};
|
| 292 |
-
|
|
|
|
|
|
|
|
|
|
| 293 |
```
|
| 294 |
|
| 295 |
The initialization will be implemented in a way roughly equivalent to
|
| 296 |
this:
|
| 297 |
|
| 298 |
``` cpp
|
| 299 |
-
|
| 300 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 301 |
```
|
| 302 |
|
| 303 |
assuming that the implementation can construct an `initializer_list`
|
| 304 |
-
object with a pair of pointers
|
|
|
|
| 305 |
|
| 306 |
— *end example*]
|
| 307 |
|
| 308 |
-
The array has the same lifetime as any other temporary object
|
| 309 |
-
[[class.temporary]], except that initializing an `initializer_list`
|
| 310 |
-
object from the array extends the lifetime of the array exactly like
|
| 311 |
-
binding a reference to a temporary.
|
| 312 |
-
|
| 313 |
[*Example 13*:
|
| 314 |
|
| 315 |
``` cpp
|
| 316 |
typedef std::complex<double> cmplx;
|
| 317 |
std::vector<cmplx> v1 = { 1, 2, 3 };
|
|
@@ -335,22 +370,19 @@ variable, so the array persists for the lifetime of the variable. For
|
|
| 335 |
*ctor-initializer* as if by binding a temporary array to a reference
|
| 336 |
member, so the program is ill-formed [[class.base.init]].
|
| 337 |
|
| 338 |
— *end example*]
|
| 339 |
|
| 340 |
-
[*Note 6*: The implementation is free to allocate the array in
|
| 341 |
-
read-only memory if an explicit array with the same initializer can be
|
| 342 |
-
so allocated. — *end note*]
|
| 343 |
-
|
| 344 |
A *narrowing conversion* is an implicit conversion
|
| 345 |
|
| 346 |
- from a floating-point type to an integer type, or
|
| 347 |
- from a floating-point type `T` to another floating-point type whose
|
| 348 |
floating-point conversion rank is neither greater than nor equal to
|
| 349 |
-
that of `T`, except where the
|
| 350 |
-
|
| 351 |
-
|
|
|
|
| 352 |
- from an integer type or unscoped enumeration type to a floating-point
|
| 353 |
type, except where the source is a constant expression and the actual
|
| 354 |
value after conversion will fit into the target type and will produce
|
| 355 |
the original value when converted back to the original type, or
|
| 356 |
- from an integer type or unscoped enumeration type to an integer type
|
|
|
|
| 7 |
are called the *elements* of the initializer list. An initializer list
|
| 8 |
may be empty. List-initialization can occur in direct-initialization or
|
| 9 |
copy-initialization contexts; list-initialization in a
|
| 10 |
direct-initialization context is called *direct-list-initialization* and
|
| 11 |
list-initialization in a copy-initialization context is called
|
| 12 |
+
*copy-list-initialization*. Direct-initialization that is not
|
| 13 |
+
list-initialization is called *direct-non-list-initialization*.
|
| 14 |
|
| 15 |
[*Note 1*:
|
| 16 |
|
| 17 |
List-initialization can be used
|
| 18 |
|
| 19 |
+
- as the initializer in a variable definition [[dcl.init]],
|
| 20 |
+
- as the initializer in a *new-expression* [[expr.new]],
|
| 21 |
+
- in a `return` statement [[stmt.return]],
|
| 22 |
+
- as a *for-range-initializer* [[stmt.iter]],
|
| 23 |
+
- as a function argument [[expr.call]],
|
| 24 |
+
- as a template argument [[temp.arg.nontype]],
|
| 25 |
+
- as a subscript [[expr.sub]],
|
| 26 |
- as an argument to a constructor invocation
|
| 27 |
+
[[dcl.init]], [[expr.type.conv]],
|
| 28 |
+
- as an initializer for a non-static data member [[class.mem]],
|
| 29 |
+
- in a *mem-initializer* [[class.base.init]], or
|
| 30 |
+
- on the right-hand side of an assignment [[expr.assign]].
|
| 31 |
|
| 32 |
[*Example 1*:
|
| 33 |
|
| 34 |
``` cpp
|
| 35 |
int a = {1};
|
|
|
|
| 64 |
library declaration [[initializer.list.syn]], [[std.modules]] of
|
| 65 |
`std::initializer_list` is not reachable from [[module.reach]] a use of
|
| 66 |
`std::initializer_list` — even an implicit use in which the type is not
|
| 67 |
named [[dcl.spec.auto]] — the program is ill-formed.
|
| 68 |
|
| 69 |
+
List-initialization of an object or reference of type *cv* `T` is
|
| 70 |
+
defined as follows:
|
| 71 |
|
| 72 |
+
- If the *braced-init-list* contains a *designated-initializer-list* and
|
| 73 |
+
`T` is not a reference type, `T` shall be an aggregate class. The
|
| 74 |
+
ordered *identifier*s in the *designator*s of the
|
| 75 |
+
*designated-initializer-list* shall form a subsequence of the ordered
|
| 76 |
+
*identifier*s in the direct non-static data members of `T`. Aggregate
|
| 77 |
+
initialization is performed [[dcl.init.aggr]].
|
| 78 |
\[*Example 2*:
|
| 79 |
``` cpp
|
| 80 |
struct A { int x; int y; int z; };
|
| 81 |
A a{.y = 2, .x = 1}; // error: designator order does not match declaration order
|
| 82 |
A b{.x = 1, .z = 2}; // OK, b.y initialized to 0
|
| 83 |
```
|
| 84 |
|
| 85 |
— *end example*]
|
| 86 |
- If `T` is an aggregate class and the initializer list has a single
|
| 87 |
+
element of type *cv1* `U`, where `U` is `T` or a class derived from
|
| 88 |
`T`, the object is initialized from that element (by
|
| 89 |
copy-initialization for copy-list-initialization, or by
|
| 90 |
direct-initialization for direct-list-initialization).
|
| 91 |
- Otherwise, if `T` is a character array and the initializer list has a
|
| 92 |
single element that is an appropriately-typed *string-literal*
|
|
|
|
| 109 |
```
|
| 110 |
|
| 111 |
— *end example*]
|
| 112 |
- Otherwise, if the initializer list has no elements and `T` is a class
|
| 113 |
type with a default constructor, the object is value-initialized.
|
| 114 |
+
- Otherwise, if `T` is a specialization of `std::initializer_list`, the
|
| 115 |
+
object is constructed as described below.
|
| 116 |
- Otherwise, if `T` is a class type, constructors are considered. The
|
| 117 |
applicable constructors are enumerated and the best one is chosen
|
| 118 |
through overload resolution [[over.match]], [[over.match.list]]. If a
|
| 119 |
narrowing conversion (see below) is required to convert any of the
|
| 120 |
arguments, the program is ill-formed.
|
| 121 |
\[*Example 4*:
|
| 122 |
``` cpp
|
| 123 |
struct S {
|
| 124 |
S(std::initializer_list<double>); // #1
|
| 125 |
S(std::initializer_list<int>); // #2
|
| 126 |
+
S(std::initializer_list<S>); // #3
|
| 127 |
+
S(); // #4
|
| 128 |
// ...
|
| 129 |
};
|
| 130 |
S s1 = { 1.0, 2.0, 3.0 }; // invoke #1
|
| 131 |
S s2 = { 1, 2, 3 }; // invoke #2
|
| 132 |
+
S s3{s2}; // invoke #3 (not the copy constructor)
|
| 133 |
+
S s4 = { }; // invoke #4
|
| 134 |
```
|
| 135 |
|
| 136 |
— *end example*]
|
| 137 |
\[*Example 5*:
|
| 138 |
``` cpp
|
|
|
|
| 156 |
S s3 { }; // OK, invoke #2
|
| 157 |
```
|
| 158 |
|
| 159 |
— *end example*]
|
| 160 |
- Otherwise, if `T` is an enumeration with a fixed underlying type
|
| 161 |
+
[[dcl.enum]] `U`, the *initializer-list* has a single element `v` of
|
| 162 |
+
scalar type, `v` can be implicitly converted to `U`, and the
|
| 163 |
+
initialization is direct-list-initialization, the object is
|
| 164 |
+
initialized with the value `T(v)` [[expr.type.conv]]; if a narrowing
|
| 165 |
+
conversion is required to convert `v` to `U`, the program is
|
| 166 |
+
ill-formed.
|
| 167 |
\[*Example 7*:
|
| 168 |
``` cpp
|
| 169 |
enum byte : unsigned char { };
|
| 170 |
byte b { 42 }; // OK
|
| 171 |
byte c = { 42 }; // error
|
|
|
|
| 182 |
enum class Handle : uint32_t { Invalid = 0 };
|
| 183 |
Handle h { 42 }; // OK
|
| 184 |
```
|
| 185 |
|
| 186 |
— *end example*]
|
| 187 |
+
- Otherwise, if the initializer list is not a
|
| 188 |
+
*designated-initializer-list* and has a single element of type `E` and
|
| 189 |
+
either `T` is not a reference type or its referenced type is
|
| 190 |
reference-related to `E`, the object or reference is initialized from
|
| 191 |
that element (by copy-initialization for copy-list-initialization, or
|
| 192 |
by direct-initialization for direct-list-initialization); if a
|
| 193 |
narrowing conversion (see below) is required to convert the element to
|
| 194 |
`T`, the program is ill-formed.
|
|
|
|
| 224 |
const int (&iar)[2] = { 1, 2 }; // OK, iar is bound to temporary array
|
| 225 |
|
| 226 |
struct A { } a;
|
| 227 |
struct B { explicit B(const A&); };
|
| 228 |
const B& b2{a}; // error: cannot copy-list-initialize B temporary from A
|
| 229 |
+
|
| 230 |
+
struct C { int x; };
|
| 231 |
+
C&& c = { .x = 1 }; // OK
|
| 232 |
```
|
| 233 |
|
| 234 |
— *end example*]
|
| 235 |
- Otherwise, if the initializer list has no elements, the object is
|
| 236 |
value-initialized.
|
|
|
|
| 278 |
arguments of a call. — *end note*]
|
| 279 |
|
| 280 |
An object of type `std::initializer_list<E>` is constructed from an
|
| 281 |
initializer list as if the implementation generated and materialized
|
| 282 |
[[conv.rval]] a prvalue of type “array of N `const E`”, where N is the
|
| 283 |
+
number of elements in the initializer list; this is called the
|
| 284 |
+
initializer list’s *backing array*. Each element of the backing array is
|
| 285 |
+
copy-initialized with the corresponding element of the initializer list,
|
| 286 |
+
and the `std::initializer_list<E>` object is constructed to refer to
|
| 287 |
+
that array.
|
| 288 |
|
| 289 |
[*Note 5*: A constructor or conversion function selected for the copy
|
| 290 |
+
needs to be accessible [[class.access]] in the context of the
|
| 291 |
initializer list. — *end note*]
|
| 292 |
|
| 293 |
If a narrowing conversion is required to initialize any of the elements,
|
| 294 |
the program is ill-formed.
|
| 295 |
|
| 296 |
+
[*Note 6*: Backing arrays are potentially non-unique objects
|
| 297 |
+
[[intro.object]]. — *end note*]
|
| 298 |
+
|
| 299 |
+
The backing array has the same lifetime as any other temporary object
|
| 300 |
+
[[class.temporary]], except that initializing an `initializer_list`
|
| 301 |
+
object from the array extends the lifetime of the array exactly like
|
| 302 |
+
binding a reference to a temporary.
|
| 303 |
+
|
| 304 |
[*Example 12*:
|
| 305 |
|
| 306 |
``` cpp
|
| 307 |
+
void f(std::initializer_list<double> il);
|
| 308 |
+
void g(float x) {
|
| 309 |
+
f({1, x, 3});
|
| 310 |
+
}
|
| 311 |
+
void h() {
|
| 312 |
+
f({1, 2, 3});
|
| 313 |
+
}
|
| 314 |
+
|
| 315 |
+
struct A {
|
| 316 |
+
mutable int i;
|
| 317 |
};
|
| 318 |
+
void q(std::initializer_list<A>);
|
| 319 |
+
void r() {
|
| 320 |
+
q({A{1}, A{2}, A{3}});
|
| 321 |
+
}
|
| 322 |
```
|
| 323 |
|
| 324 |
The initialization will be implemented in a way roughly equivalent to
|
| 325 |
this:
|
| 326 |
|
| 327 |
``` cpp
|
| 328 |
+
void g(float x) {
|
| 329 |
+
const double __a[3] = {double{1}, double{x}, double{3}}; // backing array
|
| 330 |
+
f(std::initializer_list<double>(__a, __a+3));
|
| 331 |
+
}
|
| 332 |
+
void h() {
|
| 333 |
+
static constexpr double __b[3] = {double{1}, double{2}, double{3}}; // backing array
|
| 334 |
+
f(std::initializer_list<double>(__b, __b+3));
|
| 335 |
+
}
|
| 336 |
+
void r() {
|
| 337 |
+
const A __c[3] = {A{1}, A{2}, A{3}}; // backing array
|
| 338 |
+
q(std::initializer_list<A>(__c, __c+3));
|
| 339 |
+
}
|
| 340 |
```
|
| 341 |
|
| 342 |
assuming that the implementation can construct an `initializer_list`
|
| 343 |
+
object with a pair of pointers, and with the understanding that `__b`
|
| 344 |
+
does not outlive the call to `f`.
|
| 345 |
|
| 346 |
— *end example*]
|
| 347 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 348 |
[*Example 13*:
|
| 349 |
|
| 350 |
``` cpp
|
| 351 |
typedef std::complex<double> cmplx;
|
| 352 |
std::vector<cmplx> v1 = { 1, 2, 3 };
|
|
|
|
| 370 |
*ctor-initializer* as if by binding a temporary array to a reference
|
| 371 |
member, so the program is ill-formed [[class.base.init]].
|
| 372 |
|
| 373 |
— *end example*]
|
| 374 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 375 |
A *narrowing conversion* is an implicit conversion
|
| 376 |
|
| 377 |
- from a floating-point type to an integer type, or
|
| 378 |
- from a floating-point type `T` to another floating-point type whose
|
| 379 |
floating-point conversion rank is neither greater than nor equal to
|
| 380 |
+
that of `T`, except where the result of the conversion is a constant
|
| 381 |
+
expression and either its value is finite and the conversion did not
|
| 382 |
+
overflow, or the values before and after the conversion are not
|
| 383 |
+
finite, or
|
| 384 |
- from an integer type or unscoped enumeration type to a floating-point
|
| 385 |
type, except where the source is a constant expression and the actual
|
| 386 |
value after conversion will fit into the target type and will produce
|
| 387 |
the original value when converted back to the original type, or
|
| 388 |
- from an integer type or unscoped enumeration type to an integer type
|