8 Expressions [expr]

8.1 Primary expressions [expr.prim]

8.1.5 Lambda expressions [expr.prim.lambda]

8.1.5.2 Captures [expr.prim.lambda.capture]

lambda-capture:
	capture-default
	capture-list
	capture-default , capture-list
capture-default:
	&
	=
capture-list:
	capture ...opt
	capture-list , capture ...opt
capture:
	simple-capture
	init-capture
simple-capture:
	identifier
	& identifier
	this
	* this
init-capture:
	identifier initializer
	& identifier initializer

The body of a lambda-expression may refer to variables with automatic storage duration and the *this object (if any) of enclosing block scopes by capturing those entities, as described below.

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” 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
  [&, &i]{ };       // error: i preceded by & when & is the default
  [=, *this]{ };    // OK
  [=, this]{ };     // error: this when = is the default
  [i, i]{ };        // error: i repeated
  [this, *this]{ }; // error: this appears twice
}

end example]

A lambda-expression whose smallest enclosing scope is a block scope is a local lambda expression; any other lambda-expression shall not have a capture-default or simple-capture in its lambda-introducer. The reaching scope of a local lambda expression is the set of enclosing scopes up to and including the innermost enclosing function and its parameters. [Note: This reaching scope includes any intervening lambda-expressions. end note]

The identifier in a simple-capture is looked up using the usual rules for unqualified name lookup; each such lookup shall find an entity. An entity that is designated by a simple-capture is said to be explicitly captured, and shall be *this (when the simple-capture is “this” or “* this”) or a variable with automatic storage duration declared in the reaching scope of the local lambda expression.

If an identifier in a simple-capture appears as the declarator-id of a parameter of the lambda-declarator's parameter-declaration-clause, the program is ill-formed. [Example:

void f() {
  int x = 0;
  auto g = [x](int x) { return 0; }    // error: parameter and simple-capture have the same name
}

end example]

An init-capture behaves as if it declares and explicitly captures a variable of the form “auto init-capture ;” whose declarative region is the lambda-expression's compound-statement, except that:

[Note: This enables an init-capture like “x = std​::​move(x)”; the second “x” must bind to a declaration in the surrounding context. end note] [Example:

int x = 4;
auto y = [&r = x, x = x+1]()->int {
            r += 2;
            return x+2;
         }();  // Updates ​::​x to 6, and initializes y to 7.

auto z = [a = 42](int a) { return 1; } // error: parameter and local variable have the same name

end example]

