当涉及重载函数作为参数时,模板参数推导如何工作?

How does template argument deduction work when an overloaded function is involved as an argument?

这是

中提到的更复杂的问题

下面的代码 compiles without any problem:

void foo() {}
void foo(int) {}
void foo(double) {}
void foo(int, double) {}

// Uncommenting below line break compilation
//template<class T> void foo(T) {}

template<class X, class Y> void bar(void (*f)(X, Y))
{
    f(X(), Y());
}

int main()
{
    bar(foo);
}

模板参数推导似乎不是一项具有挑战性的任务 - 只有一个函数 foo() 接受两个参数。但是,取消注释 foo() 的模板重载(它仍然只有一个参数)会无缘无故地中断编译。 gcc 5.x/6.x 和 clang 3.9.

编译均失败

是否可以通过重载resolution/template参数推导的规则来解释,或者它应该被定义为那些编译器的缺陷?

如您的链接问题的答案所述:

[temp.deduct.call]/6: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.

由于重载集包含函数模板,参数被视为非推导上下文。这会导致模板参数推导失败:

[temp.deduct.type]/4: [...]If a template parameter is used only in non-deduced contexts and is not explicitly specified, template argument deduction fails.

这个失败的推论给了你你的错误。请注意,如果您显式指定参数,代码将成功编译:

bar<int,double>(foo);

Live demo