Почему лямбда, определенная в методе, не может захватить переменную-член?

Рассмотрим следующий код:

class Object
{
public:
    void method();
private:
    bool field;
};

void Object::method()
{
    auto lambda = [&field]()
    {
        // ....
    };
}

Подскажите, пожалуйста, почему компилятор запрещает захватывать поле field?


Ответы (2 шт):

Автор решения: Harry

Захватывайте this. Все же field - не локальная переменная для method.

class Object
{
public:
    void method();
private:
    bool field;
};

void Object::method()
{
    auto lambda = [this]()
    {
        this->field = !this->field;
    };
    cout << field << endl;
    lambda();
    cout << field << endl;
}

int main(int argc, const char * argv[])
{
    Object obj;
    obj.method();
}

Впрочем, не помню точно, с какой версии (14? 17?), но вполне допустим и такой вариант:

void Object::method()
{
    auto lambda = [&f = this->field]()  // И даже [&f = field]
    {
        f = !f;
    };
    cout << field << endl;
    lambda();
    cout << field << endl;
}
→ Ссылка
Автор решения: ampawd

Это по дизайну так - члены класса явно не могут захватываться без инициализатора, только переменные могут.

Почитайте о capture list

Class members cannot be captured explicitly by a capture without initializer (as mentioned above, only variables are permitted in the capture list):

class S {
  int x = 0;
  void f() {
    int i = 0;
//  auto l1 = [i, x]{ use(i, x); };    // error: x is not a variable
    auto l2 = [i, x=x]{ use(i, x); };  // OK, copy capture
    i = 1; x = 1; l2(); // calls use(0,0)
    auto l3 = [i, &x=x]{ use(i, x); }; // OK, reference capture
    i = 2; x = 2; l3(); // calls use(1,2)
  }
}

А связано это скорее всего с тем, что объекты из внешних для лямбды пространств имен, коим является field объявленный в пространстве имен класса Object не должны быть видны лямбде напрямую, в то время как this неявно передающийся каждому члену фукнции в качестве параметра содержится в пространстве имён (в Object::method) в котором создана лямбда, поэтому его можно захватывать.

→ Ссылка