为什么此模板参数 deduction/overload 解析失败?

Why does this template argument deduction/overload resolution fail?

此代码片段无法在 MSVC, Clang and Gcc 中编译,(它们给出不同的错误消息):

int foo(int a, int b) {
    return a + b;
}

template <class Ret, class A, class B>
void foo(Ret (*)(A, B)) {

}

int main() {
    foo(foo);
    return 0;
}

这不应该编译吗?我不明白为什么它无法解析重载函数或推导模板参数。欢迎任何帮助,谢谢。

PS:如果模板被替换为 void foo(int (*)(int, int)),或者如果我们重命名 foo 之一以避免重载,它会编译。

为简单起见,我们调用第一个重载 foo1 并调用第二个重载 foo2

根据 [temp.deduct.call]/6:

,对于模板,问题是您无法推断出外部 foo 的模板参数

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

没有模板,程序会考虑所有可能性 foo1(foo1)foo1(foo2)foo2(foo1)foo2(foo2) 并选择唯一可行的 foo2(foo1),根据[over.over]/6:

[ Note: If f() and g() are both overloaded functions, the cross product of possibilities must be considered to resolve f(&g), or the equivalent expression f(g). — end note ]