ronag
ronag

Reputation: 51255

capture member variable by value

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
}

Upvotes: 9

Views: 5759

Answers (5)

c4augustus
c4augustus

Reputation: 306

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.

Upvotes: 1

Jakob Schou Jensen
Jakob Schou Jensen

Reputation: 229

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).

Upvotes: 4

rkjnsn
rkjnsn

Reputation: 985

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.

Upvotes: 5

Sarfaraz Nawaz
Sarfaraz Nawaz

Reputation: 361302

Right now, I faced the same problem and solved it myself:

  1. Capture the this pointer.
  2. then write this->member syntax inside the lambda:

That is,

 std::async([this]{ std::cout << this->my_member_; } ); 
 //          ^^^^                ^^^^^^ use this syntax
 //           | 
 //           ^
 //           capture `this` as well

It works for me. I hope it should work for you too. However, I'm not completely satisfied with this knowledge. After my work, I'll look for the reason why this syntax is required, or it is a compiler bug. I'm using GCC 4.5.0 (MinGW).

Well, I found the following topic which says this pointer should be captured in order to use the member of the class.

Upvotes: -1

Motti
Motti

Reputation: 114695

I don't think you can capture a member by value, you can capture this but since the member is part of this you'll be using a shared member and not a new variable.

Not knowing what type your member is something like this should work:

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

I don't understand why you're using a shared_ptr in your example, if you want to capture by value surely shared_ptr is the last thing you should consider.

Upvotes: 7

Related Questions