Search code examples
c++templatesc++14template-argument-deduction

C++ template deduction is not working


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.


Solution

  • Your function expects an argument of type std::function, but you're passing it a pointer to function instead. &g<int> is convertible to the std::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 an std::function, so template argument deduction will succeed.

    f<int>(&g<int>) also works because you've now explicitly specified T, it no longer participates in template argument deduction and user defined conversions will be attempted.