From Jason Turner

[dcl.spec.auto.general]

Diff to HTML by rtfpessoa

Files changed (1) hide show
  1. tmp/tmpypsxeo2u/{from.md → to.md} +214 -0
tmp/tmpypsxeo2u/{from.md → to.md} RENAMED
@@ -0,0 +1,214 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ##### General <a id="dcl.spec.auto.general">[[dcl.spec.auto.general]]</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
+ A 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*.
40
+
41
+ [*Example 1*:
42
+
43
+ ``` cpp
44
+ auto x = 5; // OK, x has type int
45
+ const auto *v = &x, u = 6; // OK, v has type const int*, u has type const int
46
+ static auto y = 0.0; // OK, y has type double
47
+ auto int r; // error: auto is not a storage-class-specifier
48
+ auto f() -> int; // OK, f returns int
49
+ auto g() { return 0.0; } // OK, g returns double
50
+ auto h(); // OK, h's return type will be deduced when it is defined
51
+ ```
52
+
53
+ — *end example*]
54
+
55
+ The `auto` *type-specifier* can also be used to introduce a structured
56
+ binding declaration [[dcl.struct.bind]].
57
+
58
+ A placeholder type can also be used in the *type-specifier-seq* in the
59
+ *new-type-id* or *type-id* of a *new-expression* [[expr.new]] and as a
60
+ *decl-specifier* of the *parameter-declaration*'s *decl-specifier-seq*
61
+ in a *template-parameter* [[temp.param]]. The `auto` *type-specifier*
62
+ can also be used as the *simple-type-specifier* in an explicit type
63
+ conversion (functional notation) [[expr.type.conv]].
64
+
65
+ A program that uses a placeholder type in a context not explicitly
66
+ allowed in [[dcl.spec.auto]] is ill-formed.
67
+
68
+ If the *init-declarator-list* contains more than one *init-declarator*,
69
+ they shall all form declarations of variables. The type of each declared
70
+ variable is determined by placeholder type deduction
71
+ [[dcl.type.auto.deduct]], and if the type that replaces the placeholder
72
+ type is not the same in each deduction, the program is ill-formed.
73
+
74
+ [*Example 2*:
75
+
76
+ ``` cpp
77
+ auto x = 5, *y = &x; // OK, auto is int
78
+ auto a = 5, b = { 1, 2 }; // error: different types for auto
79
+ ```
80
+
81
+ — *end example*]
82
+
83
+ If a function with a declared return type that contains a placeholder
84
+ type has multiple non-discarded `return` statements, the return type is
85
+ deduced for each such `return` statement. If the type deduced is not the
86
+ same in each deduction, the program is ill-formed.
87
+
88
+ If a function with a declared return type that uses a placeholder type
89
+ has no non-discarded `return` statements, the return type is deduced as
90
+ though from a `return` statement with no operand at the closing brace of
91
+ the function body.
92
+
93
+ [*Example 3*:
94
+
95
+ ``` cpp
96
+ auto f() { } // OK, return type is void
97
+ auto* g() { } // error: cannot deduce auto* from void()
98
+ ```
99
+
100
+ — *end example*]
101
+
102
+ An exported function with a declared return type that uses a placeholder
103
+ type shall be defined in the translation unit containing its exported
104
+ declaration, outside the *private-module-fragment* (if any).
105
+
106
+ [*Note 2*: The deduced return type cannot have a name with internal
107
+ linkage [[basic.link]]. — *end note*]
108
+
109
+ If a variable or function with an undeduced placeholder type is named by
110
+ an expression [[basic.def.odr]], the program is ill-formed. Once a
111
+ non-discarded `return` statement has been seen in a function, however,
112
+ the return type deduced from that statement can be used in the rest of
113
+ the function, including in other `return` statements.
114
+
115
+ [*Example 4*:
116
+
117
+ ``` cpp
118
+ auto n = n; // error: n's initializer refers to n
119
+ auto f();
120
+ void g() { &f; } // error: f's return type is unknown
121
+ auto sum(int i) {
122
+ if (i == 1)
123
+ return i; // sum's return type is int
124
+ else
125
+ return sum(i-1)+i; // OK, sum's return type has been deduced
126
+ }
127
+ ```
128
+
129
+ — *end example*]
130
+
131
+ Return type deduction for a templated function with a placeholder in its
132
+ declared type occurs when the definition is instantiated even if the
133
+ function body contains a `return` statement with a non-type-dependent
134
+ operand.
135
+
136
+ [*Note 3*: Therefore, any use of a specialization of the function
137
+ template will cause an implicit instantiation. Any errors that arise
138
+ from this instantiation are not in the immediate context of the function
139
+ type and can result in the program being ill-formed
140
+ [[temp.deduct]]. — *end note*]
141
+
142
+ [*Example 5*:
143
+
144
+ ``` cpp
145
+ template <class T> auto f(T t) { return t; } // return type deduced at instantiation time
146
+ typedef decltype(f(1)) fint_t; // instantiates f<int> to deduce return type
147
+ template<class T> auto f(T* t) { return *t; }
148
+ void g() { int (*p)(int*) = &f; } // instantiates both fs to determine return types,
149
+ // chooses second
150
+ ```
151
+
152
+ — *end example*]
153
+
154
+ If a function or function template F has a declared return type that
155
+ uses a placeholder type, redeclarations or specializations of F shall
156
+ use that placeholder type, not a deduced type; otherwise, they shall not
157
+ use a placeholder type.
158
+
159
+ [*Example 6*:
160
+
161
+ ``` cpp
162
+ auto f();
163
+ auto f() { return 42; } // return type is int
164
+ auto f(); // OK
165
+ int f(); // error: auto and int don't match
166
+ decltype(auto) f(); // error: auto and decltype(auto) don't match
167
+
168
+ template <typename T> auto g(T t) { return t; } // #1
169
+ template auto g(int); // OK, return type is int
170
+ template char g(char); // error: no matching template
171
+ template<> auto g(double); // OK, forward declaration with unknown return type
172
+
173
+ template <class T> T g(T t) { return t; } // OK, not functionally equivalent to #1
174
+ template char g(char); // OK, now there is a matching template
175
+ template auto g(float); // still matches #1
176
+
177
+ void h() { return g(42); } // error: ambiguous
178
+
179
+ template <typename T> struct A {
180
+ friend T frf(T);
181
+ };
182
+ auto frf(int i) { return i; } // not a friend of A<int>
183
+ extern int v;
184
+ auto v = 17; // OK, redeclares v
185
+ struct S {
186
+ static int i;
187
+ };
188
+ auto S::i = 23; // OK
189
+ ```
190
+
191
+ — *end example*]
192
+
193
+ A function declared with a return type that uses a placeholder type
194
+ shall not be `virtual` [[class.virtual]].
195
+
196
+ A function declared with a return type that uses a placeholder type
197
+ shall not be a coroutine [[dcl.fct.def.coroutine]].
198
+
199
+ An explicit instantiation declaration [[temp.explicit]] does not cause
200
+ the instantiation of an entity declared using a placeholder type, but it
201
+ also does not prevent that entity from being instantiated as needed to
202
+ determine its type.
203
+
204
+ [*Example 7*:
205
+
206
+ ``` cpp
207
+ template <typename T> auto f(T t) { return t; }
208
+ extern template auto f(int); // does not instantiate f<int>
209
+ int (*p)(int) = f; // instantiates f<int> to determine its return type, but an explicit
210
+ // instantiation definition is still required somewhere in the program
211
+ ```
212
+
213
+ — *end example*]
214
+