Consider this simple (bad) function template for which lots of variations exist on this site:
template <typename R, typename... Args>
R call_with(std::function<R(Args...)> f,
Args... args)
{
return f(args...);
}
And two attempts at calling it:
call_with([]{}); // (a)
call_with<void>([]{}); // (b)
I cannot call (a)
because a lambda is not a std::function<R(Args...)>
so template deduction fails. Straightforward.
However, (b)
also fails. I suspect this is because the compiler cannot determine that I mean to provide all the type arguments and reasons that I am simply providing R
- so it is trying (and failing) to deduce Args...
for the same reason that the initial call failed.
Is there a way to explicitly specify that I am providing all the template arguments? To clarify, I am interested only in how to explicitly provide the template arguments so that there is no template deduction - I am not looking for the correct way to write call_with
or for a way to make template deduction succeed when called with a lambda.
You could specify the function type beforehand, like this:
int main(){
std::function<void()> f = []{};
call_with(f);
}
or, in a little more messy but more compact way:
int main(){
call_with(static_cast<std::function<void()>>([]{}));
}
This is because the compiler doesn't know what return type and arguments to deduce for your template parameters before you ask it to implicitly convert a lambda, which is an unspecified function object defined by the compiler, to a std::function
with those template parameters.
Really, you should just change your function warpper to be more generic:
template<typename Functor, typename ... Args>
auto wrapper(Functor &&f, Args &&... args) -> decltype(f(std::forward<Args>(args)...)){
return f(std::forward<Args>(args)...);
}
This should work for any function or functor type. It's also a really good example of the use of trailing return types.
Here's a live 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