Date: 2016-06-27

Thomas Köppe <tkoeppe@google.com>

ISO/IEC JTC1 SC22 WG21 P0409R0

To: EWG

Allow lambda capture [=, this]

Contents

  1. Revision history
  2. Proposal
  3. Impact on the Standard
  4. Formal wording

Revision history

Proposal

We propose to allow [=, this] as a lambda capture.

With the introduction of capture-this-by-value in C++17, it may be desirable to increase code readability by being explicit about the kind of capture in the presence of a [=]-default:

std::function<void()> X::f(int n) {   return coin() ? [=,  this]() { g(n, x_, y_, z_); }                 : [=, *this]() { h(n, x_, y_, z_); }; }

By contrast, when both [=] and [=, *this] are present in a code base in large numbers, it may be easy to forget that the former is different from the latter: It is hard to notice the absence of something. In such situations, authors may wish to be explicit and to spare the reader from having remember the correct default.

Impact on the Standard

The proposal is a pure core language extension. The newly allowed syntax was previously ill-formed.

Formal wording

In section 5.1.5 [expr.prim.lambda], change paragraph 9 as follows.

If a lambda-capture includes a capture-default that is &, no identifier in a simple-capture of that lambda-capture shall be preceded by &. If a lambda-capture includes a capture-default that is =, each simple-capture of that lambda-capture shall be of the form “& identifier, “this or “* this”. [Note: The form [&, this] is redundant but accepted for compatibility with ISO C++ 2014. – end note] Ignoring appearances in initializers of init-captures, an identifier or this shall not appear more than once in a lambda-capture. [Example:

struct S2 { void f(int i); }; void S2::f(int i) {   [&, i]{ };         // OK   [&, this, i]{ };   // OK, equivalent to [&, i]   [&, &i]{ };        // error: i preceded by & when & is the default   [=, *this]{ };     // OK   [=, this]{ };      // error: this when = is the defaultOK, equivalent to [=]   [i, i]{ };         // error: i repeated   [this, *this]{ };  // error: this appears twice }

end example]