From Jason Turner

[dcl.spec.auto]

Diff to HTML by rtfpessoa

Files changed (1) hide show
  1. tmp/tmppvd3j7tt/{from.md → to.md} +129 -103
tmp/tmppvd3j7tt/{from.md → to.md} RENAMED
@@ -1,54 +1,53 @@
1
- #### The `auto` specifier <a id="dcl.spec.auto">[[dcl.spec.auto]]</a>
2
-
3
- The `auto` and `decltype(auto)` *type-specifier*s are used to designate
4
- a placeholder type that will be replaced later by deduction from an
5
- initializer. The `auto` *type-specifier* is also used to introduce a
6
- function type having a *trailing-return-type* or to signify that a
7
- lambda is a generic lambda ([[expr.prim.lambda.closure]]). The `auto`
8
- *type-specifier* is also used to introduce a structured binding
9
- declaration ([[dcl.struct.bind]]).
 
 
 
 
 
 
 
 
 
 
 
 
10
 
11
  The placeholder type can appear with a function declarator in the
12
  *decl-specifier-seq*, *type-specifier-seq*, *conversion-function-id*, or
13
  *trailing-return-type*, in any context where such a declarator is valid.
14
- If the function declarator includes a *trailing-return-type* (
15
- [[dcl.fct]]), that *trailing-return-type* specifies the declared return
16
  type of the function. Otherwise, the function declarator shall declare a
17
  function. If the declared return type of the function contains a
18
  placeholder type, the return type of the function is deduced from
19
- non-discarded `return` statements, if any, in the body of the function (
20
- [[stmt.if]]).
21
-
22
- If the `auto` *type-specifier* appears as one of the *decl-specifier*s
23
- in the *decl-specifier-seq* of a *parameter-declaration* of a
24
- *lambda-expression*, the lambda is a *generic lambda* (
25
- [[expr.prim.lambda.closure]]).
26
-
27
- [*Example 1*:
28
-
29
- ``` cpp
30
- auto glambda = [](int i, auto a) { return i; }; // OK: a generic lambda
31
- ```
32
-
33
- — *end example*]
34
-
35
- The type of a variable declared using `auto` or `decltype(auto)` is
36
- deduced from its initializer. This use is allowed in an initializing
37
- declaration ([[dcl.init]]) of a variable. `auto` or `decltype(auto)`
38
- shall appear as one of the *decl-specifier*s in the *decl-specifier-seq*
39
- and the *decl-specifier-seq* shall be followed by one or more
40
- *declarator*s, each of which shall be followed by a non-empty
41
- *initializer*. In an *initializer* of the form
42
 
43
  ``` cpp
44
  ( expression-list )
45
  ```
46
 
47
  the *expression-list* shall be a single *assignment-expression*.
48
 
49
- [*Example 2*:
50
 
51
  ``` cpp
52
  auto x = 5; // OK: x has type int
53
  const auto *v = &x, u = 6; // OK: v has type const int*, u has type const int
54
  static auto y = 0.0; // OK: y has type double
@@ -58,25 +57,28 @@ auto g() { return 0.0; } // OK: g returns double
58
  auto h(); // OK: h's return type will be deduced when it is defined
59
  ```
60
 
61
  — *end example*]
62
 
 
 
 
63
  A placeholder type can also be used in the *type-specifier-seq* in the
64
- *new-type-id* or *type-id* of a *new-expression* ([[expr.new]]) and as
65
- a *decl-specifier* of the *parameter-declaration*'s *decl-specifier-seq*
66
- in a *template-parameter* ([[temp.param]]).
67
 
68
- A program that uses `auto` or `decltype(auto)` in a context not
69
- explicitly allowed in this section is ill-formed.
70
 
71
  If the *init-declarator-list* contains more than one *init-declarator*,
72
  they shall all form declarations of variables. The type of each declared
73
- variable is determined by placeholder type deduction (
74
- [[dcl.type.auto.deduct]]), and if the type that replaces the placeholder
75
  type is not the same in each deduction, the program is ill-formed.
76
 
