wcochran
wcochran

Reputation: 10896

C++11 lambda capture `this` and capture local variables by value

The lambda function below captures this (so bar() can access its instance vars) and the local variables a,b,c.

class Foo {
  int x, y, z;
  std::function<void(void)> _func;
  // ...
  void bar() {
     int a,b,c;
     // ...
     _func = [this,a,b,c]() { // lambda func
        int u = this->x + a;
        // ...
     };
  }
};

But if I want to capture many instance variables and wish to avoid explicitly naming them in the capture list, I do not seem to be able to do this:

     _func = [this,=]() { // lambda func
        // ...
     };

I get a compiler error at the = following this,:

  error: expected variable name or 'this' in lambda capture list 

If I try this

     _func = [=,this]() { // lambda func
        // ...
     };

I get

  error: 'this' cannot be explicitly captured when the capture default is '='

Is there a shorthand for capturing this and everything else by value?

UPDATE: [=, this] as a lambda capture is a new feature of C++20

Upvotes: 10

Views: 22374

Answers (4)

JeJo
JeJo

Reputation: 32722

[=] will work, because it captures all automatic variables used in the body of the lambda by copy.

Here is the example output: https://www.ideone.com/kkXvJT

#include <iostream>
#include <functional>

class Foo
{
  int x, y, z;
  std::function<void(void)> _func;

public:
  Foo(int a): x(a), y(0), z(0)  {}

  void bar()
  {
    int a = 1,b,c;
    _func = [=]()
    {
      int u = this->x + a;
      std::cout << u << std::endl;
    };

    _func(); // lambda call
  }
};

int main()
{
  Foo obj(1);
  obj.bar();
}

Upvotes: 2

Yakk - Adam Nevraumont
Yakk - Adam Nevraumont

Reputation: 275330

[=] does what you want -- it captures anything not a member variable by value, and *this by reference (or this by value).

[*this,=] captures both local variables and the object by value in .

[&] captures local variables by reference and *this by reference or this (the pointer) by value.

Both default capture modes capture this the same way. Only in can you change that.

Upvotes: 6

N00byEdge
N00byEdge

Reputation: 1136

[=] already captures this by value. Take a look at the following code live here: http://cpp.sh/87iw6

#include <iostream>
#include <string>

struct A {
    std::string text;

    auto printer() {
        return [=]() {
            std::cout << this->text << "\n";
        };
    }
};

int main() {
    A a;
    auto printer = a.printer();
    a.text = "Hello, world!";

    printer();
}

Upvotes: 3

bipll
bipll

Reputation: 11940

As cppreference says:

[=] captures all automatic variables used in the body of the lambda by copy and current object by reference if exists

Upvotes: 9

Related Questions