I've got this code snippet:
int x = 3;
auto fauto = [=](){ cout<<'x'; };
function<void()> func{fauto};
func();
void (*rawPf)() = fauto; // fail to compile
rawPf();
I knew the syntax that only non-capture lambda can be assigned to function pointer. But:
(1) Why std::function can hold capture-lambda?
(2) as both std::function and function pointers are callable
, what's the core difference that makes std::function able to hold capture-lambda, while function pointer cannot?
Any detailed explanation on language design for this?
CodePudding user response:
Why can a function pointer not hold a lambda with a capture : because a Lambda is NOT a function ,it's an object!
Why can a lambda without a capture be converted to a function pointer ?
A Lambda is just an ordinairy object (a piece of data) of a compiler generated class (with a unique classname that only the compiler knows) with a function-operator member (i.e. auto operator() ( ??? )) that the compiler defines for you with the parameter definitions (if any) you provide. The data-members of a lambda-object are defined by the capture-list and/or usage of variables of its enclosing scope.
All non-static member functions when called on an object get a implicit hidden argument called this. This is also the case when you 'call' the lambda.
Now ,when you don't capture something ,the lambda has no data (empty class) and the compiler doesn't have to generate an implicit this pointer for the call ,which makes the function operator just like an ordinairy function and the compiler can convert it to function pointer. So it not the lambda that is converted to a function-pointer ,it's the lambda's function-operator that is converted.
Why can std::function hold both : because it's a template and with templates and specializations you can do almost anything.
CodePudding user response:
There's no reason not to implement it in std::function<>
, so it's implemented.
The reason a function pointer cannot hold a capture lambda is that the latter has a this
pointer and there's no place to store that in the function pointer (well, unless you compile new code or assign it from a pool). However, std::function<>
can allocate arbitrary amount of space, amongst these, the this
pointer.
You can understand this better if you try to implement a function returning function pointers for lambdas (which, when called, by specification should call the lambda).