A lambda-expression with an associated capture-default that does not explicitly capture *this or a variable with automatic storage duration (this excludes any id-expression that has been found to refer to an init-capture's associated non-static data member), is said to implicitly capture the entity (i.e., *this or a variable) if the compound-statement:

[Example:

void f(int, const int (&)[2] = {})    { }   // #1
void f(const int&, const int (&)[1])  { }   // #2
void test() {
  const int x = 17;
  auto g = [](auto a) {
    f(x);                       // OK: calls #1, does not capture x
  };

  auto g2 = [=](auto a) {
    int selector[sizeof(a) == 1 ? 1 : 2]{};
    f(x, selector);             // OK: is a dependent expression, so captures x
  };
}

end example] All such implicitly captured entities shall be declared within the reaching scope of the lambda expression. [Note: The implicit capture of an entity by a nested lambda-expression can cause its implicit capture by the containing lambda-expression (see below). Implicit odr-uses of this can result in implicit capture. end note]

An entity is captured if it is captured explicitly or implicitly. An entity captured by a lambda-expression is odr-used in the scope containing the lambda-expression. If *this is captured by a local lambda expression, its nearest enclosing function shall be a non-static member function. If a lambda-expression or an instantiation of the function call operator template of a generic lambda odr-uses this or a variable with automatic storage duration from its reaching scope, that entity shall be captured by the lambda-expression. If a lambda-expression captures an entity and that entity is not defined or captured in the immediately enclosing lambda expression or function, the program is ill-formed. [Example:

void f1(int i) {
  int const N = 20;
  auto m1 = [=]{
    int const M = 30;
    auto m2 = [i]{
      int x[N][M];          // OK: N and M are not odr-used
      x[0][0] = i;          // OK: i is explicitly captured by m2 and implicitly captured by m1
    };
  };
  struct s1 {
    int f;
    void work(int n) {
      int m = n*n;
      int j = 40;
      auto m3 = [this,m] {
        auto m4 = [&,j] {   // error: j not captured by m3
          int x = n;        // error: n implicitly captured by m4 but not captured by m3
          x += m;           // OK: m implicitly captured by m4 and explicitly captured by m3
          x += i;           // error: i is outside of the reaching scope
          x += f;           // OK: this captured implicitly by m4 and explicitly by m3
        };
      };
    }
  };
}

struct s2 {
  double ohseven = .007;
  auto f() {
    return [this] {
      return [*this] {
          return ohseven;   // OK
      }
    }();
  }
  auto g() {
    return [] {
      return [*this] { };   // error: *this not captured by outer lambda-expression
    }();
  }
};

end example]

A lambda-expression appearing in a default argument shall not implicitly or explicitly capture any entity. [Example:

void f2() {
  int i = 1;
  void g1(int = ([i]{ return i; })());          // ill-formed
  void g2(int = ([i]{ return 0; })());          // ill-formed
  void g3(int = ([=]{ return i; })());          // ill-formed
  void g4(int = ([=]{ return 0; })());          // OK
  void g5(int = ([]{ return sizeof i; })());    // OK
}

end example]

An entity is captured by copy if

For each entity captured by copy, an unnamed non-static data member is declared in the closure type. The declaration order of these members is unspecified. The type of such a data member is the referenced type if the entity is a reference to an object, an lvalue reference to the referenced function type if the entity is a reference to a function, or the type of the corresponding captured entity otherwise. A member of an anonymous union shall not be captured by copy.

Every id-expression within the compound-statement of a lambda-expression that is an odr-use of an entity captured by copy is transformed into an access to the corresponding unnamed data member of the closure type. [Note: An id-expression that is not an odr-use refers to the original entity, never to a member of the closure type. Furthermore, such an id-expression does not cause the implicit capture of the entity. end note] If *this is captured by copy, each odr-use of this is transformed into a pointer to the corresponding unnamed data member of the closure type, cast to the type of this. [Note: The cast ensures that the transformed expression is a prvalue. end note] An id-expression within the compound-statement of a lambda-expression that is an odr-use of a reference captured by reference refers to the entity to which the captured reference is bound and not to the captured reference. [Note: The validity of such captures is determined by the lifetime of the object to which the reference refers, not by the lifetime of the reference itself. end note] [Example:

void f(const int*);
void g() {
  const int N = 10;
  [=] {
    int arr[N];     // OK: not an odr-use, refers to automatic variable
    f(&N);          // OK: causes N to be captured; &N points to
                    // the corresponding member of the closure type
  };
}
auto h(int &r) {
  return [&] {
    ++r;            // Valid after h returns if the lifetime of the
                    // object to which r is bound has not ended
  };
}

end example]

An entity is captured by reference if it is implicitly or explicitly captured but not captured by copy. It is unspecified whether additional unnamed non-static data members are declared in the closure type for entities captured by reference. If declared, such non-static data members shall be of literal type. [Example:

// The inner closure type must be a literal type regardless of how reference captures are represented.
static_assert([](int n) { return [&n] { return ++n; }(); }(3) == 4);

end example] A bit-field or a member of an anonymous union shall not be captured by reference.

If a lambda-expression m2 captures an entity and that entity is captured by an immediately enclosing lambda-expression m1, then m2's capture is transformed as follows:

[Example: The nested lambda expressions and invocations below will output 123234.

int a = 1, b = 1, c = 1;
auto m1 = [a, &b, &c]() mutable {
  auto m2 = [a, b, &c]() mutable {
    std::cout << a << b << c;
    a = 4; b = 4; c = 4;
  };
  a = 3; b = 3; c = 3;
  m2();
};
a = 2; b = 2; c = 2;
m1();
std::cout << a << b << c;

end example]

Every occurrence of decltype((x)) where x is a possibly parenthesized id-expression that names an entity of automatic storage duration is treated as if x were transformed into an access to a corresponding data member of the closure type that would have been declared if x were an odr-use of the denoted entity. [Example:

void f3() {
  float x, &r = x;
  [=] {                     // x and r are not captured (appearance in a decltype operand is not an odr-use)
    decltype(x) y1;         // y1 has type float
    decltype((x)) y2 = y1;  // y2 has type float const& because this lambda is not mutable and x is an lvalue
    decltype(r) r1 = y1;    // r1 has type float& (transformation not considered)
    decltype((r)) r2 = y2;  // r2 has type float const&
  };
}

end example]

When the lambda-expression is evaluated, the entities that are captured by copy are used to direct-initialize each corresponding non-static data member of the resulting closure object, and the non-static data members corresponding to the init-captures are initialized as indicated by the corresponding initializer (which may be copy- or direct-initialization). (For array members, the array elements are direct-initialized in increasing subscript order.) These initializations are performed in the (unspecified) order in which the non-static data members are declared. [Note: This ensures that the destructions will occur in the reverse order of the constructions. end note]

[Note: If a non-reference entity is implicitly or explicitly captured by reference, invoking the function call operator of the corresponding lambda-expression after the lifetime of the entity has ended is likely to result in undefined behavior. end note]

A simple-capture followed by an ellipsis is a pack expansion. An init-capture followed by an ellipsis is ill-formed. [Example:

template<class... Args>
void f(Args... args) {
  auto lm = [&, args...] { return g(args...); };
  lm();
}

end example]