Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

capture by value class members

Is there a way, when writing a lambda function within a member function, to capture fields of the enclosing class by value? The default catch-all = doesn't work because when I reference the variable inside the lambda I get instead a dereferencing from the captured this pointer, as well as explicitly naming the variable in the capture list, because I get two compile error: capture of non-variable <name>, and ‘this’ was not captured for this lambda function

like image 392
Lorenzo Pistone Avatar asked Oct 17 '12 21:10

Lorenzo Pistone


People also ask

How to capture member variable in lambda c++?

To capture the member variables inside lambda function, capture the “this” pointer by value i.e. std::for_each(vec. begin(), vec. end(), [this](int element){ //.... }

What is Lambda capture in C++?

A capture clause of lambda definition is used to specify which variables are captured and whether they are captured by reference or by value. An empty capture closure [ ], indicates that no variables are used by lambda which means it can only access variables that are local to it.


2 Answers

No, data members cannot be captured by value. A lambda can capture only two kinds of things:

  1. the this pointer, and
  2. nonstatic local variables (that is, variables with automatic storage duration).

As has been noted by ildjarn in the comments, you can create a local variable with a copy of the value of the data member, and capture that local variable by value.

I would argue that if explicit by-value capture of a data member was allowed, it could prove confusing, since the behavior of explicit capture would differ from that of implicit capture. For example, given an accessible data member of type int named m, it would be odd that the following would produce different results:

[=] () mutable { m = 1; } // we modify this->m
[=m]() mutable { m = 1; } // we modify the copy of m that was captured
like image 91
James McNellis Avatar answered Oct 03 '22 07:10

James McNellis


Yes, simply write the [<new name>=<your class field>] construct. For instance:

class MyClass {
    int a;
    void foo() {
        auto my_lambda = [a_by_val=a] {
            // do something with a_by_val
        }

        my_lambda();
    }
}
like image 27
Vlad Zolotarov Avatar answered Oct 03 '22 09:10

Vlad Zolotarov