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 (*)()
}
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With