为什么此模板参数推导/重载解析失败?

时间:2019-02-20 10:36:19

标签: c++ templates language-lawyer overload-resolution

此代码段无法在MSVCClangGcc中编译(它们给出不同的错误消息):

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之一,它将编译。

1 个答案:

答案 0 :(得分:10)

为简单起见,我们将第一个重载称为foo1,然后将第二个重载称为foo2

对于模板,问题在于无法根据[temp.deduct.call]/6推论外部foo的模板参数:

  

如果参数是包含一个或多个函数的重载集   模板,则将参数视为非推导上下文。

在没有模板的情况下,该程序会考虑foo1(foo1)foo1(foo2)foo2(foo1)foo2(foo2)的所有可能性,并根据{{ 3}}:

  

[注意::如果foo2(foo1)f()都是重载函数,则叉号   必须考虑可能性的乘积来解决g(),或者   等价表达式f(&g)。 — 尾注]