77
- [*Example 3*:
78
 
79
  ``` cpp
80
  auto x = 5, *y = &x; // OK: auto is int
81
  auto a = 5, b = { 1, 2 }; // error: different types for auto
82
  ```
@@ -91,53 +93,60 @@ same in each deduction, the program is ill-formed.
91
  If a function with a declared return type that uses a placeholder type
92
  has no non-discarded `return` statements, the return type is deduced as
93
  though from a `return` statement with no operand at the closing brace of
94
  the function body.
95
 
96
- [*Example 4*:
97
 
98
  ``` cpp
99
  auto f() { } // OK, return type is void
100
- auto* g() { } // error, cannot deduce auto* from void()
101
  ```
102
 
103
  — *end example*]
104
 
105
- If the type of an entity with an undeduced placeholder type is needed to
106
- determine the type of an expression, the program is ill-formed. Once a
107
- non-discarded `return` statement has been seen in a function, however,
108
- the return type deduced from that statement can be used in the rest of
109
- the function, including in other `return` statements.
110
 
111
- [*Example 5*:
 
 
 
 
 
 
 
 
 
112
 
113
  ``` cpp
114
- auto n = n; // error, n's type is unknown
115
  auto f();
116
- void g() { &f; } // error, f's return type is unknown
117
  auto sum(int i) {
118
  if (i == 1)
119
  return i; // sum's return type is int
120
  else
121
  return sum(i-1)+i; // OK, sum's return type has been deduced
122
  }
123
  ```
124
 
125
  — *end example*]
126
 
127
- Return type deduction for a function template with a placeholder in its
128
- declared type occurs when the definition is instantiated even if the
129
- function body contains a `return` statement with a non-type-dependent
130
- operand.
131
 
132
- [*Note 1*: Therefore, any use of a specialization of the function
133
  template will cause an implicit instantiation. Any errors that arise
134
  from this instantiation are not in the immediate context of the function
135
- type and can result in the program being ill-formed (
136
- [[temp.deduct]]). — *end note*]
137
 
138
- [*Example 6*:
139
 
140
  ``` cpp
141
  template <class T> auto f(T t) { return t; } // return type deduced at instantiation time
142
  typedef decltype(f(1)) fint_t; // instantiates f<int> to deduce return type
143
  template<class T> auto f(T* t) { return *t; }
@@ -147,49 +156,61 @@ void g() { int (*p)(int*) = &f; } // instantiates both fs to deter
147
 
148
  — *end example*]
149
 
150
  Redeclarations or specializations of a function or function template
151
  with a declared return type that uses a placeholder type shall also use
152
- that placeholder, not a deduced type.
 
 
 
153
 
154
- [*Example 7*:
155
 
156
  ``` cpp
157
  auto f();
158
  auto f() { return 42; } // return type is int
159
  auto f(); // OK
160
- int f(); // error, cannot be overloaded with auto f()
161
- decltype(auto) f(); // error, auto and decltype(auto) don't match
162
 
163
  template <typename T> auto g(T t) { return t; } // #1
164
  template auto g(int); // OK, return type is int
165
- template char g(char); // error, no matching template
166
  template<> auto g(double); // OK, forward declaration with unknown return type
167
 
168
  template <class T> T g(T t) { return t; } // OK, not functionally equivalent to #1
169
  template char g(char); // OK, now there is a matching template
170
  template auto g(float); // still matches #1
171
 
172
- void h() { return g(42); } // error, ambiguous
173
 
174
  template <typename T> struct A {
175
  friend T frf(T);
176
  };
177
  auto frf(int i) { return i; } // not a friend of A<int>
 
 
 
 
 
 
178
  ```
179
 
180
  — *end example*]
181
 
182
  A function declared with a return type that uses a placeholder type
183
- shall not be `virtual` ([[class.virtual]]).
184
 
185
- An explicit instantiation declaration ([[temp.explicit]]) does not
186
- cause the instantiation of an entity declared using a placeholder type,
187
- but it also does not prevent that entity from being instantiated as
188
- needed to determine its type.
189
 
190
- [*Example 8*:
 
 
 
 
 
191
 
192
  ``` cpp
193
  template <typename T> auto f(T t) { return t; }
194
  extern template auto f(int); // does not instantiate f<int>
195
  int (*p)(int) = f; // instantiates f<int> to determine its return type, but an explicit
@@ -202,45 +223,46 @@ int (*p)(int) = f; // instantiates f<int> to determine its return t
202
 
203
  *Placeholder type deduction* is the process by which a type containing a
204
  placeholder type is replaced by a deduced type.
205
 
206
  A type `T` containing a placeholder type, and a corresponding
207
- initializer `e`, are determined as follows:
208
 
209
  - for a non-discarded `return` statement that occurs in a function
210
  declared with a return type that contains a placeholder type, `T` is
211
- the declared return type and `e` is the operand of the `return`
212
- statement. If the `return` statement has no operand, then `e` is
213
  `void()`;
214
  - for a variable declared with a type that contains a placeholder type,
215
- `T` is the declared type of the variable and `e` is the initializer.
216
- If the initialization is direct-list-initialization, the initializer
217
  shall be a *braced-init-list* containing only a single
218
- *assignment-expression* and `e` is the *assignment-expression*;
219
  - for a non-type template parameter declared with a type that contains a
220
  placeholder type, `T` is the declared type of the non-type template
221
- parameter and `e` is the corresponding template argument.
222
 
223
  In the case of a `return` statement with no operand or with an operand
224
- of type `void`, `T` shall be either `decltype(auto)` or cv `auto`.
 
225
 
226
- If the deduction is for a `return` statement and `e` is a
227
- *braced-init-list* ([[dcl.init.list]]), the program is ill-formed.
228
 
229
- If the placeholder is the `auto` *type-specifier*, the deduced type T'
230
- replacing `T` is determined using the rules for template argument
231
- deduction. Obtain `P` from `T` by replacing the occurrences of `auto`
232
- with either a new invented type template parameter `U` or, if the
233
- initialization is copy-list-initialization, with
234
- `std::initializer_list<U>`. Deduce a value for `U` using the rules of
235
- template argument deduction from a function call (
236
- [[temp.deduct.call]]), where `P` is a function template parameter type
237
- and the corresponding argument is `e`. If the deduction fails, the
238
- declaration is ill-formed. Otherwise, T' is obtained by substituting the
239
- deduced `U` into `P`.
240
 
241
- [*Example 9*:
242
 
243
  ``` cpp
244
  auto x1 = { 1, 2 }; // decltype(x1) is std::initializer_list<int>
245
  auto x2 = { 1, 2.0 }; // error: cannot deduce element type
246
  auto x3{ 1, 2 }; // error: not a single element
@@ -248,11 +270,11 @@ auto x4 = { 3 }; // decltype(x4) is std::initializer_list<int>
248
  auto x5{ 3 }; // decltype(x5) is int
249
  ```
250
 
251
  — *end example*]
252
 
253
- [*Example 10*:
254
 
255
  ``` cpp
256
  const auto &i = expr;
257
  ```
258
 
@@ -263,16 +285,16 @@ The type of `i` is the deduced type of the parameter `u` in the call
263
  template <class U> void f(const U& u);
264
  ```
265
 
266
  — *end example*]
267
 
268
- If the placeholder is the `decltype(auto)` *type-specifier*, `T` shall
269
- be the placeholder alone. The type deduced for `T` is determined as
270
- described in  [[dcl.type.simple]], as though `e` had been the operand of
271
- the `decltype`.
272
 
273
- [*Example 11*:
274
 
275
  ``` cpp
276
  int i;
277
  int&& f();
278
  auto x2a(i); // decltype(x2a) is int
@@ -282,12 +304,16 @@ decltype(auto) x3d = i; // decltype(x3d) is int
282
  auto x4a = (i); // decltype(x4a) is int
283
  decltype(auto) x4d = (i); // decltype(x4d) is int&
284
  auto x5a = f(); // decltype(x5a) is int
285
  decltype(auto) x5d = f(); // decltype(x5d) is int&&
286
  auto x6a = { 1, 2 }; // decltype(x6a) is std::initializer_list<int>
287
- decltype(auto) x6d = { 1, 2 }; // error, { 1, 2 } is not an expression
288
  auto *x7a = &i; // decltype(x7a) is int*
289
- decltype(auto)*x7d = &i; // error, declared type is not plain decltype(auto)
290
  ```
291
 
292
  — *end example*]
293
 
 
 
 
 
 
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
+ ```
8
+
9
+ A *placeholder-type-specifier* designates a placeholder type that will
10
+ be replaced later by deduction from an initializer.
11
+
12
+ A *placeholder-type-specifier* of the form *type-constraint*ₒₚₜ `auto`
13
+ can be used as a *decl-specifier* of the *decl-specifier-seq* of a
14
+ *parameter-declaration* of a function declaration or *lambda-expression*
15
+ and, if it is not the `auto` *type-specifier* introducing a
16
+ *trailing-return-type* (see below), is a *generic parameter type
17
+ 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
29
  function. If the declared return type of the function contains a
30
  placeholder type, the return type of the function is deduced from
31
+ non-discarded `return` statements, if any, in the body of the function
32
+ [[stmt.if]].
33
+
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
 
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
  ```
 
93
  If a function with a declared return type that uses a placeholder type
94
  has no non-discarded `return` statements, the return type is deduced as
95
  though from a `return` statement with no operand at the closing brace of
96
  the function body.
97
 
98
+ [*Example 3*:
99
 
100
  ``` cpp
101
  auto f() { } // OK, return type is void
102
+ auto* g() { } // error: cannot deduce auto* from void()
103
  ```
104
 
105
  — *end example*]
106
 
107
+ An exported function with a declared return type that uses a placeholder
108
+ 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
124
  auto f();
125
+ void g() { &f; } // error: f's return type is unknown
126
  auto sum(int i) {
127
  if (i == 1)
128
  return i; // sum's return type is int
129
  else
130
  return sum(i-1)+i; // OK, sum's return type has been deduced
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
145
+ [[temp.deduct]]. — *end note*]
146
 
147
+ [*Example 5*:
148
 
149
  ``` cpp
150
  template <class T> auto f(T t) { return t; } // return type deduced at instantiation time
151
  typedef decltype(f(1)) fint_t; // instantiates f<int> to deduce return type
152
  template<class T> auto f(T* t) { return *t; }
 
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
178
  template<> auto g(double); // OK, forward declaration with unknown return type
179
 
180
  template <class T> T g(T t) { return t; } // OK, not functionally equivalent to #1
181
  template char g(char); // OK, now there is a matching template
182
  template auto g(float); // still matches #1
183
 
184
+ void h() { return g(42); } // error: ambiguous
185
 
186
  template <typename T> struct A {
187
  friend T frf(T);
188
  };
189
  auto frf(int i) { return i; } // not a friend of A<int>
190
+ extern int v;
191
+ auto v = 17; // OK, redeclares v
192
+ struct S {
193
+ static int i;
194
+ };
195
+ auto S::i = 23; // OK
196
  ```
197
 
198
  — *end example*]
199
 
200
  A function declared with a return type that uses a placeholder type
201
+ shall not be `virtual` [[class.virtual]].
202
 
203
+ A function declared with a return type that uses a placeholder type
204
+ shall not be a coroutine [[dcl.fct.def.coroutine]].
 
 
205
 
206
+ An explicit instantiation declaration [[temp.explicit]] does not cause
207
+ the instantiation of an entity declared using a placeholder type, but it
208
+ also does not prevent that entity from being instantiated as needed to
209
+ determine its type.
210
+
211
+ [*Example 7*:
212
 
213
  ``` cpp
214
  template <typename T> auto f(T t) { return t; }
215
  extern template auto f(int); // does not instantiate f<int>
216
  int (*p)(int) = f; // instantiates f<int> to determine its return type, but an explicit
 
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>
267
  auto x2 = { 1, 2.0 }; // error: cannot deduce element type
268
  auto x3{ 1, 2 }; // error: not a single element
 
270
  auto x5{ 3 }; // decltype(x5) is int
271
  ```
272
 
273
  — *end example*]
274
 
275
+ [*Example 9*:
276
 
277
  ``` cpp
278
  const auto &i = expr;
279
  ```
280
 
 
285
  template <class U> void f(const U& u);
286
  ```
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;
299
  int&& f();
300
  auto x2a(i); // decltype(x2a) is int
 
304
  auto x4a = (i); // decltype(x4a) is int
305
  decltype(auto) x4d = (i); // decltype(x4d) is int&
306
  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
317
+ immediately-declared constraint [[temp.param]] of the *type-constraint*
318
+ for the type deduced for the placeholder shall be satisfied.
319
+