From Jason Turner

[dcl.spec.auto]

Diff to HTML by rtfpessoa

Files changed (1) hide show
  1. tmp/tmp8yyv9mpw/{from.md → to.md} +185 -35
tmp/tmp8yyv9mpw/{from.md → to.md} RENAMED
@@ -1,65 +1,91 @@
1
  #### `auto` specifier <a id="dcl.spec.auto">[[dcl.spec.auto]]</a>
2
 
3
- The `auto` *type-specifier* signifies that the type of a variable being
4
- declared shall be deduced from its initializer or that a function
5
- declarator shall include a *trailing-return-type*.
 
 
6
 
7
- The `auto` *type-specifier* may appear with a function declarator with a
8
- *trailing-return-type* ([[dcl.fct]]) in any context where such a
9
- declarator is valid.
 
 
 
 
 
10
 
11
- Otherwise, the type of the variable is deduced from its initializer. The
12
- name of the variable being declared shall not appear in the initializer
13
- expression. This use of `auto` is allowed when declaring variables in a
14
- block ([[stmt.block]]), in namespace scope (
15
- [[basic.scope.namespace]]), and in a  ([[stmt.for]]). `auto` shall
16
- appear as one of the *decl-specifier*s in the *decl-specifier-seq* and
17
- the *decl-specifier-seq* shall be followed by one or more
18
- *init-declarator*s, each of which shall have a non-empty *initializer*.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
19
 
20
  ``` cpp
21
  auto x = 5; // OK: x has type int
22
  const auto *v = &x, u = 6; // OK: v has type const int*, u has type const int
23
  static auto y = 0.0; // OK: y has type double
24
  auto int r; // error: auto is not a storage-class-specifier
 
 
 
25
  ```
26
 
27
- The `auto` can also be used in declaring a variable in the of a
28
  selection statement ([[stmt.select]]) or an iteration statement (
29
  [[stmt.iter]]), in the in the or of a  ([[expr.new]]), in a
30
  *for-range-declaration*, and in declaring a static data member with a
31
  *brace-or-equal-initializer* that appears within the of a class
32
  definition ([[class.static.data]]).
33
 
34
- A program that uses `auto` in a context not explicitly allowed in this
35
- section is ill-formed.
36
 
37
- Once the type of a has been determined according to  [[dcl.meaning]],
38
- the type of the declared variable using the is determined from the type
39
- of its initializer using the rules for template argument deduction. Let
40
- `T` be the type that has been determined for a variable identifier `d`.
41
- Obtain `P` from `T` by replacing the occurrences of `auto` with either a
42
- new invented type template parameter `U` or, if the initializer is a
43
- *braced-init-list* ([[dcl.init.list]]), with
44
- `std::initializer_list<U>`. The type deduced for the variable `d` is
45
- then the deduced `A` determined using the rules of template argument
46
- deduction from a function call ([[temp.deduct.call]]), where `P` is a
47
- function template parameter type and the initializer for `d` is the
48
- corresponding argument. If the deduction fails, the declaration is
49
- ill-formed.
 
 
 
 
 
 
50
 
51
  ``` cpp
52
  auto x1 = { 1, 2 }; // decltype(x1) is std::initializer_list<int>
53
  auto x2 = { 1, 2.0 }; // error: cannot deduce element type
54
  ```
55
 
56
- If the list of declarators contains more than one declarator, the type
57
- of each declared variable is determined as described above. If the type
58
- deduced for the template parameter `U` is not the same in each
59
- deduction, the program is ill-formed.
60
-
61
  ``` cpp
62
  const auto &i = expr;
63
  ```
64
 
65
  The type of `i` is the deduced type of the parameter `u` in the call
@@ -67,5 +93,129 @@ The type of `i` is the deduced type of the parameter `u` in the call
67
 
68
  ``` cpp
69
  template <class U> void f(const U& u);
70
  ```
71
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
 
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
155
+ auto sum(int i) {
156
+ if (i == 1)
157
+ return i; // sum's return type is int
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()
188
+ decltype(auto) f(); // error, auto and decltype(auto) don't match
189
+
190
+ template <typename T> auto g(T t) { return t; } // #1
191
+ template auto g(int); // OK, return type is int
192
+ template char g(char); // error, no matching template
193
+ template<> auto g(double); // OK, forward declaration with unknown return type
194
+
195
+ template <class T> T g(T t) { return t; } // OK, not functionally equivalent to #1
196
+ template char g(char); // OK, now there is a matching template
197
+ template auto g(float); // still matches #1
198
+
199
+ void h() { return g(42); } // error, ambiguous
200
+
201
+ 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
+