Search code examples
c++lambdafunction-pointersstd-functiondefault-parameters

Possible to copy std::function containing lambda with default parameters?


Is there any way to recover type information from a lambda with default parameters stored in a std::function that does not have those parameters in its type?

std::function<void()> f1 = [](int i = 0){};
std::function<void(int)> f2 = [](int i = 0){};
std::function<void(int)> f3 = f1;  // error
std::function<void()> f4 = f2;     // error

Looking at std::function's copy constructor, there is no partial template specialization for other function types, so I'd imagine this information is lost and it is just a case that you can't assign a function of one type to a function of another type, even if internally they can both call the function. Is this correct? Are there any work-arounds to achieve this? I'm looking at std::function::target, but haven't had any luck, I'm no expert on function types and pointers.

On a side note, how does f1(or the lambda) bind the default parameter?


Solution

  • No, that is not possible, because default arguments are a property of a set of a function's declarations, not of the function itself. In other words, this is perfectly legal C++:

    A.cpp

    int f(int i = 42);
    
    const int j = f(); // will call f(42)
    

    B.cpp

    int f(int i = 314);
    
    const int k = f(); // will call f(314)
    

    F.cpp

    int f(int i = 0)
    {
      return i;
    }
    
    const int x = f(); // will call f(0)
    

    These can all be linked together just fine.

    Which means it's not possible to somehow "retrieve" a default argument from a function.

    You can do the equivalent of f4 = f2 using std::bind and providing your own default argument, like this:

    std::function<void()> f4 = std::bind(f2, 42);
    

    [Live example]

    However, there is no way to get something equivalent to f3 = f1.