I do not understand why does the line func<void, double>(f);
give me a compiling error
The compiler doesn't know that you want Params
to be exactly double
, it thinks maybe you want it to deduce a pack with more elements, such as double, int, void*, char
or double, double, double
or some other pack of types, and it doesn't know how to deduce that from the argument f
.
In theory there could be other specializations of std::function
which could be constructible from f
and which would allow the compiler to deduce a pack of more than one type for Params
(it can't know that isn't true without instantiating every possible specialization of std::function
and testing them, which is not feasible.
whereas if I cast the parameter f
to a std::function
(as in the non-commented line) it works.
Because now the compiler is able to deduce Params
correctly.
And the most puzzling issue is that, if I use a non-variadic version of func
[...] then the commented line in main works as desired. Any ideas why?
Because now the compiler knows that Params
is a single type, not a pack of zero or more types, so when you say func<void, double>
it knows Params
is double
, and not double, int, void*, char
or some other parameter pack.
Edit in answer to your comment, consider this:
template<typename T, typename U, typename V>
int func(T t, U u, V v)
{ return 0; }
int i = func<int, char>(1, '2', "three");
I've only given an explicit template argument for two of the parameters, so the third must still be deduced.
When you have a variadic template there could be any number of other parameters remaining to be deduced.