具有以下3个重载

template <class T> auto foo() { return 1; }
template <class T> int  foo() { return 2; }
template <class T> T    foo() { return 3; }

下列疾病形成了吗?
static_cast<int(*)()>(&foo<int>)();

Clang选择重载#2,而gcc无法编译(Demo)

除去过载#1时,双方都同意选择过载#2(Demo)。

删除#2重载时,gcc选择#1重载,而clang编译失败(Demo)

最佳答案

根据[over.over]/2,我们执行模板参数推导。这对于所有三个重载都将成功:在第一个重载中,请记住[temp.deduct.funcaddr]/2:



由于推论将成功(假设所有模板参数均已明确提供参数),因此将返回类型推导为int。在第二种情况下,由于提供了参数,推导成功,而在第三种情况下,将推导T。 †

继续paragraph 4



根据[temp.deduct.partial]/3,功能模板的功能类型用于部分排序。我们可以立即看到,#1和#2的函数类型不包含任何参与推论的模板参数,因此,通过对核心问题[temp.deduct.partial]/4的分辨率引入的1391的添加,它们相应的P不会用于确定排序。 @bogdan解释here为什么该分辨率有问题;最重要的是,排序只会对#1和#2产生歧义。

即,根据当前(可能是有缺陷的)措辞,在所有情况下转换都是不正确的。如果部分非固定/推论参数的部分排序是固定的,

  • 的情况1和3是不明确的,因为对于两个非依赖性函数类型(#1和#2中的一个),没有排序对。
  • 在第2种情况下的接受行为是正确的(符合预期)。


  • [temp.deduct.type]/8元素9(T()),以防您感到好奇。

    10-04 22:54
    查看更多