From Jason Turner

[dcl.spec.auto]

Diff to HTML by rtfpessoa

Files changed (1) hide show
  1. tmp/tmpv7cocn6r/{from.md → to.md} +168 -96
tmp/tmpv7cocn6r/{from.md → to.md} RENAMED
@@ -1,154 +1,116 @@
1
- #### `auto` specifier <a id="dcl.spec.auto">[[dcl.spec.auto]]</a>
2
 
3
- The `auto` and `decltype(auto)` *type-specifier*s designate a
4
- placeholder type that will be replaced later, either by deduction from
5
- an initializer or by explicit specification with a
6
- *trailing-return-type*. The `auto` *type-specifier* is also used to
7
- signify that a lambda is a generic lambda.
 
 
8
 
9
  The placeholder type can appear with a function declarator in the
10
  *decl-specifier-seq*, *type-specifier-seq*, *conversion-function-id*, or
11
  *trailing-return-type*, in any context where such a declarator is valid.
12
  If the function declarator includes a *trailing-return-type* (
13
- [[dcl.fct]]), that specifies the declared return type of the function.
14
- If the declared return type of the function contains a placeholder type,
15
- the return type of the function is deduced from `return` statements in
16
- the body of the function, if any.
 
 
17
 
18
  If the `auto` *type-specifier* appears as one of the *decl-specifier*s
19
  in the *decl-specifier-seq* of a *parameter-declaration* of a
20
  *lambda-expression*, the lambda is a *generic lambda* (
21
- [[expr.prim.lambda]]).
 
 
22
 
23
  ``` cpp
24
  auto glambda = [](int i, auto a) { return i; }; // OK: a generic lambda
25
  ```
26
 
 
 
27
  The type of a variable declared using `auto` or `decltype(auto)` is
28
- deduced from its initializer. This use is allowed when declaring
29
- variables in a block ([[stmt.block]]), in namespace scope (
30
- [[basic.scope.namespace]]), and in a  ([[stmt.for]]). `auto` or
31
- `decltype(auto)` shall appear as one of the *decl-specifier*s in the
32
- *decl-specifier-seq* and the *decl-specifier-seq* shall be followed by
33
- one or more *init-declarator*s, each of which shall have a non-empty
34
  *initializer*. In an *initializer* of the form
35
 
36
  ``` cpp
37
  ( expression-list )
38
  ```
39
 
40
  the *expression-list* shall be a single *assignment-expression*.
41
 
 
 
42
  ``` cpp
43
  auto x = 5; // OK: x has type int
44
  const auto *v = &x, u = 6; // OK: v has type const int*, u has type const int
45
  static auto y = 0.0; // OK: y has type double
46
  auto int r; // error: auto is not a storage-class-specifier
47
  auto f() -> int; // OK: f returns int
48
  auto g() { return 0.0; } // OK: g returns double
49
  auto h(); // OK: h's return type will be deduced when it is defined
50
  ```
51
 
52
- A placeholder type can also be used in declaring a variable in the of a
53
- selection statement ([[stmt.select]]) or an iteration statement (
54
- [[stmt.iter]]), in the in the or of a  ([[expr.new]]), in a
55
- *for-range-declaration*, and in declaring a static data member with a
56
- *brace-or-equal-initializer* that appears within the of a class
57
- definition ([[class.static.data]]).
58
 
59
  A program that uses `auto` or `decltype(auto)` in a context not
60
  explicitly allowed in this section is ill-formed.
61
 
62
- When a variable declared using a placeholder type is initialized, or a
63
- `return` statement occurs in a function declared with a return type that
64
- contains a placeholder type, the deduced return type or variable type is
65
- determined from the type of its initializer. In the case of a `return`
66
- with no operand, the initializer is considered to be `void()`. Let `T`
67
- be the declared type of the variable or return type of the function. If
68
- the placeholder is the `auto` *type-specifier*, the deduced type is
69
- determined using the rules for template argument deduction. If the
70
- deduction is for a `return` statement and the initializer is a
71
- *braced-init-list* ([[dcl.init.list]]), the program is ill-formed.
72
- Otherwise, obtain `P` from `T` by replacing the occurrences of `auto`
73
- with either a new invented type template parameter `U` or, if the
74
- initializer is a *braced-init-list*, with `std::initializer_list<U>`.
75
- Deduce a value for `U` using the rules of template argument deduction
76
- from a function call ([[temp.deduct.call]]), where `P` is a function
77
- template parameter type and the initializer is the corresponding
78
- argument. If the deduction fails, the declaration is ill-formed.
79
- Otherwise, the type deduced for the variable or return type is obtained
80
- by substituting the deduced `U` into `P`.
81
-
82
- ``` cpp
83
- auto x1 = { 1, 2 }; // decltype(x1) is std::initializer_list<int>
84
- auto x2 = { 1, 2.0 }; // error: cannot deduce element type
85
- ```
86
-
87
- ``` cpp
88
- const auto &i = expr;
89
- ```
90
-
91
- The type of `i` is the deduced type of the parameter `u` in the call
92
- `f(expr)` of the following invented function template:
93
-
94
- ``` cpp
95
- template <class U> void f(const U& u);
96
- ```
97
-
98
- If the placeholder is the `decltype(auto)` *type-specifier*, the
99
- declared type of the variable or return type of the function shall be
100
- the placeholder alone. The type deduced for the variable or return type
101
- is determined as described in  [[dcl.type.simple]], as though the
102
- initializer had been the operand of the `decltype`.
103
-
104
- ``` cpp
105
- int i;
106
- int&& f();
107
- auto x3a = i; // decltype(x3a) is int
108
- decltype(auto) x3d = i; // decltype(x3d) is int
109
- auto x4a = (i); // decltype(x4a) is int
110
- decltype(auto) x4d = (i); // decltype(x4d) is int&
111
- auto x5a = f(); // decltype(x5a) is int
112
- decltype(auto) x5d = f(); // decltype(x5d) is int&&
113
- auto x6a = { 1, 2 }; // decltype(x6a) is std::initializer_list<int>
114
- decltype(auto) x6d = { 1, 2 }; // error, { 1, 2 } is not an expression
115
- auto *x7a = &i; // decltype(x7a) is int*
116
- decltype(auto)*x7d = &i; // error, declared type is not plain decltype(auto)
117
- ```
118
-
119
  If the *init-declarator-list* contains more than one *init-declarator*,
