From Jason Turner

[expr.prim.lambda.capture]

Diff to HTML by rtfpessoa

Files changed (1) hide show
  1. tmp/tmpoex98vh9/{from.md → to.md} +43 -38
tmp/tmpoex98vh9/{from.md → to.md} RENAMED
@@ -37,13 +37,12 @@ simple-capture:
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
@@ -76,35 +75,37 @@ A *lambda-expression* shall not have a *capture-default* or
76
  *simple-capture* in its *lambda-introducer* unless its innermost
77
  enclosing scope is a block scope [[basic.scope.block]] or it appears
78
  within a default member initializer and its innermost enclosing scope is
79
  the corresponding class scope [[basic.scope.class]].
80
 
81
- The *identifier* in a *simple-capture* is looked up using the usual
82
- rules for unqualified name lookup [[basic.lookup.unqual]]; each such
83
- lookup shall find a local entity. The *simple-capture*s `this` and
84
  `* this` denote the local entity `*this`. An entity that is designated
85
  by a *simple-capture* is said to be *explicitly captured*.
86
 
87
- If an *identifier* in a *simple-capture* appears as the *declarator-id*
88
- of a parameter of the *lambda-declarator*'s
89
- *parameter-declaration-clause*, the program is ill-formed.
 
90
 
91
  [*Example 2*:
92
 
93
  ``` cpp
94
  void f() {
95
  int x = 0;
96
- auto g = [x](int x) { return 0; }; // error: parameter and simple-capture have the same name
 
 
97
  }
98
  ```
99
 
100
  — *end example*]
101
 
102
- An *init-capture* without ellipsis behaves as if it declares and
103
- explicitly captures a variable of the form “`auto` *init-capture* `;`”
104
- whose declarative region is the *lambda-expression*’s
105
- *compound-statement*, except that:
106
 
107
  - if the capture is by copy (see below), the non-static data member
108
  declared for the capture and the variable are treated as two different
109
  ways of referring to the same object, which has the lifetime of the
110
  non-static data member, and no additional copy and destruction is
@@ -123,11 +124,14 @@ int x = 4;
123
  auto y = [&r = x, x = x+1]()->int {
124
  r += 2;
125
  return x+2;
126
  }(); // Updates ::x to 6, and initializes y to 7.
127
 
128
- auto z = [a = 42](int a) { return 1; }; // error: parameter and local variable have the same name
 
 
 
129
  ```
130
 
131
  — *end example*]
132
 
133
  For the purposes of lambda capture, an expression potentially references
@@ -141,13 +145,13 @@ local entities as follows:
141
  *id-expression*. — *end note*]
142
  - A `this` expression potentially references `*this`.
143
  - A *lambda-expression* potentially references the local entities named
144
  by its *simple-capture*s.
145
 
146
- If an expression potentially references a local entity within a
147
- declarative region in which it is odr-usable, and the expression would
148
- be potentially evaluated if the effect of any enclosing `typeid`
149
  expressions [[expr.typeid]] were ignored, the entity is said to be
150
  *implicitly captured* by each intervening *lambda-expression* with an
151
  associated *capture-default* that does not explicitly capture it. The
152
  implicit capture of `*this` is deprecated when the *capture-default* is
153
  `=`; see [[depr.capture.this]].
@@ -158,38 +162,38 @@ implicit capture of `*this` is deprecated when the *capture-default* is
158
  void f(int, const int (&)[2] = {}); // #1
159
  void f(const int&, const int (&)[1]); // #2
160
  void test() {
161
  const int x = 17;
162
  auto g = [](auto a) {
163
- f(x); // OK: calls #1, does not capture x
164
  };
165
 
166
  auto g1 = [=](auto a) {
167
- f(x); // OK: calls #1, captures x
168
  };
169
 
170
  auto g2 = [=](auto a) {
171
  int selector[sizeof(a) == 1 ? 1 : 2]{};
172
- f(x, selector); // OK: captures x, might call #1 or #2
173
  };
174
 
175
  auto g3 = [=](auto a) {
176
  typeid(a + x); // captures x regardless of whether a + x is an unevaluated operand
177
  };
178
  }
179
  ```
180
 
181
- Within `g1`, an implementation might optimize away the capture of `x` as
182
  it is not odr-used.
183
 
184
  — *end example*]
