I have the following code:
#include <iostream>
#include <functional>
template<typename Return, typename... Params>
void func(std::function<Return(Params... )> x) {}
void f(double) {}
int main() {
//func<void, double>(f); // compile error here in the variadic case
func(std::function<void(double)>(f));
}
I have 2 questions:
1.
I do not understand why does the line func<void, double>(f);
give me a compiling error
/Users/vlad/minimal.cpp:10:5: error: no matching function for call to 'func'
func<void, double>(f); // compile error here in the variadic case
^~~~~~~~~~~~~~~~~~
/Users/vlad/minimal.cpp:5:6: note: candidate template ignored: could not match 'function<void (double, type-parameter-0-1...)>' against 'void (*)(double)'
void func(std::function<Return(Params... )> x) {}
^
1 error generated.
whereas if I cast the parameter f
to a std::function
(as in the non-commented line) it works.
2.
And the most puzzling issue is that, if I use a non-variadic version of func
(i.e. just replace typename...
by typename
so in effect func
takes a std::function<Return(Params)>
as parameter), then the commented line in main
works as desired. Any ideas why?
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 astd::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.
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