From Jason Turner

[expr.prim.lambda.closure]

Diff to HTML by rtfpessoa

Files changed (1) hide show
  1. tmp/tmpba2gqdv7/{from.md → to.md} +111 -55
tmp/tmpba2gqdv7/{from.md → to.md} RENAMED
@@ -2,38 +2,46 @@
2
 
3
  The type of a *lambda-expression* (which is also the type of the closure
4
  object) is a unique, unnamed non-union class type, called the *closure
5
  type*, whose properties are described below.
6
 
 
 
 
7
  The closure type is declared in the smallest block scope, class scope,
8
  or namespace scope that contains the corresponding *lambda-expression*.
9
 
10
  [*Note 1*: This determines the set of namespaces and classes associated
11
  with the closure type [[basic.lookup.argdep]]. The parameter types of a
12
  *lambda-declarator* do not affect these associated namespaces and
13
  classes. — *end note*]
14
 
15
- The closure type is not an aggregate type [[dcl.init.aggr]]. An
16
- implementation may define the closure type differently from what is
17
- described below provided this does not alter the observable behavior of
18
- the program other than by changing:
 
19
 
20
  - the size and/or alignment of the closure type,
21
- - whether the closure type is trivially copyable [[class.prop]], or
 
 
22
  - whether the closure type is a standard-layout class [[class.prop]].
23
 
24
  An implementation shall not add members of rvalue reference type to the
25
  closure type.
26
 
27
  The closure type for a *lambda-expression* has a public inline function
28
  call operator (for a non-generic lambda) or function call operator
29
  template (for a generic lambda) [[over.call]] whose parameters and
30
- return type are described by the *lambda-expression*s
31
  *parameter-declaration-clause* and *trailing-return-type* respectively,
32
  and whose *template-parameter-list* consists of the specified
33
- *template-parameter-list*, if any. The *requires-clause* of the function
34
- call operator template is the *requires-clause* immediately following
 
 
35
  `<` *template-parameter-list* `>`, if any. The trailing
36
  *requires-clause* of the function call operator or operator template is
37
  the *requires-clause* of the *lambda-declarator*, if any.
38
 
