tmp/tmp2o3rgo0x/{from.md → to.md}
RENAMED
|
@@ -19,12 +19,12 @@ List-initialization can be used
|
|
| 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 |
-
[[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*:
|
|
@@ -56,12 +56,13 @@ initializer list as the argument to the constructor template
|
|
| 56 |
`template<class T> C(T)` of a class `C` does not create an
|
| 57 |
initializer-list constructor, because an initializer list argument
|
| 58 |
causes the corresponding parameter to be a non-deduced context
|
| 59 |
[[temp.deduct.call]]. — *end note*]
|
| 60 |
|
| 61 |
-
The template `std::initializer_list` is not predefined; if
|
| 62 |
-
|
|
|
|
| 63 |
`std::initializer_list` — even an implicit use in which the type is not
|
| 64 |
named [[dcl.spec.auto]] — the program is ill-formed.
|
| 65 |
|
| 66 |
List-initialization of an object or reference of type `T` is defined as
|
| 67 |
follows:
|
|
@@ -100,22 +101,22 @@ follows:
|
|
| 100 |
int m1;
|
| 101 |
double m2, m3;
|
| 102 |
};
|
| 103 |
S2 s21 = { 1, 2, 3.0 }; // OK
|
| 104 |
S2 s22 { 1.0, 2, 3 }; // error: narrowing
|
| 105 |
-
S2 s23 { }; // OK
|
| 106 |
```
|
| 107 |
|
| 108 |
— *end example*]
|
| 109 |
- Otherwise, if the initializer list has no elements and `T` is a class
|
| 110 |
type with a default constructor, the object is value-initialized.
|
| 111 |
- Otherwise, if `T` is a specialization of `std::initializer_list<E>`,
|
| 112 |
the object is constructed as described below.
|
| 113 |
- Otherwise, if `T` is a class type, constructors are considered. The
|
| 114 |
applicable constructors are enumerated and the best one is chosen
|
| 115 |
-
through overload resolution
|
| 116 |
-
|
| 117 |
arguments, the program is ill-formed.
|
| 118 |
\[*Example 4*:
|
| 119 |
``` cpp
|
| 120 |
struct S {
|
| 121 |
S(std::initializer_list<double>); // #1
|
|
@@ -144,13 +145,13 @@ follows:
|
|
| 144 |
// no initializer-list constructors
|
| 145 |
S(int, double, double); // #1
|
| 146 |
S(); // #2
|
| 147 |
// ...
|
| 148 |
};
|
| 149 |
-
S s1 = { 1, 2, 3.0 }; // OK
|
| 150 |
S s2 { 1.0, 2, 3 }; // error: narrowing
|
| 151 |
-
S s3 { }; // OK
|
| 152 |
```
|
| 153 |
|
| 154 |
— *end example*]
|
| 155 |
- Otherwise, if `T` is an enumeration with a fixed underlying type
|
| 156 |
[[dcl.enum]] `U`, the *initializer-list* has a single element `v`, `v`
|
|
@@ -191,32 +192,32 @@ follows:
|
|
| 191 |
int x2 {2.0}; // error: narrowing
|
| 192 |
```
|
| 193 |
|
| 194 |
— *end example*]
|
| 195 |
- Otherwise, if `T` is a reference type, a prvalue is generated. The
|
| 196 |
-
prvalue initializes its result object by copy-list-initialization
|
| 197 |
-
prvalue is then used to direct-initialize
|
| 198 |
-
the
|
| 199 |
-
to array of unknown bound of `U`”, in which
|
| 200 |
-
|
| 201 |
-
the initializer list.
|
| 202 |
\[*Note 3*: As usual, the binding will fail and the program is
|
| 203 |
ill-formed if the reference type is an lvalue reference to a non-const
|
| 204 |
type. — *end note*]
|
| 205 |
\[*Example 9*:
|
| 206 |
``` cpp
|
| 207 |
struct S {
|
| 208 |
S(std::initializer_list<double>); // #1
|
| 209 |
S(const std::string&); // #2
|
| 210 |
// ...
|
| 211 |
};
|
| 212 |
-
const S& r1 = { 1, 2, 3.0 }; // OK
|
| 213 |
-
const S& r2 { "Spinach" }; // OK
|
| 214 |
S& r3 = { 1, 2, 3 }; // error: initializer is not an lvalue
|
| 215 |
const int& i1 = { 1 }; // OK
|
| 216 |
const int& i2 = { 1.1 }; // error: narrowing
|
| 217 |
-
const int (&iar)[2] = { 1, 2 }; // OK
|
| 218 |
|
| 219 |
struct A { } a;
|
| 220 |
struct B { explicit B(const A&); };
|
| 221 |
const B& b2{a}; // error: cannot copy-list-initialize B temporary from A
|
| 222 |
```
|
|
@@ -335,27 +336,34 @@ variable, so the array persists for the lifetime of the variable. For
|
|
| 335 |
member, so the program is ill-formed [[class.base.init]].
|
| 336 |
|
| 337 |
— *end example*]
|
| 338 |
|
| 339 |
[*Note 6*: The implementation is free to allocate the array in
|
| 340 |
-
read-only memory if an explicit array with the same initializer
|
| 341 |
so allocated. — *end note*]
|
| 342 |
|
| 343 |
A *narrowing conversion* is an implicit conversion
|
| 344 |
|
| 345 |
- from a floating-point type to an integer type, or
|
| 346 |
-
- from
|
| 347 |
-
|
|
|
|
| 348 |
actual value after conversion is within the range of values that can
|
| 349 |
be represented (even if it cannot be represented exactly), or
|
| 350 |
- from an integer type or unscoped enumeration type to a floating-point
|
| 351 |
type, except where the source is a constant expression and the actual
|
| 352 |
value after conversion will fit into the target type and will produce
|
| 353 |
the original value when converted back to the original type, or
|
| 354 |
- from an integer type or unscoped enumeration type to an integer type
|
| 355 |
that cannot represent all the values of the original type, except
|
| 356 |
-
where
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 357 |
promotions will fit into the target type, or
|
| 358 |
- from a pointer type or a pointer-to-member type to `bool`.
|
| 359 |
|
| 360 |
[*Note 7*: As indicated above, such conversions are not allowed at the
|
| 361 |
top level in list-initializations. — *end note*]
|
|
@@ -364,24 +372,24 @@ top level in list-initializations. — *end note*]
|
|
| 364 |
|
| 365 |
``` cpp
|
| 366 |
int x = 999; // x is not a constant expression
|
| 367 |
const int y = 999;
|
| 368 |
const int z = 99;
|
| 369 |
-
char c1 = x; // OK, though it
|
| 370 |
-
char c2{x}; // error:
|
| 371 |
char c3{y}; // error: narrows (assuming char is 8 bits)
|
| 372 |
-
char c4{z}; // OK
|
| 373 |
-
unsigned char uc1 = {5}; // OK
|
| 374 |
unsigned char uc2 = {-1}; // error: narrows
|
| 375 |
unsigned int ui1 = {-1}; // error: narrows
|
| 376 |
signed int si1 =
|
| 377 |
{ (unsigned int)-1 }; // error: narrows
|
| 378 |
int ii = {2.0}; // error: narrows
|
| 379 |
-
float f1 { x }; // error:
|
| 380 |
-
float f2 { 7 }; // OK
|
| 381 |
bool b = {"meow"}; // error: narrows
|
| 382 |
int f(int);
|
| 383 |
-
int a[] = { 2, f(2), f(2.0) }; // OK
|
| 384 |
```
|
| 385 |
|
| 386 |
— *end example*]
|
| 387 |
|
|
|
|
| 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*:
|
|
|
|
| 56 |
`template<class T> C(T)` of a class `C` does not create an
|
| 57 |
initializer-list constructor, because an initializer list argument
|
| 58 |
causes the corresponding parameter to be a non-deduced context
|
| 59 |
[[temp.deduct.call]]. — *end note*]
|
| 60 |
|
| 61 |
+
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:
|
|
|
|
| 101 |
int m1;
|
| 102 |
double m2, m3;
|
| 103 |
};
|
| 104 |
S2 s21 = { 1, 2, 3.0 }; // OK
|
| 105 |
S2 s22 { 1.0, 2, 3 }; // error: narrowing
|
| 106 |
+
S2 s23 { }; // OK, default to 0,0,0
|
| 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
|
|
|
|
| 145 |
// no initializer-list constructors
|
| 146 |
S(int, double, double); // #1
|
| 147 |
S(); // #2
|
| 148 |
// ...
|
| 149 |
};
|
| 150 |
+
S s1 = { 1, 2, 3.0 }; // OK, invoke #1
|
| 151 |
S s2 { 1.0, 2, 3 }; // error: narrowing
|
| 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`
|
|
|
|
| 192 |
int x2 {2.0}; // error: narrowing
|
| 193 |
```
|
| 194 |
|
| 195 |
— *end example*]
|
| 196 |
- Otherwise, if `T` is a reference type, a prvalue is generated. The
|
| 197 |
+
prvalue initializes its result object by copy-list-initialization from
|
| 198 |
+
the initializer list. The prvalue is then used to direct-initialize
|
| 199 |
+
the reference. The type of the prvalue is the type referenced by `T`,
|
| 200 |
+
unless `T` is “reference to array of unknown bound of `U`”, in which
|
| 201 |
+
case the type of the prvalue is the type of `x` in the declaration
|
| 202 |
+
`U x[] H`, where H is the initializer list.
|
| 203 |
\[*Note 3*: As usual, the binding will fail and the program is
|
| 204 |
ill-formed if the reference type is an lvalue reference to a non-const
|
| 205 |
type. — *end note*]
|
| 206 |
\[*Example 9*:
|
| 207 |
``` cpp
|
| 208 |
struct S {
|
| 209 |
S(std::initializer_list<double>); // #1
|
| 210 |
S(const std::string&); // #2
|
| 211 |
// ...
|
| 212 |
};
|
| 213 |
+
const S& r1 = { 1, 2, 3.0 }; // OK, invoke #1
|
| 214 |
+
const S& r2 { "Spinach" }; // OK, invoke #2
|
| 215 |
S& r3 = { 1, 2, 3 }; // error: initializer is not an lvalue
|
| 216 |
const int& i1 = { 1 }; // OK
|
| 217 |
const int& i2 = { 1.1 }; // error: narrowing
|
| 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 |
```
|
|
|
|
| 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
|
| 357 |
that cannot represent all the values of the original type, except
|
| 358 |
+
where
|
| 359 |
+
- the source is a bit-field whose width w is less than that of its
|
| 360 |
+
type (or, for an enumeration type, its underlying type) and the
|
| 361 |
+
target type can represent all the values of a hypothetical extended
|
| 362 |
+
integer type with width w and with the same signedness as the
|
| 363 |
+
original type or
|
| 364 |
+
- the source is a constant expression whose value after integral
|
| 365 |
promotions will fit into the target type, or
|
| 366 |
- from a pointer type or a pointer-to-member type to `bool`.
|
| 367 |
|
| 368 |
[*Note 7*: As indicated above, such conversions are not allowed at the
|
| 369 |
top level in list-initializations. — *end note*]
|
|
|
|
| 372 |
|
| 373 |
``` cpp
|
| 374 |
int x = 999; // x is not a constant expression
|
| 375 |
const int y = 999;
|
| 376 |
const int z = 99;
|
| 377 |
+
char c1 = x; // OK, though it potentially narrows (in this case, it does narrow)
|
| 378 |
+
char c2{x}; // error: potentially narrows
|
| 379 |
char c3{y}; // error: narrows (assuming char is 8 bits)
|
| 380 |
+
char c4{z}; // OK, no narrowing needed
|
| 381 |
+
unsigned char uc1 = {5}; // OK, no narrowing needed
|
| 382 |
unsigned char uc2 = {-1}; // error: narrows
|
| 383 |
unsigned int ui1 = {-1}; // error: narrows
|
| 384 |
signed int si1 =
|
| 385 |
{ (unsigned int)-1 }; // error: narrows
|
| 386 |
int ii = {2.0}; // error: narrows
|
| 387 |
+
float f1 { x }; // error: potentially narrows
|
| 388 |
+
float f2 { 7 }; // OK, 7 can be exactly represented as a float
|
| 389 |
bool b = {"meow"}; // error: narrows
|
| 390 |
int f(int);
|
| 391 |
+
int a[] = { 2, f(2), f(2.0) }; // OK, the double-to-int conversion is not at the top level
|
| 392 |
```
|
| 393 |
|
| 394 |
— *end example*]
|
| 395 |
|