Home > Blockchain >  function with default arguments as an argument
function with default arguments as an argument

Time:12-09

So, I know that you can pass a function as an argument like so:

int a(int x) {
    return x   1;
}

int b(int (*f)(int), int x) {
    return f(x); // returns x   1
}

I also know you can have a function with default arguments, like so:

int a(int x = 1) {
    return x;
}

a(2); // 2
a();  // 1

However, how do I pass a function with default arguments to a function and preserve this behavior?

I've tried the following:

int b(int (*f)(int), int x) {
    f(x); // works as expected
    f();  // doesn't work because there aren't enough arguments to f
}

and

int b(int (*f)()) {
    f();  // doesn't work because it cannot convert int (*)(int) to int (*)()
}

CodePudding user response:

There is no way to forward default parameter values with function pointers.

But you can make it work if you can turn b into a templated function:

By using a parameter pack for operator() and explicitly calling a we give the compiler the opportunity to apply the default argument values if needed:

int a(int x = 12) {
    return x   1;
}

template<class T>
int b(T f, int x) {
    return f()   f(x);
}

struct AFnWrapper {
    template<class... Args>
    auto operator()(Args&&... args) {
        return a(std::forward<Args>(args)...);
    }
};

int main() {
   std::cout << b(AFnWrapper{}, 1) << std::endl; // 15
}

A shorter version of this would be to just use a lambda:

std::cout << b([](auto&&... args) { return a(std::forward<decltype(args)>(args)...); }, 1) << std::endl;

If you don't need perfect forwarding you can make it even shorter:

std::cout << b([](auto... args) { return a(args...); }, 1) << std::endl;

godbolt example

CodePudding user response:

It's not possible to do this with function pointers, as function pointers don't have the ability to store information about default arguments. However, you can pass around a function object that happens to have a member function with default arguments.

Converting a to such an object is straightforward; just make it a lambda

auto a = [](int x = 1) {
    // ...
};

and then b can take a function object, where the type is deduced

template<typename F>
int b(F f, int x) {
    f(x);  // ok
    f();   // also ok, default value is 1
}

Here's a demo.

  • Related