From Jason Turner

[dcl.spec.auto]

Diff to HTML by rtfpessoa

Files changed (1) hide show
  1. tmp/tmpzmt340_k/{from.md → to.md} +78 -62
tmp/tmpzmt340_k/{from.md → to.md} RENAMED
@@ -1,7 +1,9 @@
1
  #### Placeholder type specifiers <a id="dcl.spec.auto">[[dcl.spec.auto]]</a>
2
 
 
 
3
  ``` bnf
4
  placeholder-type-specifier:
5
  type-constraintₒₚₜ auto
6
  type-constraintₒₚₜ decltype '(' auto ')'
7
  ```
@@ -18,11 +20,11 @@ placeholder* of the function declaration or *lambda-expression*.
18
 
19
  [*Note 1*: Having a generic parameter type placeholder signifies that
20
  the function is an abbreviated function template [[dcl.fct]] or the
21
  lambda is a generic lambda [[expr.prim.lambda]]. — *end note*]
22
 
23
- The placeholder type can appear with a function declarator in the
24
  *decl-specifier-seq*, *type-specifier-seq*, *conversion-function-id*, or
25
  *trailing-return-type*, in any context where such a declarator is valid.
26
  If the function declarator includes a *trailing-return-type*
27
  [[dcl.fct]], that *trailing-return-type* specifies the declared return
28
  type of the function. Otherwise, the function declarator shall declare a
@@ -34,54 +36,49 @@ non-discarded `return` statements, if any, in the body of the function
34
  The type of a variable declared using a placeholder type is deduced from
35
  its initializer. This use is allowed in an initializing declaration
36
  [[dcl.init]] of a variable. The placeholder type shall appear as one of
37
  the *decl-specifier*s in the *decl-specifier-seq* and the
38
  *decl-specifier-seq* shall be followed by one or more *declarator*s,
39
- each of which shall be followed by a non-empty *initializer*. In an
40
- *initializer* of the form
41
-
42
- ``` cpp
43
- ( expression-list )
44
- ```
45
-
46
- the *expression-list* shall be a single *assignment-expression*.
47
 
48
  [*Example 1*:
49
 
50
  ``` cpp
51
- auto x = 5; // OK: x has type int
52
- const auto *v = &x, u = 6; // OK: v has type const int*, u has type const int
53
- static auto y = 0.0; // OK: y has type double
54
  auto int r; // error: auto is not a storage-class-specifier
55
- auto f() -> int; // OK: f returns int
56
- auto g() { return 0.0; } // OK: g returns double
57
- auto h(); // OK: h's return type will be deduced when it is defined
58
  ```
59
 
60
  — *end example*]
61
 
62
  The `auto` *type-specifier* can also be used to introduce a structured
63
  binding declaration [[dcl.struct.bind]].
64
 
65
  A placeholder type can also be used in the *type-specifier-seq* in the
66
  *new-type-id* or *type-id* of a *new-expression* [[expr.new]] and as a
67
  *decl-specifier* of the *parameter-declaration*'s *decl-specifier-seq*
68
- in a *template-parameter* [[temp.param]].
 
 
69
 
70
  A program that uses a placeholder type in a context not explicitly
71
- allowed in this subclause is ill-formed.
72
 
73
  If the *init-declarator-list* contains more than one *init-declarator*,
74
  they shall all form declarations of variables. The type of each declared
75
  variable is determined by placeholder type deduction
76
  [[dcl.type.auto.deduct]], and if the type that replaces the placeholder
77
  type is not the same in each deduction, the program is ill-formed.
78
 
79
  [*Example 2*:
80
 
81
  ``` cpp
82
- auto x = 5, *y = &x; // OK: auto is int
83
  auto a = 5, b = { 1, 2 }; // error: different types for auto
84
  ```
85
 
86
  — *end example*]
87
 
@@ -109,15 +106,15 @@ type shall be defined in the translation unit containing its exported
109
  declaration, outside the *private-module-fragment* (if any).
