From Jason Turner

[dcl.init.list]

Diff to HTML by rtfpessoa

Files changed (1) hide show
  1. tmp/tmp2e7gq8hg/{from.md → to.md} +86 -54
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 subscript [[expr.sub]]
 
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.ass]]
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 defined as
68
- follows:
69
 
70
- - If the *braced-init-list* contains a *designated-initializer-list*,
71
- `T` shall be an aggregate class. The ordered *identifier*s in the
72
- *designator*s of the *designated-initializer-list* shall form a
73
- subsequence of the ordered *identifier*s in the direct non-static data
74
- members of `T`. Aggregate initialization is performed
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 *cv* `U`, where `U` is `T` or a class derived from
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<E>`,
113
- the object is constructed as described below.
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(); // #3
 
125
  // ...
126
  };
127
  S s1 = { 1.0, 2.0, 3.0 }; // invoke #1
128
  S s2 = { 1, 2, 3 }; // invoke #2
129
- S s3 = { }; // invoke #3
 
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`, `v`
158
- can be implicitly converted to `U`, and the initialization is
159
- direct-list-initialization, the object is initialized with the value
160
- `T(v)` [[expr.type.conv]]; if a narrowing conversion is required to
161
- convert `v` to `U`, the program is ill-formed.
 
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 has a single element of type `E`
183
- and either `T` is not a reference type or its referenced type is
 
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. Each element of that array
275
- is copy-initialized with the corresponding element of the initializer
276
- list, and the `std::initializer_list<E>` object is constructed to refer
277
- to that array.
 
278
 
279
  [*Note 5*: A constructor or conversion function selected for the copy
280
- is required to be accessible [[class.access]] in the context of the
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
- struct X {
290
- X(std::initializer_list<double> v);
 
 
 
 
 
 
 
 
291
  };
292
- X x{ 1,2,3 };
 
 
 
293
  ```
294
 
295
  The initialization will be implemented in a way roughly equivalent to
296
  this:
297
 
298
  ``` cpp
299
- const double __a[3] = {double{1}, double{2}, double{3}};
300
- X x(std::initializer_list<double>(__a, __a+3));
 
 
 
 
 
 
 
 
 
 
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 source is a constant expression and the
350
- actual value after conversion is within the range of values that can
351
- be represented (even if it cannot be represented exactly), or
 
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