There is a function
template <class ...T>
void foo(std::function<void(T...)> callback);
into which I pass a callback.
I'd like to do something like
foo(bar);
where bar is, for example,
void bar(int a, long b, double c, float d);
but that gives me
error: no matching function for call to bar(void (&)(int, long int, double, float))
I have to call foo as
foo(std::function<void(int, long, double, float)>(bar));
which is too verbose. Even
foo<int, long, double, float>(bar);
would have been better.
foo(bar);
would be just ideal.
Anyway, how can I make calls to foo to be less verbose?
Edit: declaration of foo has to stay the same.
I'd write a wrapper function that translates the function pointer into a std::function wrapper:
template <typename... T>
void foo(std::function<void (T...)> f) {}
template <typename... T>
void foo(void (*f)(T...)) {
foo(std::function<void (T...)>(f));
}
foo() can then be called either way:
void bar(int,double) {}
void foo_caller() {
foo(std::function<void (int,double)>(bar));
foo(bar);
}
Addendum: Non-static member function wrapper
Same approach can be used for pointer-to-member functions — just add another overload:
template <typename C,typename... T>
void foo(void (C::*f)(T...)) {
foo(std::function<void (C *,T...)>(f));
}
Note the extra first parameter for the this pointer for the member function. Usage is similar:
struct quux {
void mf(char *,double) {}
};
void foo_caller() {
foo(&quux::mf);
}
If you know you will pass a plain function pointer to foo, and not just any C++11 lambda, you can redefine foo as:
template <class ...T>
void foo(void(*callback)(T...)) {
// .....
}
If you want to support lambdas, you can be more generic with the type
template <class LambdaType>
void foo(LambdaType callback) {
// .....
}
the downside of this approach is that if you pass something that is not a function or lambda, you will get weird template error messages coming from inside of foo.
With your original solution the compiler has problems matching T... to int, long, double, float, probably because it is a nested type.
If I told you to match void(int, double) to MyTempalte<T...> you wouldn't know that I intend to replace T... with int, double, because you don't know what MyTemplate does with its arguments. Maybe MyTemplate is doing something weird to its template arguments first?
Same, the compiler doesn't know how to match std::function template parameters to your function pointer.
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