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