Search code examples
c++functionpointerslambdacapture

Why cpp std::function can hold capture-lambda, while function pointer cannot?


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?


Solution

  • 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.