How to call a function with default parameter through a pointer to function that is the return of another function?

Defaulted arguments are a bit of C++ syntactic sugar; when calling the function directly with insufficient arguments, the compiler inserts the default as if the caller had passed it explicitly, so the function is still called with the full complement of arguments (Mult(4) is compiled into the same code as Mult(4, 2) in this case).

The default isn't actually part of the function type though, so you can't use the default for an indirect call; the syntactic sugar breaks down there, since as soon as you are calling through a pointer, the information about the defaults is lost.


For the "why not" I refer you to this answer. If you want to somehow keep the ability to use a default, you need to provide something more than a function pointer, eg a lamdba will do:

auto Double() {
    return [](int x,int y=2){ return Mult(x,y); };
}

And by using a variadic lambda (thanks to @Artyer) you do not even have to repeat the default value:

#include <iostream>

int Mult(int x, int y = 2) { // y is default
    return x * y;
}

auto Double() {
    return [](auto... args) { return Mult(args...); };
}

int main(int argc, char* argv[]){    
    auto func = Double();
    std::cout << func(7, 4) << '\n'; // ok
    std::cout << func(7) << '\n';    // ok
    std::cout << Mult(4) << '\n';    // ok
}

Live demo


If you always have 2 as default argument, you can wrap your function pointer into a simple helper class like this:

using pFn_ = int(*)(int, int);

class pFn
{
    pFn_ ptr;
public:
    pFn(pFn_ p) : ptr(p) {}
    int operator()(int x, int y = 2) const {
        return ptr(x,y);
    }
};

Full working example: https://godbolt.org/z/5r7tZ8