Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Lambda Captures C++14

Tags:

c++

lambda

c++14

I've encountered a notation like:

int x = 4;
auto y = [&r = x, x = x+1]()->int { 
    r += 2;
    return x+2;
}();

Can you explain this statement? I was a user of C++03 and recently upgraded to C++11. From today I starts C++14 and encountered this snippet.

Thanks!

like image 976
Kaidul Avatar asked Aug 20 '14 15:08

Kaidul


People also ask

What are captures in lambda 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.

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.

What does it mean to lambda capture this?

The lambda is capturing an outside variable. A lambda is a syntax for creating a class. Capturing a variable means that variable is passed to the constructor for that class. A lambda can specify whether it's passed by reference or by value.

Are lambdas objects C++?

A lambda is an object (hence why we're referring to it as a functor, rather than a function) so has a type and can be stored. However, the type of the lambda is only known by the compiler (since it is compiler-generated), so you must use auto for declaration instances of the lambda.


2 Answers

Thanks @chris for the wikipedia reference. What I found is -

Here is nice explanation who don't know about the old lambda Captures of C++11

In C++14:


C++11 lambda functions capture variables declared in their outer scope by value-copy or by reference. This means that value members of a lambda cannot be move-only types. C++14 allows captured members to be initialized with arbitrary expressions. This allows both capture by value-move and declaring arbitrary members of the lambda, without having a correspondingly named variable in an outer scope.

This is done via the use of an initializer expression:

auto lambda = [value = 1] {return value;};

The lambda function lambda will return 1, which is what value was initialized with. The declared capture deduces the type from the initializer expression as if by auto.

This can be used to capture by move, via the use of the standard std::move function:

std::unique_ptr<int> ptr(new int(10));
auto lambda = [value = std::move(ptr)] {return *value;};

So the above expression updates x to 6, and initializes y to 7.

like image 180
Kaidul Avatar answered Sep 26 '22 00:09

Kaidul


This example is part of C++14 feature "Lambda capture Initializers", This allows creating lambda captures initialized with arbitrary expressions. Using this reference-captures can have different names than the referenced variable.

If you run your code :

int x = 4;
auto y = [&r = x, x = x+1]()->int { 
    r += 2; //r=6
    return x+2;//5+2
};
cout<<y()<<endl; // this will print 7
like image 36
Ramanand Yadav Avatar answered Sep 26 '22 00:09

Ramanand Yadav