Weird substitution failure with C++11 variadic template
c++11, variadic-templates
Solution
First: You can specify less arguments than what you use and let the compiler deduce the rest:
template <typename ...Params>
void func1(Params... params);
func1<int, int>(1, 2, 3); // calls func1<int, int, int>
This means `Params` is still open for adding extra types when you call it. But if you take the function address, it becomes defined and closed:
auto x = func1<int, int>;
x(1, 2, 3); // not possible
When you call your `call1` function directly:
template <typename... Params>
void call1(Params... params, std::function<bool(Params...)> func);
call1<int, int, int>(1, 2, 3, f);
call1<int>(1, 2, 3, f); // same as before
call1(1, 2, 3, f); // same as before
The compiler is able to deduce that you have exactly 3 ints because you just sent him 3 ints. This way the last parameter must be `std::function<bool(int, int, int)>` because we fully deduced what `Params...` means and there's no space for more types.
Now the problematic case:
template <typename... Params>
void call2(std::function<bool(Params...)> func);
call2<int, int, int>(f);
Here you informed the compiler that the first 3 elements of `Params` are all ints. `Params = {int, int, int, ...}`. Note that it is still open for adding something else if deduction tells so. Replacing we have: `std::function<bool(int, int, int, ...)> func`. The compiler can't possibly know what this incomplete type means unless you explicitly pass a `std:function` (exact match). It doesn't know yet it can have a constructor taking the function pointer you provided, so there's a mismatch. Now the compiler does not have enough data to decide if it need more types into `Params` or not. Failure.
But note this interesting case:
auto x = call2<int, int, int>;
x(f); // x is exactly void(*)(std::function<bool(int, int, int)>). No doubts.
Here the you force `Params` to be complete. There's no deduction to evaluate. Although ugly, this also works:
(&call2<int, int, int>)(f);
Problem
I'm having a hard time figuring out what causes the substitution failure in this example code: ``` bool f(int a, int b, float c) { printf("%d %d %f", a, b, c); return true; } template <typename ...Params> void call1(Params... params, std::function<bool(Params...)> func) { func(params...); } template <typename ...Params> void call2(std::function<bool(Params...)> func) { } ``` Somewhere in main: ``` call1<int, int, float>(3, 4, 5.5, f); // Ok. call2<int, int, float>(f); // Substitution failure. ``` The compiler says: ``` template argument deduction/substitution failed: mismatched types 'std::function<bool(Params ...)>' and 'bool (*)(int, int, float)' call2<int, int, float>(f); ^ ``` What baffles me is that call1 works while call2 doesn't. Any tips? =)