The short answer to your question is the edited question: if you cannot change the declaration of call_with() , then either use the cast type demonstrated by @CoffeeandCode, or use the method described below to create a wrapper for call_with() .
The problem is that the compiler is trying to infer the template arguments from the first argument of the function. You can prevent this if you write your code like this :
#include <functional> #include <iostream> // identity is a useful meta-function to have around. // There is no std::identity, alas. template< typename T> struct identity { using type = T; }; template <typename R, typename... Args> R call_with( typename identity<std::function<R(Args...)>>::type f, Args... args) { return f(args...); } int main() { call_with<void>([](int){ std::cout << "called" << std::endl; }, 2); }
Using the template meta-function to βgenerateβ, the type std :: function means that the compiler cannot even try to infer the type of the function from the first argument, and it will only use other arguments.
You still need to explicitly specify the return type, but for other arguments you can now choose whether to explicitly specify them or leave it to the compiler to deduce them from the arguments given.
If you really want to ensure that all template arguments are provided and not output, you can also wrap the argument package when calling identity as follows:
template <typename R, typename... Args> R call_with( typename identity<std::function<R(Args...)>>::type f, typename identity<Args>::type... args)
In general, if you want the compiler not to output function template argument types that also appear as function parameters, wrap them in a meta function such as identity .
dhavenith
source share