Jar*_*d42 9 c++ templates overloading language-lawyer c++14
随着3次超载
template <class T> auto foo() { return 1; }
template <class T> int foo() { return 2; }
template <class T> T foo() { return 3; }
Run Code Online (Sandbox Code Playgroud)
以下是不良形成的?
static_cast<int(*)()>(&foo<int>)();
Run Code Online (Sandbox Code Playgroud)
Clang选择重载#2,而gcc无法编译(Demo)
当删除过载#1时,两者都同意选择过载#2(演示).
当删除重载#2时,gcc选择重载#1并且clang无法编译(Demo)
根据[over.over]/2,我们执行模板参数推导.这将成功实现所有三个重载:在第一个重载中,记住[temp.deduct.funcaddr]/2:
函数模板的返回类型中的占位符类型(7.1.7.4)是非推导的上下文.如果模板参数推导对于这样的函数成功,则返回类型是从函数体的实例化确定的.
由于推导将成功(假设所有模板参数都显式提供了参数),则返回类型推导为int.在第二种情况下,从提供参数开始,推论成功,在第三种情况下,将推T导出推论.†
继续第4段,
如果选择了多个函数,
F1则如果集合包含第二个函数模板特化,则消除任何给定的函数模板特化,其功能模板比F1根据14.5.6.2的部分排序规则的函数模板更专业化.在这种消除之后,如果有的话,应该保留一个选定的功能.
根据[temp.deduct.partial]/3,函数模板的函数类型用于部分排序.我们可以立即看到#1和#2的函数类型不包含任何参与演绎的模板参数,因此通过核心问题1391分辨率引入的[temp.deduct.partial]/4的加法,它们的对应s是不习惯确定订货.@bogdan 在这里解释了为什么这个解决方案有问题; 最重要的是,排序只会产生#1和#2的歧义.P
也就是说,根据当前(可能是有缺陷的)措辞,转换在所有情况下都是错误的.如果对非依赖/推导参数对修正了部分排序,
† [temp.deduct.type]/8 element 9(T()),以防您好奇.