185
 
186
  [*Note 4*:
187
 
188
  The set of captured entities is determined syntactically, and entities
189
- might be implicitly captured even if the expression denoting a local
190
- entity is within a discarded statement [[stmt.if]].
191
 
192
  [*Example 5*:
193
 
194
  ``` cpp
195
  template<bool B>
@@ -205,12 +209,12 @@ void f(int n) {
205
  — *end example*]
206
 
207
  — *end note*]
208
 
209
  An entity is *captured* if it is captured explicitly or implicitly. An
210
- entity captured by a *lambda-expression* is odr-used [[basic.def.odr]]
211
- in the scope containing the *lambda-expression*.
212
 
213
  [*Note 5*: As a consequence, if a *lambda-expression* explicitly
214
  captures an entity that is not odr-usable, the program is ill-formed
215
  [[basic.def.odr]]. — *end note*]
216
 
@@ -220,26 +224,26 @@ captures an entity that is not odr-usable, the program is ill-formed
220
  void f1(int i) {
221
  int const N = 20;
222
  auto m1 = [=]{
223
  int const M = 30;
224
  auto m2 = [i]{
225
- int x[N][M]; // OK: N and M are not odr-used
226
- x[0][0] = i; // OK: i is explicitly captured by m2 and implicitly captured by m1
227
  };
228
  };
229
  struct s1 {
230
  int f;
231
  void work(int n) {
232
  int m = n*n;
233
  int j = 40;
234
  auto m3 = [this,m] {
235
  auto m4 = [&,j] { // error: j not odr-usable due to intervening lambda m3
236
  int x = n; // error: n is odr-used but not odr-usable due to intervening lambda m3
237
- x += m; // OK: m implicitly captured by m4 and explicitly captured by m3
238
  x += i; // error: i is odr-used but not odr-usable
239
  // due to intervening function and class scopes
240
- x += f; // OK: this captured implicitly by m4 and explicitly by m3
241
  };
242
  };
243
  }
244
  };
245
  }
@@ -302,11 +306,11 @@ the entity is a reference to an object, an lvalue reference to the
302
  referenced function type if the entity is a reference to a function, or
303
  the type of the corresponding captured entity otherwise. A member of an
304
  anonymous union shall not be captured by copy.
305
 
306
  Every *id-expression* within the *compound-statement* of a
307
- *lambda-expression* that is an odr-use [[basic.def.odr]] of an entity
308
  captured by copy is transformed into an access to the corresponding
309
  unnamed data member of the closure type.
310
 
311
  [*Note 7*: An *id-expression* that is not an odr-use refers to the
312
  original entity, never to a member of the closure type. However, such an
@@ -322,12 +326,12 @@ the closure type.
322
  ``` cpp
323
  void f(const int*);
324
  void g() {
325
  const int N = 10;
326
  [=] {
327
- int arr[N]; // OK: not an odr-use, refers to automatic variable
328
- f(&N); // OK: causes N to be captured; &N points to
329
  // the corresponding member of the closure type
330
  };
331
  }
332
  ```
333
 
@@ -375,13 +379,15 @@ auto h(int &r) {
375
 
376
  If a *lambda-expression* `m2` captures an entity and that entity is
377
  captured by an immediately enclosing *lambda-expression* `m1`, then
378
  `m2`’s capture is transformed as follows:
379
 
380
- - if `m1` captures the entity by copy, `m2` captures the corresponding
381
- non-static data member of `m1`’s closure type;
382
- - if `m1` captures the entity by reference, `m2` captures the same
 
 
383
  entity captured by `m1`.
384
 
385
  [*Example 11*:
386
 
387
  The nested *lambda-expression*s and invocations below will output
@@ -422,12 +428,11 @@ captured by reference, invoking the function call operator of the
422
  corresponding *lambda-expression* after the lifetime of the entity has
423
  ended is likely to result in undefined behavior. — *end note*]
424
 
425
  A *simple-capture* containing an ellipsis is a pack expansion
426
  [[temp.variadic]]. An *init-capture* containing an ellipsis is a pack
427
- expansion that introduces an *init-capture* pack [[temp.variadic]] whose
428
- declarative region is the *lambda-expression*’s *compound-statement*.
429
 
430
  [*Example 12*:
431
 
432
  ``` cpp
433
  template<class... Args>
 
37
  init-capture:
38
  '...'ₒₚₜ identifier initializer
39
  '&' '...'ₒₚₜ identifier initializer
40
  ```
41
 
42
+ The body of a *lambda-expression* may refer to local entities of
43
+ enclosing block scopes by capturing those entities, as described below.
 
44
 
45
  If a *lambda-capture* includes a *capture-default* that is `&`, no
46
  identifier in a *simple-capture* of that *lambda-capture* shall be
47
  preceded by `&`. If a *lambda-capture* includes a *capture-default* that
48
  is `=`, each *simple-capture* of that *lambda-capture* shall be of the
 
75
  *simple-capture* in its *lambda-introducer* unless its innermost
76
  enclosing scope is a block scope [[basic.scope.block]] or it appears
77
  within a default member initializer and its innermost enclosing scope is
78
  the corresponding class scope [[basic.scope.class]].
79
 
80
+ The *identifier* in a *simple-capture* shall denote a local entity
81
+ [[basic.lookup.unqual]], [[basic.pre]]. The *simple-capture*s `this` and
 
82
  `* this` denote the local entity `*this`. An entity that is designated
83
  by a *simple-capture* is said to be *explicitly captured*.
84
 
85
+ If an *identifier* in a *capture* appears as the *declarator-id* of a
86
+ parameter of the *lambda-declarator*s *parameter-declaration-clause* or
87
+ as the name of a template parameter of the *lambda-expression*’s
88
+ *template-parameter-list*, the program is ill-formed.
89
 
90
  [*Example 2*:
91
 
92
  ``` cpp
93
  void f() {
94
  int x = 0;
95
+ auto g = [x](int x) { return 0; }; // error: parameter and capture have the same name
96
+ auto h = [y = 0]<typename y>(y) { return 0; }; // error: template parameter and capture
97
+ // have the same name
98
  }
99
  ```
100
 
101
  — *end example*]
102
 
103
+ An *init-capture* inhabits the lambda scope [[basic.scope.lambda]] of
104
+ the *lambda-expression*. An *init-capture* without ellipsis behaves as
105
+ if it declares and explicitly captures a variable of the form “`auto`
106
+ *init-capture* `;`”, except that:
107
 
108
  - if the capture is by copy (see below), the non-static data member
109
  declared for the capture and the variable are treated as two different
110
  ways of referring to the same object, which has the lifetime of the
111
  non-static data member, and no additional copy and destruction is
 
124
  auto y = [&r = x, x = x+1]()->int {
125
  r += 2;
126
  return x+2;
127
  }(); // Updates ::x to 6, and initializes y to 7.
128
 
129
+ auto z = [a = 42](int a) { return 1; }; // error: parameter and conceptual local variable have the same name
130
+ auto counter = [i=0]() mutable -> decltype(i) { // OK, returns int
131
+ return i++;
132
+ };
133
  ```
134
 
135
  — *end example*]
136
 
137
  For the purposes of lambda capture, an expression potentially references
 
145
  *id-expression*. — *end note*]