110
 
111
  [*Note 2*: The deduced return type cannot have a name with internal
112
  linkage [[basic.link]]. — *end note*]
113
 
114
- If the name of an entity with an undeduced placeholder type appears in
115
- an expression, the program is ill-formed. Once a non-discarded `return`
116
- statement has been seen in a function, however, the return type deduced
117
- from that statement can be used in the rest of the function, including
118
- in other `return` statements.
119
 
120
  [*Example 4*:
121
 
122
  ``` cpp
123
  auto n = n; // error: n's initializer refers to n
@@ -131,14 +128,14 @@ auto sum(int i) {
131
  }
132
  ```
133
 
134
  — *end example*]
135
 
136
- Return type deduction for a templated entity that is a function or
137
- function template with a placeholder in its declared type occurs when
138
- the definition is instantiated even if the function body contains a
139
- `return` statement with a non-type-dependent operand.
140
 
141
  [*Note 3*: Therefore, any use of a specialization of the function
142
  template will cause an implicit instantiation. Any errors that arise
143
  from this instantiation are not in the immediate context of the function
144
  type and can result in the program being ill-formed
@@ -154,24 +151,22 @@ void g() { int (*p)(int*) = &f; } // instantiates both fs to deter
154
  // chooses second
155
  ```
156
 
157
  — *end example*]
158
 
159
- Redeclarations or specializations of a function or function template
160
- with a declared return type that uses a placeholder type shall also use
161
- that placeholder, not a deduced type. Similarly, redeclarations or
162
- specializations of a function or function template with a declared
163
- return type that does not use a placeholder type shall not use a
164
- placeholder.
165
 
166
  [*Example 6*:
167
 
168
  ``` cpp
169
  auto f();
170
  auto f() { return 42; } // return type is int
171
  auto f(); // OK
172
- int f(); // error: cannot be overloaded with auto f()
173
  decltype(auto) f(); // error: auto and decltype(auto) don't match
174
 
175
  template <typename T> auto g(T t) { return t; } // #1
176
  template auto g(int); // OK, return type is int
177
  template char g(char); // error: no matching template
@@ -223,44 +218,63 @@ int (*p)(int) = f; // instantiates f<int> to determine its return t
223
 
224
  *Placeholder type deduction* is the process by which a type containing a
225
  placeholder type is replaced by a deduced type.
226
 
227
  A type `T` containing a placeholder type, and a corresponding
228
- initializer E, are determined as follows:
229
 
230
- - for a non-discarded `return` statement that occurs in a function
231
  declared with a return type that contains a placeholder type, `T` is
232
- the declared return type and E is the operand of the `return`
233
- statement. If the `return` statement has no operand, then E is
234
- `void()`;
235
- - for a variable declared with a type that contains a placeholder type,
236
- `T` is the declared type of the variable and E is the initializer. If
237
- the initialization is direct-list-initialization, the initializer
238
- shall be a *braced-init-list* containing only a single
239
- *assignment-expression* and E is the *assignment-expression*;
240
- - for a non-type template parameter declared with a type that contains a
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
241
  placeholder type, `T` is the declared type of the non-type template
242
  parameter and E is the corresponding template argument.
243
 
244
- In the case of a `return` statement with no operand or with an operand
245
- of type `void`, `T` shall be either *type-constraint*ₒₚₜ
246
- `decltype(auto)` or cv *type-constraint*ₒₚₜ `auto`.
247
-
248
- If the deduction is for a `return` statement and E is a
249
- *braced-init-list* [[dcl.init.list]], the program is ill-formed.
250
 
251
  If the *placeholder-type-specifier* is of the form *type-constraint*ₒₚₜ
252
  `auto`, the deduced type T' replacing `T` is determined using the rules
253
- for template argument deduction. Obtain `P` from `T` by replacing the
254
- occurrences of *type-constraint*ₒₚₜ `auto` either with a new invented
255
- type template parameter `U` or, if the initialization is
256
- copy-list-initialization, with `std::initializer_list<U>`. Deduce a
257
- value for `U` using the rules of template argument deduction from a
258
- function call [[temp.deduct.call]], where `P` is a function template
259
- parameter type and the corresponding argument is E. If the deduction
260
- fails, the declaration is ill-formed. Otherwise, T' is obtained by
261
- substituting the deduced `U` into `P`.
 
 
 
262
 
263
  [*Example 8*:
264
 
265
  ``` cpp
266
  auto x1 = { 1, 2 }; // decltype(x1) is std::initializer_list<int>
@@ -287,12 +301,12 @@ template <class U> void f(const U& u);
287
 
288
  — *end example*]
289
 
290
  If the *placeholder-type-specifier* is of the form *type-constraint*ₒₚₜ
291
  `decltype(auto)`, `T` shall be the placeholder alone. The type deduced
292
- for `T` is determined as described in  [[dcl.type.simple]], as though E
293
- had been the operand of the `decltype`.
294
 
295
  [*Example 10*:
296
 
297
  ``` cpp
298
  int i;
@@ -307,10 +321,12 @@ auto x5a = f(); // decltype(x5a) is int
307
  decltype(auto) x5d = f(); // decltype(x5d) is int&&
308
  auto x6a = { 1, 2 }; // decltype(x6a) is std::initializer_list<int>
309
  decltype(auto) x6d = { 1, 2 }; // error: { 1, 2 } is not an expression
310
  auto *x7a = &i; // decltype(x7a) is int*
311
  decltype(auto)*x7d = &i; // error: declared type is not plain decltype(auto)
 
 
312
  ```
313
 
314
  — *end example*]
315
 
316
  For a *placeholder-type-specifier* with a *type-constraint*, the
 
1
  #### Placeholder type specifiers <a id="dcl.spec.auto">[[dcl.spec.auto]]</a>
2
 
3
+ ##### General <a id="dcl.spec.auto.general">[[dcl.spec.auto.general]]</a>
4
+
5
  ``` bnf
6
  placeholder-type-specifier:
7
  type-constraintₒₚₜ auto
8
  type-constraintₒₚₜ decltype '(' auto ')'
9
  ```
 
20
 
21
  [*Note 1*: Having a generic parameter type placeholder signifies that
22
  the function is an abbreviated function template [[dcl.fct]] or the
23
  lambda is a generic lambda [[expr.prim.lambda]]. — *end note*]
24
 
25
+ A placeholder type can appear with a function declarator in the
26
  *decl-specifier-seq*, *type-specifier-seq*, *conversion-function-id*, or
27
  *trailing-return-type*, in any context where such a declarator is valid.
28
  If the function declarator includes a *trailing-return-type*
29
  [[dcl.fct]], that *trailing-return-type* specifies the declared return
30
  type of the function. Otherwise, the function declarator shall declare a
 
36
  The type of a variable declared using a placeholder type is deduced from
37
  its initializer. This use is allowed in an initializing declaration
38
  [[dcl.init]] of a variable. The placeholder type shall appear as one of
39
  the *decl-specifier*s in the *decl-specifier-seq* and the
40
  *decl-specifier-seq* shall be followed by one or more *declarator*s,
41
+ each of which shall be followed by a non-empty *initializer*.
 
 
 
 
 
 
 
42
 
43
  [*Example 1*:
44
 
45
  ``` cpp
46
+ auto x = 5; // OK, x has type int
47
+ const auto *v = &x, u = 6; // OK, v has type const int*, u has type const int
48
+ static auto y = 0.0; // OK, y has type double
49
  auto int r; // error: auto is not a storage-class-specifier
50
+ auto f() -> int; // OK, f returns int
51
+ auto g() { return 0.0; } // OK, g returns double
52
+ auto h(); // OK, h's return type will be deduced when it is defined
53
  ```
54
 
55
  — *end example*]
56
 
57
  The `auto` *type-specifier* can also be used to introduce a structured
58
  binding declaration [[dcl.struct.bind]].
59
 
60
  A placeholder type can also be used in the *type-specifier-seq* in the
61
  *new-type-id* or *type-id* of a *new-expression* [[expr.new]] and as a
62
  *decl-specifier* of the *parameter-declaration*'s *decl-specifier-seq*
63
+ in a *template-parameter* [[temp.param]]. The `auto` *type-specifier*
64
+ can also be used as the *simple-type-specifier* in an explicit type
65
+ conversion (functional notation) [[expr.type.conv]].
66
 
67
  A program that uses a placeholder type in a context not explicitly
68
+ allowed in [[dcl.spec.auto]] is ill-formed.
69
 
70
  If the *init-declarator-list* contains more than one *init-declarator*,
71
  they shall all form declarations of variables. The type of each declared
72
  variable is determined by placeholder type deduction
73
  [[dcl.type.auto.deduct]], and if the type that replaces the placeholder
74
  type is not the same in each deduction, the program is ill-formed.
75
 
76
  [*Example 2*:
77
 
78
  ``` cpp
79
+ auto x = 5, *y = &x; // OK, auto is int
80
  auto a = 5, b = { 1, 2 }; // error: different types for auto
81
  ```
82
 
83
  — *end example*]
84
 
 
106
  declaration, outside the *private-module-fragment* (if any).
107
 
108
  [*Note 2*: The deduced return type cannot have a name with internal
109
  linkage [[basic.link]]. — *end note*]
110
 
111
+ If a variable or function with an undeduced placeholder type is named by
112
+ an expression [[basic.def.odr]], the program is ill-formed. Once a
113
+ non-discarded `return` statement has been seen in a function, however,
114
+ the return type deduced from that statement can be used in the rest of
115
+ the function, including in other `return` statements.
116
 
117
  [*Example 4*:
118
 
119
  ``` cpp
120
  auto n = n; // error: n's initializer refers to n
 
128
  }
129
  ```
130
 
131
  — *end example*]
132
 
133
+ Return type deduction for a templated function with a placeholder in its
134
+ declared type occurs when the definition is instantiated even if the
135
+ function body contains a `return` statement with a non-type-dependent
136
+ operand.
137
 
138
  [*Note 3*: Therefore, any use of a specialization of the function
139
  template will cause an implicit instantiation. Any errors that arise
140
  from this instantiation are not in the immediate context of the function
141
  type and can result in the program being ill-formed
 
151
  // chooses second
152
  ```
153
 
154
  — *end example*]
