Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Parentheses at the end of a C++11 lambda expression

I am confused with some of the examples that I have come across with C++11 lambdas. For eg:

#include <iostream>
#include <string>

using namespace std;

int main()
{ 
        cout << []()->string{return "Hello World 1!";}() << endl;

        []{cout << "Hello World 2!" << endl;}();

        string result = [](const string& str)->string {return "Hello World " + str;}("2!");
        cout << "Result: " << result << endl;

        result = [](const string& str){return "Hello World " + str;}("3!");
        cout << "Result: " << result << endl;

        string s;
        [&s](){s = "Hello World 4!";};   // does not work
        cout << s << endl; 
        [&s](){s = "Hello World 4!";}(); // works!
        cout << s << endl;

        return 0;
}

I am unable to figure out what the parentheses at the end are doing. Are they instantiating, as a constructor, a lambda? Given that the template for a lambda is:

[capture_block](parameters) mutable exception_specification -> return_type {body}

it baffles me that those parentheses are required for those instances to work. Can someone explain what they are why they are required?

like image 499
Quiescent Avatar asked Sep 30 '12 16:09

Quiescent


People also ask

What is the correct syntax for lambda expression in C++11?

Creating a Lambda Expression in C++auto greet = []() { // lambda function body }; Here, [] is called the lambda introducer which denotes the start of the lambda expression. () is called the parameter list which is similar to the () operator of a normal function.

Can a lambda closure be used to create a C++11 thread?

Can you create a C++11 thread with a lambda closure that takes a bunch of arguments? Yes – just like the previous case, you can pass the arguments needed by the lambda closure to the thread constructor.

Does C have lambda expression?

No, C has no support for lambda expressions.

What is a lambda closure C++?

c++17 intermediate Lambdas, also known as closures, are unnamed function objects in C++. Unnamed means we cannot know or name their type . Because their type is unknown to us lambdas can only ever be stored in an auto variable on the stack.


2 Answers

Well, given that a lambda expression is basically an anonymous function, the parentheses at the end do nothing more than just call this function. So

result = [](const string& str){return "Hello World " + str;}("3!");

is just equivalent to

auto lambda = [](const string& str){return "Hello World " + str;};
string result = lambda("3!");

This holds in the same way for a lambda with no arguments, like in

cout << []()->string{return "Hello World 1!";}() << endl;

which would otherwise (if not called) try to output a lambda expression, which in itself doesn't work. By calling it it just puts out the resulting std::string.

like image 132
Christian Rau Avatar answered Sep 18 '22 23:09

Christian Rau


They're calling the function object!

In two phases:

auto l = []()->string{return "Hello World 1!";}; // make a named object
l(); // call it

A lambda expression evaluates to a function object. Since there's no operator<< overload that takes such a function object, you'd get an error if you didn't call it to produce a std::string.

like image 33
Xeo Avatar answered Sep 20 '22 23:09

Xeo