120
  they shall all form declarations of variables. The type of each declared
121
- variable is determined as described above, and if the type that replaces
122
- the placeholder type is not the same in each deduction, the program is
123
- ill-formed.
 
 
124
 
125
  ``` cpp
126
  auto x = 5, *y = &x; // OK: auto is int
127
  auto a = 5, b = { 1, 2 }; // error: different types for auto
128
  ```
129
 
 
 
130
  If a function with a declared return type that contains a placeholder
131
- type has multiple `return` statements, the return type is deduced for
132
- each `return` statement. If the type deduced is not the same in each
133
- deduction, the program is ill-formed.
134
 
135
  If a function with a declared return type that uses a placeholder type
136
- has no `return` statements, the return type is deduced as though from a
137
- `return` statement with no operand at the closing brace of the function
138
- body.
 
 
139
 
140
  ``` cpp
141
  auto f() { } // OK, return type is void
142
  auto* g() { } // error, cannot deduce auto* from void()
143
  ```
144
 
 
 
145
  If the type of an entity with an undeduced placeholder type is needed to
146
  determine the type of an expression, the program is ill-formed. Once a
147
- `return` statement has been seen in a function, however, the return type
148
- deduced from that statement can be used in the rest of the function,
149
- including in other `return` statements.
 
 
150
 
151
  ``` cpp
152
  auto n = n; // error, n's type is unknown
153
  auto f();
154
  void g() { &f; } // error, f's return type is unknown
@@ -158,30 +120,41 @@ auto sum(int i) {
158
  else
159
  return sum(i-1)+i; // OK, sum's return type has been deduced
160
  }
161
  ```
162
 
 
 
163
  Return type deduction for a function template with a placeholder in its
164
  declared type occurs when the definition is instantiated even if the
165
  function body contains a `return` statement with a non-type-dependent
166
- operand. Therefore, any use of a specialization of the function template
167
- will cause an implicit instantiation. Any errors that arise from this
168
- instantiation are not in the immediate context of the function type and
169
- can result in the program being ill-formed.
 
 
 
 
 
170
 
171
  ``` cpp
172
  template <class T> auto f(T t) { return t; } // return type deduced at instantiation time
173
  typedef decltype(f(1)) fint_t; // instantiates f<int> to deduce return type
174
  template<class T> auto f(T* t) { return *t; }
175
  void g() { int (*p)(int*) = &f; } // instantiates both fs to determine return types,
176
  // chooses second
177
  ```
178
 
 
 
179
  Redeclarations or specializations of a function or function template
180
  with a declared return type that uses a placeholder type shall also use
181
  that placeholder, not a deduced type.
182
 
 
 
183
  ``` cpp
184
  auto f();
185
  auto f() { return 42; } // return type is int
186
  auto f(); // OK
187
  int f(); // error, cannot be overloaded with auto f()
@@ -202,20 +175,119 @@ template <typename T> struct A {
202
  friend T frf(T);
203
  };
204
  auto frf(int i) { return i; } // not a friend of A<int>
205
  ```
206
 
 
 
207
  A function declared with a return type that uses a placeholder type
208
  shall not be `virtual` ([[class.virtual]]).
209
 
210
  An explicit instantiation declaration ([[temp.explicit]]) does not
211
  cause the instantiation of an entity declared using a placeholder type,
212
  but it also does not prevent that entity from being instantiated as
213
  needed to determine its type.
214
 
 
 
215
  ``` cpp
216
  template <typename T> auto f(T t) { return t; }
217
  extern template auto f(int); // does not instantiate f<int>
218
  int (*p)(int) = f; // instantiates f<int> to determine its return type, but an explicit
219
  // instantiation definition is still required somewhere in the program
220
  ```
221
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
55
  auto int r; // error: auto is not a storage-class-specifier
56
  auto f() -> int; // OK: f returns int
57
  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
  ```
83
 
84
+ — *end example*]
85
+
86
  If a function with a declared return type that contains a placeholder
87
+ type has multiple non-discarded `return` statements, the return type is
88
+ deduced for each such `return` statement. If the type deduced is not the
89
+ same in each deduction, the program is ill-formed.
90
 
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
 
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; }
144
  void g() { int (*p)(int*) = &f; } // instantiates both fs to determine return types,
145
  // chooses second
146
  ```
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()
 
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
196
  // instantiation definition is still required somewhere in the program
197
  ```
198
 
199
+ — *end example*]
200
+
201
+ ##### Placeholder type deduction <a id="dcl.type.auto.deduct">[[dcl.type.auto.deduct]]</a>
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
247
+ 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
+
259
+ The type of `i` is the deduced type of the parameter `u` in the call
260
+ `f(expr)` of the following invented function template:
261
+
262
+ ``` cpp
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
279
+ decltype(auto) x2d(i); // decltype(x2d) is int
280
+ auto x3a = i; // decltype(x3a) is int
281
+ 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
+