tmp/tmpi5fxs06g/{from.md → to.md}
RENAMED
|
@@ -2,44 +2,63 @@
|
|
| 2 |
|
| 3 |
*Placeholder type deduction* is the process by which a type containing a
|
| 4 |
placeholder type is replaced by a deduced type.
|
| 5 |
|
| 6 |
A type `T` containing a placeholder type, and a corresponding
|
| 7 |
-
initializer E, are determined as follows:
|
| 8 |
|
| 9 |
-
-
|
| 10 |
declared with a return type that contains a placeholder type, `T` is
|
| 11 |
-
the declared return type
|
| 12 |
-
|
| 13 |
-
|
| 14 |
-
|
| 15 |
-
|
| 16 |
-
|
| 17 |
-
|
| 18 |
-
|
| 19 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 20 |
placeholder type, `T` is the declared type of the non-type template
|
| 21 |
parameter and E is the corresponding template argument.
|
| 22 |
|
| 23 |
-
|
| 24 |
-
of type `void`, `T` shall be either *type-constraint*ₒₚₜ
|
| 25 |
-
`decltype(auto)` or cv *type-constraint*ₒₚₜ `auto`.
|
| 26 |
-
|
| 27 |
-
If the deduction is for a `return` statement and E is a
|
| 28 |
-
*braced-init-list* [[dcl.init.list]], the program is ill-formed.
|
| 29 |
|
| 30 |
If the *placeholder-type-specifier* is of the form *type-constraint*ₒₚₜ
|
| 31 |
`auto`, the deduced type T' replacing `T` is determined using the rules
|
| 32 |
-
for template argument deduction.
|
| 33 |
-
|
| 34 |
-
|
| 35 |
-
|
| 36 |
-
|
| 37 |
-
|
| 38 |
-
|
| 39 |
-
|
| 40 |
-
|
|
|
|
|
|
|
|
|
|
| 41 |
|
| 42 |
[*Example 8*:
|
| 43 |
|
| 44 |
``` cpp
|
| 45 |
auto x1 = { 1, 2 }; // decltype(x1) is std::initializer_list<int>
|
|
@@ -66,12 +85,12 @@ template <class U> void f(const U& u);
|
|
| 66 |
|
| 67 |
— *end example*]
|
| 68 |
|
| 69 |
If the *placeholder-type-specifier* is of the form *type-constraint*ₒₚₜ
|
| 70 |
`decltype(auto)`, `T` shall be the placeholder alone. The type deduced
|
| 71 |
-
for `T` is determined as described in [[dcl.type.
|
| 72 |
-
had been the operand of the `decltype`.
|
| 73 |
|
| 74 |
[*Example 10*:
|
| 75 |
|
| 76 |
``` cpp
|
| 77 |
int i;
|
|
@@ -86,10 +105,12 @@ auto x5a = f(); // decltype(x5a) is int
|
|
| 86 |
decltype(auto) x5d = f(); // decltype(x5d) is int&&
|
| 87 |
auto x6a = { 1, 2 }; // decltype(x6a) is std::initializer_list<int>
|
| 88 |
decltype(auto) x6d = { 1, 2 }; // error: { 1, 2 } is not an expression
|
| 89 |
auto *x7a = &i; // decltype(x7a) is int*
|
| 90 |
decltype(auto)*x7d = &i; // error: declared type is not plain decltype(auto)
|
|
|
|
|
|
|
| 91 |
```
|
| 92 |
|
| 93 |
— *end example*]
|
| 94 |
|
| 95 |
For a *placeholder-type-specifier* with a *type-constraint*, the
|
|
|
|
| 2 |
|
| 3 |
*Placeholder type deduction* is the process by which a type containing a
|
| 4 |
placeholder type is replaced by a deduced type.
|
| 5 |
|
| 6 |
A type `T` containing a placeholder type, and a corresponding
|
| 7 |
+
*initializer-clause* E, are determined as follows:
|
| 8 |
|
| 9 |
+
- For a non-discarded `return` statement that occurs in a function
|
| 10 |
declared with a return type that contains a placeholder type, `T` is
|
| 11 |
+
the declared return type.
|
| 12 |
+
- If the `return` statement has no operand, then E is `void()`.
|
| 13 |
+
- If the operand is a *braced-init-list* [[dcl.init.list]], the
|
| 14 |
+
program is ill-formed.
|
| 15 |
+
- If the operand is an *expression* X that is not an
|
| 16 |
+
*assignment-expression*, E is `(X)`. \[*Note 4*: A comma expression
|
| 17 |
+
[[expr.comma]] is not an *assignment-expression*. — *end note*]
|
| 18 |
+
- Otherwise, E is the operand of the `return` statement.
|
| 19 |
+
|
| 20 |
+
If E has type `void`, `T` shall be either *type-constraint*ₒₚₜ
|
| 21 |
+
`decltype(auto)` or cv *type-constraint*ₒₚₜ `auto`.
|
| 22 |
+
- For a variable declared with a type that contains a placeholder type,
|
| 23 |
+
`T` is the declared type of the variable.
|
| 24 |
+
- If the initializer of the variable is a *brace-or-equal-initializer*
|
| 25 |
+
of the form `= initializer-clause`, E is the *initializer-clause*.
|
| 26 |
+
- If the initializer is a *braced-init-list*, it shall consist of a
|
| 27 |
+
single brace-enclosed *assignment-expression* and E is the
|
| 28 |
+
*assignment-expression*.
|
| 29 |
+
- If the initializer is a parenthesized *expression-list*, the
|
| 30 |
+
*expression-list* shall be a single *assignment-expression* and E is
|
| 31 |
+
the *assignment-expression*.
|
| 32 |
+
- For an explicit type conversion [[expr.type.conv]], `T` is the
|
| 33 |
+
specified type, which shall be `auto`.
|
| 34 |
+
- If the initializer is a *braced-init-list*, it shall consist of a
|
| 35 |
+
single brace-enclosed *assignment-expression* and E is the
|
| 36 |
+
*assignment-expression*.
|
| 37 |
+
- If the initializer is a parenthesized *expression-list*, the
|
| 38 |
+
*expression-list* shall be a single *assignment-expression* and E is
|
| 39 |
+
the *assignment-expression*.
|
| 40 |
+
- For a non-type template parameter declared with a type that contains a
|
| 41 |
placeholder type, `T` is the declared type of the non-type template
|
| 42 |
parameter and E is the corresponding template argument.
|
| 43 |
|
| 44 |
+
`T` shall not be an array type.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 45 |
|
| 46 |
If the *placeholder-type-specifier* is of the form *type-constraint*ₒₚₜ
|
| 47 |
`auto`, the deduced type T' replacing `T` is determined using the rules
|
| 48 |
+
for template argument deduction. If the initialization is
|
| 49 |
+
copy-list-initialization, a declaration of `std::initializer_list` shall
|
| 50 |
+
precede [[basic.lookup.general]] the *placeholder-type-specifier*.
|
| 51 |
+
Obtain `P` from `T` by replacing the occurrences of
|
| 52 |
+
*type-constraint*ₒₚₜ `auto` either with a new invented type template
|
| 53 |
+
parameter `U` or, if the initialization is copy-list-initialization,
|
| 54 |
+
with `std::initializer_list<U>`. Deduce a value for `U` using the rules
|
| 55 |
+
of template argument deduction from a function call
|
| 56 |
+
[[temp.deduct.call]], where `P` is a function template parameter type
|
| 57 |
+
and the corresponding argument is E. If the deduction fails, the
|
| 58 |
+
declaration is ill-formed. Otherwise, T' is obtained by substituting the
|
| 59 |
+
deduced `U` into `P`.
|
| 60 |
|
| 61 |
[*Example 8*:
|
| 62 |
|
| 63 |
``` cpp
|
| 64 |
auto x1 = { 1, 2 }; // decltype(x1) is std::initializer_list<int>
|
|
|
|
| 85 |
|
| 86 |
— *end example*]
|
| 87 |
|
| 88 |
If the *placeholder-type-specifier* is of the form *type-constraint*ₒₚₜ
|
| 89 |
`decltype(auto)`, `T` shall be the placeholder alone. The type deduced
|
| 90 |
+
for `T` is determined as described in [[dcl.type.decltype]], as though
|
| 91 |
+
E had been the operand of the `decltype`.
|
| 92 |
|
| 93 |
[*Example 10*:
|
| 94 |
|
| 95 |
``` cpp
|
| 96 |
int i;
|
|
|
|
| 105 |
decltype(auto) x5d = f(); // decltype(x5d) is int&&
|
| 106 |
auto x6a = { 1, 2 }; // decltype(x6a) is std::initializer_list<int>
|
| 107 |
decltype(auto) x6d = { 1, 2 }; // error: { 1, 2 } is not an expression
|
| 108 |
auto *x7a = &i; // decltype(x7a) is int*
|
| 109 |
decltype(auto)*x7d = &i; // error: declared type is not plain decltype(auto)
|
| 110 |
+
auto f1(int x) -> decltype((x)) { return (x); } // return type is int&
|
| 111 |
+
auto f2(int x) -> decltype(auto) { return (x); } // return type is int&&
|
| 112 |
```
|
| 113 |
|
| 114 |
— *end example*]
|
| 115 |
|
| 116 |
For a *placeholder-type-specifier* with a *type-constraint*, the
|