Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

capture member variable by value

Tags:

c++

c++11

lambda

How would I catch a member variable by value when using C++11 lambda expressions?

Using the [my_member] syntax doesn't seem to work, and implicit capture uses the this pointer. What is need is a way to explicitly specify capture type of member variables. Is that possible?

My workaround for now is:

void member_function()
{
    std::shared_ptr<my_member_class> my_member_copy = my_member; // this shouldn't be necessary
    std::async([=]{ std::cout << *my_member_copy; });
    // std::async([=]{ std::cout << *my_member_; }); // wrong, my member could be potentially out of scope
}
like image 606
ronag Avatar asked Sep 15 '10 13:09

ronag


People also ask

How do you capture a member variable?

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){ //.... }

How do you capture a variable in lambda C++?

Much like functions can change the value of arguments passed by reference, we can also capture variables by reference to allow our lambda to affect the value of the argument. To capture a variable by reference, we prepend an ampersand ( & ) to the variable name in the capture.

How do you capture variables in lambda?

Capture clause A lambda can introduce new variables in its body (in C++14), and it can also access, or capture, variables from the surrounding scope. A lambda begins with the capture clause. It specifies which variables are captured, and whether the capture is by value or by reference.


3 Answers

Since your question is about C++11 this is not really an answer, but in C++14 you can do like this:

void member_function()
{
    std::async([my_member=my_member]{ std::cout << *my_member; });
}

It does the same thing as your own "work-around" (if my_member is a shared_ptr).

like image 197
Jakob Schou Jensen Avatar answered Sep 18 '22 09:09

Jakob Schou Jensen


Unfortunately, I don't think there is a straight-forward way to do this, but I can think of a couple of ways to capture a member without making an extra copy.

The first option is similar to your example but uses a reference for the local variable:

void member_function()
{
   std::shared_ptr<my_member_class> &my_member_ref = my_member;
   // Copied by the lambda capture
   std::async([my_member_ref]{ std::cout << *my_member_ref; });
}

Note that there is a bug in pre 4.6.2 versions of GCC that cause the value not to be copied. See Capturing reference variable by copy in C++0x lambda.

A second approach would be to use bind to make the copy:

void member_function()
{
   // Copied by std::bind
   std::async(std::bind([](const shared_ptr<my_member_class>& my_member){
      std::cout << *my_member; }, my_member));
}

In this example, bind will make its own copy of my_member, and this copy will then be passed to the lambda expression by reference.

like image 30
rkjnsn Avatar answered Sep 18 '22 09:09

rkjnsn


auto& copy = my_member;
std::async([copy]{ std::cout << copy; });

auto& (above) also works and obviates copying twice. Although this approach is more syntax than passing [this], it obviates passing into the closure a dependency on the object [this] points to.

like image 33
c4augustus Avatar answered Sep 21 '22 09:09

c4augustus