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
}
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){ //.... }
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.
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.
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).
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With