155
 
156
+ If a function or function template F has a declared return type that
157
+ uses a placeholder type, redeclarations or specializations of F shall
158
+ use that placeholder type, not a deduced type; otherwise, they shall not
159
+ use a placeholder type.
 
 
160
 
161
  [*Example 6*:
162
 
163
  ``` cpp
164
  auto f();
165
  auto f() { return 42; } // return type is int
166
  auto f(); // OK
167
+ int f(); // error: auto and int don't match
168
  decltype(auto) f(); // error: auto and decltype(auto) don't match
169
 
170
  template <typename T> auto g(T t) { return t; } // #1
171
  template auto g(int); // OK, return type is int
172
  template char g(char); // error: no matching template
 
218
 
219
  *Placeholder type deduction* is the process by which a type containing a
220
  placeholder type is replaced by a deduced type.
221
 
222
  A type `T` containing a placeholder type, and a corresponding
223
+ *initializer-clause* E, are determined as follows:
224
 
225
+ - For a non-discarded `return` statement that occurs in a function
226
  declared with a return type that contains a placeholder type, `T` is
227
+ the declared return type.
228
+ - If the `return` statement has no operand, then E is `void()`.
229
+ - If the operand is a *braced-init-list* [[dcl.init.list]], the
230
+ program is ill-formed.
231
+ - If the operand is an *expression* X that is not an
232
+ *assignment-expression*, E is `(X)`. \[*Note 4*: A comma expression
233
+ [[expr.comma]] is not an *assignment-expression*. *end note*]
234
+ - Otherwise, E is the operand of the `return` statement.
235
+
236
+ If E has type `void`, `T` shall be either *type-constraint*ₒₚₜ
237
+ `decltype(auto)` or cv *type-constraint*ₒₚₜ `auto`.
238
+ - For a variable declared with a type that contains a placeholder type,
239
+ `T` is the declared type of the variable.
240
+ - If the initializer of the variable is a *brace-or-equal-initializer*
241
+ of the form `= initializer-clause`, E is the *initializer-clause*.
242
+ - If the initializer is a *braced-init-list*, it shall consist of a
243
+ single brace-enclosed *assignment-expression* and E is the
244
+ *assignment-expression*.
245
+ - If the initializer is a parenthesized *expression-list*, the
246
+ *expression-list* shall be a single *assignment-expression* and E is
247
+ the *assignment-expression*.
248
+ - For an explicit type conversion [[expr.type.conv]], `T` is the
249
+ specified type, which shall be `auto`.
250
+ - If the initializer is a *braced-init-list*, it shall consist of a
251
+ single brace-enclosed *assignment-expression* and E is the
252
+ *assignment-expression*.
253
+ - If the initializer is a parenthesized *expression-list*, the
254
+ *expression-list* shall be a single *assignment-expression* and E is
255
+ the *assignment-expression*.
256
+ - For a non-type template parameter declared with a type that contains a
257
  placeholder type, `T` is the declared type of the non-type template
258
  parameter and E is the corresponding template argument.
259
 
260
+ `T` shall not be an array type.
 
 
 
 
 
261
 
262
  If the *placeholder-type-specifier* is of the form *type-constraint*ₒₚₜ
263
  `auto`, the deduced type T' replacing `T` is determined using the rules
264
+ for template argument deduction. If the initialization is
265
+ copy-list-initialization, a declaration of `std::initializer_list` shall
266
+ precede [[basic.lookup.general]] the *placeholder-type-specifier*.
267
+ Obtain `P` from `T` by replacing the occurrences of
268
+ *type-constraint*ₒₚₜ `auto` either with a new invented type template
269
+ parameter `U` or, if the initialization is copy-list-initialization,
270
+ with `std::initializer_list<U>`. Deduce a value for `U` using the rules
271
+ of template argument deduction from a function call
272
+ [[temp.deduct.call]], where `P` is a function template parameter type
273
+ and the corresponding argument is E. If the deduction fails, the
274
+ declaration is ill-formed. Otherwise, T' is obtained by substituting the
275
+ deduced `U` into `P`.
276
 
277
  [*Example 8*:
278
 
279
  ``` cpp
280
  auto x1 = { 1, 2 }; // decltype(x1) is std::initializer_list<int>
 
301
 
302
  — *end example*]
303
 
304
  If the *placeholder-type-specifier* is of the form *type-constraint*ₒₚₜ
305
  `decltype(auto)`, `T` shall be the placeholder alone. The type deduced
306
+ for `T` is determined as described in  [[dcl.type.decltype]], as though
307
+ E had been the operand of the `decltype`.
308
 
309
  [*Example 10*:
310
 
311
  ``` cpp
312
  int i;
 
321
  decltype(auto) x5d = f(); // decltype(x5d) is int&&
322
  auto x6a = { 1, 2 }; // decltype(x6a) is std::initializer_list<int>
323
  decltype(auto) x6d = { 1, 2 }; // error: { 1, 2 } is not an expression
324
  auto *x7a = &i; // decltype(x7a) is int*
325
  decltype(auto)*x7d = &i; // error: declared type is not plain decltype(auto)
326
+ auto f1(int x) -> decltype((x)) { return (x); } // return type is int&
327
+ auto f2(int x) -> decltype(auto) { return (x); } // return type is int&&
328
  ```
329
 
330
  — *end example*]
331
 
332
  For a *placeholder-type-specifier* with a *type-constraint*, the