For the following code:
#include<functional>
template<typename T>
void f(std::function<void(T)> g) {
}
template<typename T>
void g(T x) {
}
int main() {
f(&g<int>);
}
C++14 compiler produces the error:
no matching function for call to 'f(<unresolved overloaded function type>)'
f(&g<int>);
I am curious why is template argument deduction not working here.
It seems that, given that the argument of g is of type int, we can deduce that the argument of f is of type std::function<void(int)>
, and, therefore T = int
in f. Why does this not happen? I am interested in the relevant section of the C++ standard which explains this. Does T occur in a non-deduced context here?
The following similar code compiles:
#include<vector>
template<typename T>
void f(std::vector<T> vec) {
}
int main() {
f(std::vector<int>{});
}
So it's not the angle brackets which create a non-deduced context.
Your function expects an argument of type
std::function
, but you're passing it a pointer to function instead.&g<int>
is convertible to thestd::function
parameter type, but template argument deduction requires exact matches (except for the adjustments allowed by [temp.deduct.call]/2,3,4), user defined conversions are not considered.Writing
f(std::function<void(int)>(g<int>))
will work because you're now passing anstd::function
, so template argument deduction will succeed.f<int>(&g<int>)
also works because you've now explicitly specifiedT
, it no longer participates in template argument deduction and user defined conversions will be attempted.