From Jason Turner

[expr.prim.lambda.capture]

Diff to HTML by rtfpessoa

Files changed (1) hide show
  1. tmp/tmp2ieqnjmr/{from.md → to.md} +425 -0
tmp/tmp2ieqnjmr/{from.md → to.md} RENAMED
@@ -0,0 +1,425 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #### Captures <a id="expr.prim.lambda.capture">[[expr.prim.lambda.capture]]</a>
2
+
3
+ ``` bnf
4
+ lambda-capture:
5
+ capture-default
6
+ capture-list
7
+ capture-default ',' capture-list
8
+ ```
9
+
10
+ ``` bnf
11
+ capture-default:
12
+ '&'
13
+ '='
14
+ ```
15
+
16
+ ``` bnf
17
+ capture-list:
18
+ capture '...'ₒₚₜ
19
+ capture-list ',' capture '...'ₒₚₜ
20
+ ```
21
+
22
+ ``` bnf
23
+ capture:
24
+ simple-capture
25
+ init-capture
26
+ ```
27
+
28
+ ``` bnf
29
+ simple-capture:
30
+ identifier
31
+ '&' identifier
32
+ 'this'
33
+ '* this'
34
+ ```
35
+
36
+ ``` bnf
37
+ init-capture:
38
+ identifier initializer
39
+ '&' identifier initializer
40
+ ```
41
+
42
+ The body of a *lambda-expression* may refer to variables with automatic
43
+ storage duration and the `*this` object (if any) of enclosing block
44
+ scopes by capturing those entities, as described below.
45
+
46
+ If a *lambda-capture* includes a *capture-default* that is `&`, no
47
+ identifier in a *simple-capture* of that *lambda-capture* shall be
48
+ preceded by `&`. If a *lambda-capture* includes a *capture-default* that
49
+ is `=`, each *simple-capture* of that *lambda-capture* shall be of the
50
+ form “`&` *identifier*” or “`* this`”.
51
+
52
+ [*Note 1*: The form `[&,this]` is redundant but accepted for
53
+ compatibility with ISO C++14. — *end note*]
54
+
55
+ Ignoring appearances in *initializer*s of *init-capture*s, an identifier
56
+ or `this` shall not appear more than once in a *lambda-capture*.
57
+
58
+ [*Example 1*:
59
+
60
+ ``` cpp
61
+ struct S2 { void f(int i); };
62
+ void S2::f(int i) {
63
+ [&, i]{ }; // OK
64
+ [&, &i]{ }; // error: i preceded by & when & is the default
65
+ [=, *this]{ }; // OK
66
+ [=, this]{ }; // error: this when = is the default
67
+ [i, i]{ }; // error: i repeated
68
+ [this, *this]{ }; // error: this appears twice
69
+ }
70
+ ```
71
+
72
+ — *end example*]
73
+
74
+ A *lambda-expression* whose smallest enclosing scope is a block scope (
75
+ [[basic.scope.block]]) is a *local lambda expression*; any other
76
+ *lambda-expression* shall not have a *capture-default* or
77
+ *simple-capture* in its *lambda-introducer*. The *reaching scope* of a
78
+ local lambda expression is the set of enclosing scopes up to and
79
+ including the innermost enclosing function and its parameters.
80
+
81
+ [*Note 2*: This reaching scope includes any intervening
82
+ *lambda-expression*s. — *end note*]
83
+
84
+ The *identifier* in a *simple-capture* is looked up using the usual
85
+ rules for unqualified name lookup ([[basic.lookup.unqual]]); each such
86
+ lookup shall find an entity. An entity that is designated by a
87
+ *simple-capture* is said to be *explicitly captured*, and shall be
88
+ `*this` (when the *simple-capture* is “`this`” or “`* this`”) or a
89
+ variable with automatic storage duration declared in the reaching scope
90
+ of the local lambda expression.
91
+
92
+ If an *identifier* in a *simple-capture* appears as the *declarator-id*
93
+ of a parameter of the *lambda-declarator*'s
94
+ *parameter-declaration-clause*, the program is ill-formed.
95
+
96
+ [*Example 2*:
97
+
98
+ ``` cpp
99
+ void f() {
100
+ int x = 0;
101
+ auto g = [x](int x) { return 0; } // error: parameter and simple-capture have the same name
102
+ }
103
+ ```
104
+
105
+ — *end example*]
106
+
107
+ An *init-capture* behaves as if it declares and explicitly captures a
108
+ variable of the form “`auto` *init-capture* `;`” whose declarative
109
+ region is the *lambda-expression*’s *compound-statement*, except that:
110
+
111
+ - if the capture is by copy (see below), the non-static data member
112
+ declared for the capture and the variable are treated as two different
113
+ ways of referring to the same object, which has the lifetime of the
114
+ non-static data member, and no additional copy and destruction is
115
+ performed, and
116
+ - if the capture is by reference, the variable’s lifetime ends when the
117
+ closure object’s lifetime ends.
118
+
119
+ [*Note 3*: This enables an *init-capture* like “`x = std::move(x)`”;
120
+ the second “`x`” must bind to a declaration in the surrounding
121
+ context. — *end note*]
122
+
123
+ [*Example 3*:
124
+
125
+ ``` cpp
126
+ int x = 4;
127
+ auto y = [&r = x, x = x+1]()->int {
128
+ r += 2;
129
+ return x+2;
130
+ }(); // Updates ::x to 6, and initializes y to 7.
131
+
132
+ auto z = [a = 42](int a) { return 1; } // error: parameter and local variable have the same name
133
+ ```
134
+
135
+ — *end example*]
136
+
137
+ A *lambda-expression* with an associated *capture-default* that does not
138
+ explicitly capture `*this` or a variable with automatic storage duration
139
+ (this excludes any *id-expression* that has been found to refer to an
140
+ *init-capture*'s associated non-static data member), is said to
141
+ *implicitly capture* the entity (i.e., `*this` or a variable) if the
142
+ *compound-statement*:
143
+
144
+ - odr-uses ([[basic.def.odr]]) the entity (in the case of a variable),
145
+ - odr-uses ([[basic.def.odr]]) `this` (in the case of the object
146
+ designated by `*this`), or
147
+ - names the entity in a potentially-evaluated expression (
148
+ [[basic.def.odr]]) where the enclosing full-expression depends on a
149
+ generic lambda parameter declared within the reaching scope of the
150
+ *lambda-expression*.
151
+
152
+ [*Example 4*:
153
+
154
+ ``` cpp
155
+ void f(int, const int (&)[2] = {}) { } // #1
156
+ void f(const int&, const int (&)[1]) { } // #2
157
+ void test() {
158
+ const int x = 17;
159
+ auto g = [](auto a) {
160
+ f(x); // OK: calls #1, does not capture x
161
+ };
162
+
163
+ auto g2 = [=](auto a) {
164
+ int selector[sizeof(a) == 1 ? 1 : 2]{};
165
+ f(x, selector); // OK: is a dependent expression, so captures x
166
+ };
167
+ }
168
+ ```
169
+
170
+ — *end example*]
171
+
172
+ All such implicitly captured entities shall be declared within the
173
+ reaching scope of the lambda expression.
174
+
175
+ [*Note 4*: The implicit capture of an entity by a nested
176
+ *lambda-expression* can cause its implicit capture by the containing
177
+ *lambda-expression* (see below). Implicit odr-uses of `this` can result
178
+ in implicit capture. — *end note*]
179
+
180
+ An entity is *captured* if it is captured explicitly or implicitly. An
181
+ entity captured by a *lambda-expression* is odr-used (
182
+ [[basic.def.odr]]) in the scope containing the *lambda-expression*. If
183
+ `*this` is captured by a local lambda expression, its nearest enclosing
184
+ function shall be a non-static member function. If a *lambda-expression*
185
+ or an instantiation of the function call operator template of a generic
186
+ lambda odr-uses ([[basic.def.odr]]) `this` or a variable with automatic
187
+ storage duration from its reaching scope, that entity shall be captured
188
+ by the *lambda-expression*. If a *lambda-expression* captures an entity
189
+ and that entity is not defined or captured in the immediately enclosing
190
+ lambda expression or function, the program is ill-formed.
191
+
192
+ [*Example 5*:
193
+
194
+ ``` cpp
195
+ void f1(int i) {
196
+ int const N = 20;
197
+ auto m1 = [=]{
198
+ int const M = 30;
199
+ auto m2 = [i]{
200
+ int x[N][M]; // OK: N and M are not odr-used
201
+ x[0][0] = i; // OK: i is explicitly captured by m2 and implicitly captured by m1
202
+ };
203
+ };
204
+ struct s1 {
205
+ int f;
206
+ void work(int n) {
207
+ int m = n*n;
208
+ int j = 40;
209
+ auto m3 = [this,m] {
210
+ auto m4 = [&,j] { // error: j not captured by m3
211
+ int x = n; // error: n implicitly captured by m4 but not captured by m3
212
+ x += m; // OK: m implicitly captured by m4 and explicitly captured by m3
213
+ x += i; // error: i is outside of the reaching scope
214
+ x += f; // OK: this captured implicitly by m4 and explicitly by m3
215
+ };
216
+ };
217
+ }
218
+ };
219
+ }
220
+
221
+ struct s2 {
222
+ double ohseven = .007;
223
+ auto f() {
224
+ return [this] {
225
+ return [*this] {
226
+ return ohseven; // OK
227
+ }
228
+ }();
229
+ }
230
+ auto g() {
231
+ return [] {
232
+ return [*this] { }; // error: *this not captured by outer lambda-expression
233
+ }();
234
+ }
235
+ };
236
+ ```
237
+
238
+ — *end example*]
239
+
240
+ A *lambda-expression* appearing in a default argument shall not
241
+ implicitly or explicitly capture any entity.
242
+
243
+ [*Example 6*:
244
+
245
+ ``` cpp
246
+ void f2() {
247
+ int i = 1;
248
+ void g1(int = ([i]{ return i; })()); // ill-formed
249
+ void g2(int = ([i]{ return 0; })()); // ill-formed
250
+ void g3(int = ([=]{ return i; })()); // ill-formed
251
+ void g4(int = ([=]{ return 0; })()); // OK
252
+ void g5(int = ([]{ return sizeof i; })()); // OK
253
+ }
254
+ ```
255
+
256
+ — *end example*]
257
+
258
+ An entity is *captured by copy* if
259
+
260
+ - it is implicitly captured, the *capture-default* is `=`, and the
261
+ captured entity is not `*this`, or
262
+ - it is explicitly captured with a capture that is not of the form
263
+ `this`, `&` *identifier*, or `&` *identifier* *initializer*.
264
+
265
+ For each entity captured by copy, an unnamed non-static data member is
266
+ declared in the closure type. The declaration order of these members is
267
+ unspecified. The type of such a data member is the referenced type if
268
+ the entity is a reference to an object, an lvalue reference to the
269
+ referenced function type if the entity is a reference to a function, or
270
+ the type of the corresponding captured entity otherwise. A member of an
271
+ anonymous union shall not be captured by copy.
272
+
273
+ Every *id-expression* within the *compound-statement* of a
274
+ *lambda-expression* that is an odr-use ([[basic.def.odr]]) of an entity
275
+ captured by copy is transformed into an access to the corresponding
276
+ unnamed data member of the closure type.
277
+
278
+ [*Note 5*: An *id-expression* that is not an odr-use refers to the
279
+ original entity, never to a member of the closure type. Furthermore,
280
+ such an *id-expression* does not cause the implicit capture of the
281
+ entity. — *end note*]
282
+
283
+ If `*this` is captured by copy, each odr-use of `this` is transformed
284
+ into a pointer to the corresponding unnamed data member of the closure
285
+ type, cast ([[expr.cast]]) to the type of `this`.
286
+
287
+ [*Note 6*: The cast ensures that the transformed expression is a
288
+ prvalue. — *end note*]
289
+
290
+ An *id-expression* within the *compound-statement* of a
291
+ *lambda-expression* that is an odr-use of a reference captured by
292
+ reference refers to the entity to which the captured reference is bound
293
+ and not to the captured reference.
294
+
295
+ [*Note 7*: The validity of such captures is determined by the lifetime
296
+ of the object to which the reference refers, not by the lifetime of the
297
+ reference itself. — *end note*]
298
+
299
+ [*Example 7*:
300
+
301
+ ``` cpp
302
+ void f(const int*);
303
+ void g() {
304
+ const int N = 10;
305
+ [=] {
306
+ int arr[N]; // OK: not an odr-use, refers to automatic variable
307
+ f(&N); // OK: causes N to be captured; &N points to
308
+ // the corresponding member of the closure type
309
+ };
310
+ }
311
+ auto h(int &r) {
312
+ return [&] {
313
+ ++r; // Valid after h returns if the lifetime of the
314
+ // object to which r is bound has not ended
315
+ };
316
+ }
317
+ ```
318
+
319
+ — *end example*]
320
+
321
+ An entity is *captured by reference* if it is implicitly or explicitly
322
+ captured but not captured by copy. It is unspecified whether additional
323
+ unnamed non-static data members are declared in the closure type for
324
+ entities captured by reference. If declared, such non-static data
325
+ members shall be of literal type.
326
+
327
+ [*Example 8*:
328
+
329
+ ``` cpp
330
+ // The inner closure type must be a literal type regardless of how reference captures are represented.
331
+ static_assert([](int n) { return [&n] { return ++n; }(); }(3) == 4);
332
+ ```
333
+
334
+ — *end example*]
335
+
336
+ A bit-field or a member of an anonymous union shall not be captured by
337
+ reference.
338
+
339
+ If a *lambda-expression* `m2` captures an entity and that entity is
340
+ captured by an immediately enclosing *lambda-expression* `m1`, then
341
+ `m2`’s capture is transformed as follows:
342
+
343
+ - if `m1` captures the entity by copy, `m2` captures the corresponding
344
+ non-static data member of `m1`’s closure type;
345
+ - if `m1` captures the entity by reference, `m2` captures the same
346
+ entity captured by `m1`.
347
+
348
+ [*Example 9*:
349
+
350
+ The nested lambda expressions and invocations below will output
351
+ `123234`.
352
+
353
+ ``` cpp
354
+ int a = 1, b = 1, c = 1;
355
+ auto m1 = [a, &b, &c]() mutable {
356
+ auto m2 = [a, b, &c]() mutable {
357
+ std::cout << a << b << c;
358
+ a = 4; b = 4; c = 4;
359
+ };
360
+ a = 3; b = 3; c = 3;
361
+ m2();
362
+ };
363
+ a = 2; b = 2; c = 2;
364
+ m1();
365
+ std::cout << a << b << c;
366
+ ```
367
+
368
+ — *end example*]
369
+
370
+ Every occurrence of `decltype((x))` where `x` is a possibly
371
+ parenthesized *id-expression* that names an entity of automatic storage
372
+ duration is treated as if `x` were transformed into an access to a
373
+ corresponding data member of the closure type that would have been
374
+ declared if `x` were an odr-use of the denoted entity.
375
+
376
+ [*Example 10*:
377
+
378
+ ``` cpp
379
+ void f3() {
380
+ float x, &r = x;
381
+ [=] { // x and r are not captured (appearance in a decltype operand is not an odr-use)
382
+ decltype(x) y1; // y1 has type float
383
+ decltype((x)) y2 = y1; // y2 has type float const& because this lambda is not mutable and x is an lvalue
384
+ decltype(r) r1 = y1; // r1 has type float& (transformation not considered)
385
+ decltype((r)) r2 = y2; // r2 has type float const&
386
+ };
387
+ }
388
+ ```
389
+
390
+ — *end example*]
391
+
392
+ When the *lambda-expression* is evaluated, the entities that are
393
+ captured by copy are used to direct-initialize each corresponding
394
+ non-static data member of the resulting closure object, and the
395
+ non-static data members corresponding to the *init-capture*s are
396
+ initialized as indicated by the corresponding *initializer* (which may
397
+ be copy- or direct-initialization). (For array members, the array
398
+ elements are direct-initialized in increasing subscript order.) These
399
+ initializations are performed in the (unspecified) order in which the
400
+ non-static data members are declared.
401
+
402
+ [*Note 8*: This ensures that the destructions will occur in the reverse
403
+ order of the constructions. — *end note*]
404
+
405
+ [*Note 9*: If a non-reference entity is implicitly or explicitly
406
+ captured by reference, invoking the function call operator of the
407
+ corresponding *lambda-expression* after the lifetime of the entity has
408
+ ended is likely to result in undefined behavior. — *end note*]
409
+
410
+ A *simple-capture* followed by an ellipsis is a pack expansion (
411
+ [[temp.variadic]]). An *init-capture* followed by an ellipsis is
412
+ ill-formed.
413
+
414
+ [*Example 11*:
415
+
416
+ ``` cpp
417
+ template<class... Args>
418
+ void f(Args... args) {
419
+ auto lm = [&, args...] { return g(args...); };
420
+ lm();
421
+ }
422
+ ```
423
+
424
+ — *end example*]
425
+