39
  [*Note 2*: The function call operator template for a generic lambda can
@@ -70,11 +78,12 @@ std::cout << fact(5); // OK, outputs 1
70
  Given a lambda with a *lambda-capture*, the type of the explicit object
71
  parameter, if any, of the lambda’s function call operator (possibly
72
  instantiated from a function call operator template) shall be either:
73
 
74
  - the closure type,
75
- - a class type derived from the closure type, or
 
76
  - a reference to a possibly cv-qualified such type.
77
 
78
  [*Example 2*:
79
 
80
  ``` cpp
@@ -98,13 +107,14 @@ function or static member function template [[class.static.mfct]] if the
98
  `static`. Otherwise, it is a non-static member function or member
99
  function template [[class.mfct.non.static]] that is declared `const`
100
  [[class.mfct.non.static]] if and only if the *lambda-expression*’s
101
  *parameter-declaration-clause* is not followed by `mutable` and the
102
  *lambda-declarator* does not contain an explicit object parameter. It is
103
- neither virtual nor declared `volatile`. Any *noexcept-specifier*
104
- specified on a *lambda-expression* applies to the corresponding function
105
- call operator or operator template. An *attribute-specifier-seq* in a
 
106
  *lambda-declarator* appertains to the type of the corresponding function
107
  call operator or operator template. An *attribute-specifier-seq* in a
108
  *lambda-expression* preceding a *lambda-declarator* appertains to the
109
  corresponding function call operator or operator template. The function
110
  call operator or any given operator template specialization is a
@@ -183,35 +193,80 @@ auto f = []<typename T1, C1 T2> requires C2<sizeof(T1) + sizeof(T2)>
183
 
184
  — *end example*]
185
 
186
  — *end note*]
187
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
188
  The closure type for a non-generic *lambda-expression* with no
189
- *lambda-capture* whose constraints (if any) are satisfied has a
190
- conversion function to pointer to function with C++ language linkage
191
- [[dcl.link]] having the same parameter and return types as the closure
192
- type’s function call operator. The conversion is to “pointer to
193
- `noexcept` function” if the function call operator has a non-throwing
194
- exception specification. If the function call operator is a static
195
- member function, then the value returned by this conversion function is
196
- the address of the function call operator. Otherwise, the value returned
197
- by this conversion function is the address of a function `F` that, when
198
- invoked, has the same effect as invoking the closure type’s function
199
- call operator on a default-constructed instance of the closure type. `F`
200
- is a constexpr function if the function call operator is a constexpr
201
- function and is an immediate function if the function call operator is
202
- an immediate function.
 
203
 
204
- For a generic lambda with no *lambda-capture*, the closure type has a
205
- conversion function template to pointer to function. The conversion
206
- function template has the same invented template parameter list, and the
207
- pointer to function has the same parameter types, as the function call
208
- operator template. The return type of the pointer to function shall
209
- behave as if it were a *decltype-specifier* denoting the return type of
210
- the corresponding function call operator template specialization.
 
211
 
212
- [*Note 4*:
213
 
214
  If the generic lambda has no *trailing-return-type* or the
215
  *trailing-return-type* contains a placeholder type, return type
216
  deduction of the corresponding function call operator template
217
  specialization has to be done. The corresponding specialization is that
@@ -243,11 +298,11 @@ struct Closure {
243
  };
244
  ```
245
 
246
  — *end note*]
247
 
248
- [*Example 6*:
249
 
250
  ``` cpp
251
  void f1(int (*)(int)) { }
252
  void f2(char (*)(int)) { }
253
 
@@ -267,27 +322,26 @@ int& (*fpi)(int*) = [](auto* a) -> auto& { return *a; }; // OK
267
 
268
  — *end example*]
269
 
270
  If the function call operator template is a static member function
271
  template, then the value returned by any given specialization of this
272
- conversion function template is the address of the corresponding
273
- function call operator template specialization. Otherwise, the value
274
- returned by any given specialization of this conversion function
275
- template is the address of a function `F` that, when invoked, has the
276
- same effect as invoking the generic lambda’s corresponding function call
277
- operator template specialization on a default-constructed instance of
278
- the closure type. `F` is a constexpr function if the corresponding
279
- specialization is a constexpr function and `F` is an immediate function
280
- if the function call operator template specialization is an immediate
281
- function.
282
 
283
- [*Note 5*: This will result in the implicit instantiation of the
284
  generic lambda’s body. The instantiated generic lambda’s return type and
285
- parameter types are required to match the return type and parameter
286
- types of the pointer to function. — *end note*]
287
 
288
- [*Example 7*:
289
 
290
  ``` cpp
291
  auto GL = [](auto a) { std::cout << a; return a; };
292
  int (*GL_int)(int) = GL; // OK, through conversion function template
293
  GL_int(3); // OK, same as GL(3)
@@ -297,11 +351,11 @@ GL_int(3); // OK, same as GL(3)
297
 
298
  The conversion function or conversion function template is public,
299
  constexpr, non-virtual, non-explicit, const, and has a non-throwing
300
  exception specification [[except.spec]].
301
 
302
- [*Example 8*:
303
 
304
  ``` cpp
305
  auto Fwd = [](int (*fp)(int), auto a) { return fp(a); };
306
  auto C = [](auto a) { return a; };
307
 
@@ -316,11 +370,11 @@ static_assert(Fwd(NC,3) == 3); // error
316
 
317
  The *lambda-expression*’s *compound-statement* yields the
318
  *function-body* [[dcl.fct.def]] of the function call operator, but it is
319
  not within the scope of the closure type.
320
 
321
- [*Example 9*:
322
 
323
  ``` cpp
324
  struct S1 {
325
  int x, y;
326
  int operator()(int);
@@ -333,23 +387,25 @@ struct S1 {
333
  };
334
  ```
335
 
336
  — *end example*]
337
 
338
- Further, a variable `__func__` is implicitly defined at the beginning of
339
- the *compound-statement* of the *lambda-expression*, with semantics as
340
- described in  [[dcl.fct.def.general]].
 
 
341
 
342
  The closure type associated with a *lambda-expression* has no default
343
  constructor if the *lambda-expression* has a *lambda-capture* and a
344
  defaulted default constructor otherwise. It has a defaulted copy
345
  constructor and a defaulted move constructor [[class.copy.ctor]]. It has
346
  a deleted copy assignment operator if the *lambda-expression* has a
347
  *lambda-capture* and defaulted copy and move assignment operators
348
  otherwise [[class.copy.assign]].
349
 
350
- [*Note 6*: These special member functions are implicitly defined as
351
  usual, which can result in them being defined as deleted. — *end note*]
352
 
353
  The closure type associated with a *lambda-expression* has an
354
  implicitly-declared destructor [[class.dtor]].
355
 
 
2
 
3
  The type of a *lambda-expression* (which is also the type of the closure
4
  object) is a unique, unnamed non-union class type, called the *closure
5
  type*, whose properties are described below.
6
 
7
+ The closure type is incomplete until the end of its corresponding
8
+ *compound-statement*.
9
+
10
  The closure type is declared in the smallest block scope, class scope,
11
  or namespace scope that contains the corresponding *lambda-expression*.
12
 
13
  [*Note 1*: This determines the set of namespaces and classes associated
14
  with the closure type [[basic.lookup.argdep]]. The parameter types of a
15
  *lambda-declarator* do not affect these associated namespaces and
16
  classes. — *end note*]
17
 
18
+ The closure type is not an aggregate type [[dcl.init.aggr]]; it is a
19
+ structural type [[term.structural.type]] if and only if the lambda has
20
+ no *lambda-capture*. An implementation may define the closure type
21
+ differently from what is described below provided this does not alter
22
+ the observable behavior of the program other than by changing:
23
 
24
  - the size and/or alignment of the closure type,
25
+ - whether the closure type is trivially copyable [[class.prop]],
26
+ - whether the closure type is trivially relocatable [[class.prop]],
27
+ - whether the closure type is replaceable [[class.prop]], or
28
  - whether the closure type is a standard-layout class [[class.prop]].
29
 
30
  An implementation shall not add members of rvalue reference type to the
31
  closure type.
32
 
33
  The closure type for a *lambda-expression* has a public inline function
34
  call operator (for a non-generic lambda) or function call operator
35
  template (for a generic lambda) [[over.call]] whose parameters and
36
+ return type are those of the *lambda-expression*'s
37
  *parameter-declaration-clause* and *trailing-return-type* respectively,
38
  and whose *template-parameter-list* consists of the specified
39
+ *template-parameter-list*, if any. The function call operator or the
40
+ function call operator template are direct members of the closure type.
41
+ The *requires-clause* of the function call operator template is the
42
+ *requires-clause* immediately following
43
  `<` *template-parameter-list* `>`, if any. The trailing
44
  *requires-clause* of the function call operator or operator template is
45
  the *requires-clause* of the *lambda-declarator*, if any.
46
 
47
  [*Note 2*: The function call operator template for a generic lambda can
 
78
  Given a lambda with a *lambda-capture*, the type of the explicit object
79
  parameter, if any, of the lambda’s function call operator (possibly
80
  instantiated from a function call operator template) shall be either:
81
 
82
  - the closure type,
83
+ - a class type publicly and unambiguously derived from the closure type,
84
+ or
85
  - a reference to a possibly cv-qualified such type.
86
 
87
  [*Example 2*:
88
 
89
  ``` cpp
 
107
  `static`. Otherwise, it is a non-static member function or member
108
  function template [[class.mfct.non.static]] that is declared `const`
109
  [[class.mfct.non.static]] if and only if the *lambda-expression*’s
110
  *parameter-declaration-clause* is not followed by `mutable` and the
111
  *lambda-declarator* does not contain an explicit object parameter. It is
112
+ neither virtual nor declared `volatile`. Any *noexcept-specifier* or
113
+ *function-contract-specifier* [[dcl.contract.func]] specified on a
114
+ *lambda-expression* applies to the corresponding function call operator
115
+ or operator template. An *attribute-specifier-seq* in a
116
  *lambda-declarator* appertains to the type of the corresponding function
117
  call operator or operator template. An *attribute-specifier-seq* in a
118
  *lambda-expression* preceding a *lambda-declarator* appertains to the
119
  corresponding function call operator or operator template. The function
120
  call operator or any given operator template specialization is a
 
193
 
194
  — *end example*]
195
 
196
  — *end note*]
197
 
198
+ If all potential references to a local entity implicitly captured by a
199
+ *lambda-expression* L occur within the function contract assertions
200
+ [[dcl.contract.func]] of the call operator or operator template of L or
201
+ within *assertion-statement*s [[stmt.contract.assert]] within the body
202
+ of L, the program is ill-formed.
203
+
204
+ [*Note 4*: Adding a contract assertion to an existing C++ program
205
+ cannot cause additional captures. — *end note*]
206
+
207
+ [*Example 6*:
208
+
209
+ ``` cpp
210
+ static int i = 0;
211
+
212
+ void test() {
213
+ auto f1 = [=] pre(i > 0) {}; // OK, no local entities are captured.
214
+
215
+ int i = 1;
216
+ auto f2 = [=] pre(i > 0) {}; // error: cannot implicitly capture i here
217
+ auto f3 = [i] pre(i > 0) {}; // OK, i is captured explicitly.
218
+
219
+ auto f4 = [=] {
220
+ contract_assert(i > 0); // error: cannot implicitly capture i here
221
+ };
222
+
223
+ auto f5 = [=] {
224
+ contract_assert(i > 0); // OK, i is referenced elsewhere.
225
+ (void)i;
226
+ };
227
+
228
+ auto f6 = [=] pre( // #1
229
+ []{
230
+ bool x = true;
231
+ return [=]{ return x; }(); // OK, #1 captures nothing.
232
+ }()) {};
233
+
234
+ bool y = true;
235
+ auto f7 = [=] pre([=]{ return y; }()); // error: outer capture of y is invalid.
236
+ }
237
+ ```
238
+
239
+ — *end example*]
240
+
241
  The closure type for a non-generic *lambda-expression* with no
242
+ *lambda-capture* and no explicit object parameter [[dcl.fct]] whose
243
+ constraints (if any) are satisfied has a conversion function to pointer
244
+ to function with C++ language linkage [[dcl.link]] having the same
245
+ parameter and return types as the closure type’s function call operator.
246
+ The conversion is to “pointer to `noexcept` function” if the function
247
+ call operator has a non-throwing exception specification. If the
248
+ function call operator is a static member function, then the value
249
+ returned by this conversion function is a pointer to the function call
250
+ operator. Otherwise, the value returned by this conversion function is a
251
+ pointer to a function `F` that, when invoked, has the same effect as
252
+ invoking the closure type’s function call operator on a
253
+ default-constructed instance of the closure type. `F` is a constexpr
254
+ function if the function call operator is a constexpr function and is an
255
+ immediate function if the function call operator is an immediate
256
+ function.
257
 
258
+ For a generic lambda with no *lambda-capture* and no explicit object
259
+ parameter [[dcl.fct]], the closure type has a conversion function
260
+ template to pointer to function. The conversion function template has
261
+ the same invented template parameter list, and the pointer to function
262
+ has the same parameter types, as the function call operator template.
263
+ The return type of the pointer to function shall behave as if it were a
264
+ *decltype-specifier* denoting the return type of the corresponding
265
+ function call operator template specialization.
266
 
267
+ [*Note 5*:
268
 
269
  If the generic lambda has no *trailing-return-type* or the
270
  *trailing-return-type* contains a placeholder type, return type
271
  deduction of the corresponding function call operator template
272
  specialization has to be done. The corresponding specialization is that
 
298
  };
299
  ```
300
 
301
  — *end note*]
302
 
303
+ [*Example 7*:
304
 
305
  ``` cpp
306
  void f1(int (*)(int)) { }
307
  void f2(char (*)(int)) { }
308
 
 
322
 
323
  — *end example*]
324
 
325
  If the function call operator template is a static member function
326
  template, then the value returned by any given specialization of this
327
+ conversion function template is a pointer to the corresponding function
328
+ call operator template specialization. Otherwise, the value returned by
329
+ any given specialization of this conversion function template is a
330
+ pointer to a function `F` that, when invoked, has the same effect as
331
+ invoking the generic lambda’s corresponding function call operator
332
+ template specialization on a default-constructed instance of the closure
333
+ type. `F` is a constexpr function if the corresponding specialization is
334
+ a constexpr function and `F` is an immediate function if the function
335
+ call operator template specialization is an immediate function.
 
336
 
337
+ [*Note 6*: This will result in the implicit instantiation of the
338
  generic lambda’s body. The instantiated generic lambda’s return type and
339
+ parameter types need to match the return type and parameter types of the
340
+ pointer to function. — *end note*]
341
 
342
+ [*Example 8*:
343
 
344
  ``` cpp
345
  auto GL = [](auto a) { std::cout << a; return a; };
346
  int (*GL_int)(int) = GL; // OK, through conversion function template
347
  GL_int(3); // OK, same as GL(3)
 
351
 
352
  The conversion function or conversion function template is public,
353
  constexpr, non-virtual, non-explicit, const, and has a non-throwing
354
  exception specification [[except.spec]].
355
 
356
+ [*Example 9*:
357
 
358
  ``` cpp
359
  auto Fwd = [](int (*fp)(int), auto a) { return fp(a); };
360
  auto C = [](auto a) { return a; };
361
 
 
370
 
371
  The *lambda-expression*’s *compound-statement* yields the
372
  *function-body* [[dcl.fct.def]] of the function call operator, but it is
373
  not within the scope of the closure type.
374
 
375
+ [*Example 10*:
376
 
377
  ``` cpp
378
  struct S1 {
379
  int x, y;
380
  int operator()(int);
 
387
  };
388
  ```
389
 
390
  — *end example*]
391
 
392
+ Unless the *compound-statement* is that of a
393
+ *consteval-block-declaration* [[dcl.pre]], a variable `__func__` is
394
+ implicitly defined at the beginning of the *compound-statement* of the
395
+ *lambda-expression*, with semantics as described in 
396
+ [[dcl.fct.def.general]].
397
 
398
  The closure type associated with a *lambda-expression* has no default
399
  constructor if the *lambda-expression* has a *lambda-capture* and a
400
  defaulted default constructor otherwise. It has a defaulted copy
401
  constructor and a defaulted move constructor [[class.copy.ctor]]. It has
402
  a deleted copy assignment operator if the *lambda-expression* has a
403
  *lambda-capture* and defaulted copy and move assignment operators
404
  otherwise [[class.copy.assign]].
405
 
406
+ [*Note 7*: These special member functions are implicitly defined as
407
  usual, which can result in them being defined as deleted. — *end note*]
408
 
409
  The closure type associated with a *lambda-expression* has an
410
  implicitly-declared destructor [[class.dtor]].
411