Overload resolution when passing in a function template to another function

123 views Asked by At

I have the following code :

template<typename T>
void bar(int x, T y)
{
}

void baz(int x, int y)
{
}

template<typename T0, typename T1>
void foo(void k(T0, T1), T1 t)
{
}

int main()
{
  foo(baz, 10); // OK
  foo(bar, 10); // ERROR
  return 0;
}

Overload resolution for foo works correctly when passing in baz. However, when passing in the function template bar, the compiler is unable to infer the template argument T0 of foo, even though there is only one bar in the scope, and its first argument is completely resolved to int. How do I write the function template foo such that calls like foo(bar, 10) can be resolved by the compiler?

2

There are 2 answers

2
Kerrek SB On

14.8.2.1/6 (Deducing template arguments from a function call) answers this:

When P is a function type, pointer to function type, or pointer to member function type:

  • If the argument is an overload set containing one or more function templates, the parameter is treated as a non-deduced context.

In your case, bar is a function template, and thus the argument k is of function type whose overload set contains function templates. Thus the template argument for bar<T> is not deducible.

As a practical reasons for this, consider that foo(bar<int>, 10) and foo(bar<long>, 10) are both entirely viable calls, and the choice will not be made for you implicitly. Remember that the type of an integer literal depends on the value, and it would be weird if foo(bar, 10) and foo(bar, 100000000) produced different template specializations.

0
curiousguy On

You can do:

  void (&b)(int,int) = bar;
  foo(b, 10);