C ++ lambda expressions - how does the compiler interpret them?

I'm just starting to learn new features in C ++ 11. I read about lambdas in C ++ Primer (Stanley Lippman) and experimented with them.

I tried the following code snippets:

auto func() -> int (*) (){ //int c=0; return []()-> int {return 0;}; } int main(){ auto p = func(); } 

This code is compiled. Therefore, I believe that lambdas without any captures are generated as normal functions by the compiler, and we can use a regular pointer to them.

Now I changed the code to use captures:

 auto func() -> int (*) (){ int c=0; return [=]()-> int {return c;}; } int main(){ auto p = func(); } 

But this could not be compiled. When using g ++, I got the following compilation error:

 main.cpp: In function 'int (* func())()': main.cpp:6:31: error: cannot convert 'func()::__lambda0' to 'int (*)()' in return return [=]()-> int {return c;}; 

From the error, I can understand that this is not a normal function that is generated, and perhaps this is a class with an overloaded call statement. Or is it something else?

My questions: How does the compiler handle lambdas internally? How should I go around lambdas that use captures, i.e. what should the func () return value be? I can’t think about a use case where I will need to use lambdas, but I just want to learn more about them. Please, help.

Thanks.

+7
c ++ lambda c ++ 11
source share
3 answers

All lambdas are function objects with a specific implementation type called a closure type, with a member of operator() . Each lambda expression has its own type of closure.

Lambdas without capture can be converted to a function pointer. Regardless of whether the compiler generates a normal function behind the scenes, the inner detail does not matter to you.

It is not possible to return the lambda defined inside the function. There are several things that prevent this β€” you don’t know the name of the lambda expression type, you cannot use the lambda expression inside decltype , and, as already mentioned, the two lambda expressions (even if they are lexically identical) are of different types.

What you can do is use std::function :

 std::function<int()> func() { int i = 0; return [=]()-> int {return i;}; } 

This method also works with grippers.

Or something like this:

 auto f = []{ return 0; }; auto func() -> decltype(f) { return f; } 

EDIT: The new C ++ 1y standard (more specifically, output of type return) will allow you to do this:

 auto func() { int i = 42; return [=]{ return i; }; } 
+8
source share

The compiler can decide how to generate the type of lambda function. It generates a function object, which means you can call it with () . But the type may be different in different situations. Each individual lambda can have a unique type. A simple lambda (doesn't capture anything) can be stored in a function pointer.

In C ++ 11, to wrap a lambda that captures data, you can use std::function :

 auto func() -> std::function<int()> { int c = 0; return [=]()-> int {return c;}; } 

In C ++ 14, it has a function return function , let the compiler process it:

 auto func() { int c = 0; return [=]()-> int {return c;}; } 
+2
source share

The function cannot return the lambda function itself. If you write:

 auto func() -> int () { int c=0; return [=]()-> int {return c;}; } 

The GCC then complains:

 lambda.cpp:3:21: error: function return type cannot be function auto func() -> int (){ 

So, the solution is to wrap the returned object in std::function :

 #include <functional> auto func() -> std::function<int ()> { int c=0; return [=]()-> int {return c;}; } int main(){ auto p = func(); } 
+2
source share

All Articles