I just starter learning the new features in C++ 11. I was reading about lambdas in C++ Primer (Stanley Lippman) and was experimenting with them.
I tried the following pieces of code:
auto func() -> int (*) (){
//int c=0;
return []()-> int {return 0;};
}
int main(){
auto p = func();
}
This code compiled fine. So I guess lambdas without any captures are just generated as normal functions by the compiler and we can use a normal function 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 failed to compile. I got the following compilation error while using g++:
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 it is not a normal function that is generated and it might probably be a class with an overloaded call-operator. Or is it something else?
My questions : How does the compiler handle lambdas internally? How should I pass around lambdas that use captures i.e. what should be the return value from func()? I cant currently think of a use case where I would need to use lambdas like this but I just want to understand more about them. Please help.
Thanks.
All lambdas are function objects with implementation defined type called closure type with a operator()
member. Every lambda expression has it's own unique closure type, too.
Lambdas without a capture can be converted to a function pointer. Whether or not compiler generates a normal function behind the scenes is an internal detail and shouldn't matter to you.
It's not possible to return a lambda that's defined inside a function. There are few things that prevent this - you don't know the name of a type of lambda expression, you can't use a lambda expression inside a decltype
and as already said, two lambda expressions (even if lexically identical) have different types.
What you can do is use std::function
:
std::function<int()> func()
{
int i = 0;
return [=]()-> int {return i;};
}
This way works with captures, too.
Or something like this:
auto f = []{ return 0; };
auto func() -> decltype(f)
{
return f;
}
EDIT: The upcoming C++1y standard (more specifically, return type deduction), however, will allow you to do this:
auto func()
{
int i = 42;
return [=]{ return i; };
}
A function cannot return a lambda function itself. If you write:
auto func() -> int () {
int c=0;
return [=]()-> int {return c;};
}
Then GCC complains:
lambda.cpp:3:21: error: function return type cannot be function
auto func() -> int (){
So the solution is to wrap the return object into a std::function
:
#include <functional>
auto func() -> std::function<int ()> {
int c=0;
return [=]()-> int {return c;};
}
int main(){
auto p = func();
}
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