146
  - A `this` expression potentially references `*this`.
147
  - A *lambda-expression* potentially references the local entities named
148
  by its *simple-capture*s.
149
 
150
+ If an expression potentially references a local entity within a scope in
151
+ which it is odr-usable [[basic.def.odr]], and the expression would be
152
+ potentially evaluated if the effect of any enclosing `typeid`
153
  expressions [[expr.typeid]] were ignored, the entity is said to be
154
  *implicitly captured* by each intervening *lambda-expression* with an
155
  associated *capture-default* that does not explicitly capture it. The
156
  implicit capture of `*this` is deprecated when the *capture-default* is
157
  `=`; see [[depr.capture.this]].
 
162
  void f(int, const int (&)[2] = {}); // #1
163
  void f(const int&, const int (&)[1]); // #2
164
  void test() {
165
  const int x = 17;
166
  auto g = [](auto a) {
167
+ f(x); // OK, calls #1, does not capture x
168
  };
169
 
170
  auto g1 = [=](auto a) {
171
+ f(x); // OK, calls #1, captures x
172
  };
173
 
174
  auto g2 = [=](auto a) {
175
  int selector[sizeof(a) == 1 ? 1 : 2]{};
176
+ f(x, selector); // OK, captures x, can call #1 or #2
177
  };
178
 
179
  auto g3 = [=](auto a) {
180
  typeid(a + x); // captures x regardless of whether a + x is an unevaluated operand
181
  };
182
  }
183
  ```
184
 
185
+ Within `g1`, an implementation can optimize away the capture of `x` as
186
  it is not odr-used.
187
 
188
  — *end example*]
189
 
190
  [*Note 4*:
191
 
192
  The set of captured entities is determined syntactically, and entities
193
+ are implicitly captured even if the expression denoting a local entity
194
+ is within a discarded statement [[stmt.if]].
195
 
196
  [*Example 5*:
197
 
198
  ``` cpp
199
  template<bool B>
 
209
  — *end example*]
210
 
211
  — *end note*]
212
 
213
  An entity is *captured* if it is captured explicitly or implicitly. An
214
+ entity captured by a *lambda-expression* is odr-used [[term.odr.use]] by
215
+ the *lambda-expression*.
216
 
217
  [*Note 5*: As a consequence, if a *lambda-expression* explicitly
218
  captures an entity that is not odr-usable, the program is ill-formed
219
  [[basic.def.odr]]. — *end note*]
220
 
 
224
  void f1(int i) {
225
  int const N = 20;
226
  auto m1 = [=]{
227
  int const M = 30;
228
  auto m2 = [i]{
229
+ int x[N][M]; // OK, N and M are not odr-used
230
+ x[0][0] = i; // OK, i is explicitly captured by m2 and implicitly captured by m1
231
  };
232
  };
233
  struct s1 {
234
  int f;
235
  void work(int n) {
236
  int m = n*n;
237
  int j = 40;
238
  auto m3 = [this,m] {
239
  auto m4 = [&,j] { // error: j not odr-usable due to intervening lambda m3
240
  int x = n; // error: n is odr-used but not odr-usable due to intervening lambda m3
241
+ x += m; // OK, m implicitly captured by m4 and explicitly captured by m3
242
  x += i; // error: i is odr-used but not odr-usable
243
  // due to intervening function and class scopes
244
+ x += f; // OK, this captured implicitly by m4 and explicitly by m3
245
  };
246
  };
247
  }
248
  };
249
  }
 
306
  referenced function type if the entity is a reference to a function, or
307
  the type of the corresponding captured entity otherwise. A member of an
308
  anonymous union shall not be captured by copy.
309
 
310
  Every *id-expression* within the *compound-statement* of a
311
+ *lambda-expression* that is an odr-use [[term.odr.use]] of an entity
312
  captured by copy is transformed into an access to the corresponding
313
  unnamed data member of the closure type.
314
 
315
  [*Note 7*: An *id-expression* that is not an odr-use refers to the
316
  original entity, never to a member of the closure type. However, such an
 
326
  ``` cpp
327
  void f(const int*);
328
  void g() {
329
  const int N = 10;
330
  [=] {
331
+ int arr[N]; // OK, not an odr-use, refers to automatic variable
332
+ f(&N); // OK, causes N to be captured; &N points to
333
  // the corresponding member of the closure type
334
  };
335
  }
336
  ```
337
 
 
379
 
380
  If a *lambda-expression* `m2` captures an entity and that entity is
381
  captured by an immediately enclosing *lambda-expression* `m1`, then
382
  `m2`’s capture is transformed as follows:
383
 
384
+ - If `m1` captures the entity by copy, `m2` captures the corresponding
385
+ non-static data member of `m1`’s closure type; if `m1` is not
386
+ `mutable`, the non-static data member is considered to be
387
+ const-qualified.
388
+ - If `m1` captures the entity by reference, `m2` captures the same
389
  entity captured by `m1`.
390
 
391
  [*Example 11*:
392
 
393
  The nested *lambda-expression*s and invocations below will output
 
428
  corresponding *lambda-expression* after the lifetime of the entity has
429
  ended is likely to result in undefined behavior. — *end note*]
430
 
431
  A *simple-capture* containing an ellipsis is a pack expansion
432
  [[temp.variadic]]. An *init-capture* containing an ellipsis is a pack
433
+ expansion that declares an *init-capture* pack [[temp.variadic]].
 
434
 
435
  [*Example 12*:
436
 
437
  ``` cpp
438
  template<class... Args>