以下代码传递断言:
int foo() { return 1; }
template<typename T>
int foo() { return 2; }
int main() {
assert( 1 == foo() );
assert( 2 == foo<int>() );
return 0;
}
但据我了解,根据C ++ 11标准的13.3.3 / 1段:
[...]给出这些定义,如果对所有参数
F1
,{{1}而言,可行函数F2
被定义为比另一个可行函数i
更好的函数}的转换顺序并不比ICSi(F1)
差,然后[...]ICSi(F2)
是非模板函数,而F1
是函数模板专门化[...] >
不应该这样,因为签名最终是相同的。那么,为什么在调用F2
时没有歧义?我想念什么?
答案 0 :(得分:5)
您引用的文本比较密集;您必须仔细阅读。 “如果对于所有自变量i
来说,F1优于F2,则ICSi(F1)的转换顺序不比ICSi(F2)差” –在这里是对的,因为两个转换序列相同,因此,比另一个更差。因此,现在转到最后一部分:“ 然后,F1是非模板函数,而F2是函数模板专业化”。没错,因此F1比F2更好。规则说,foo()
和foo<int>()
分别用F1和F2代替,foo()
比foo<int>()
更好。
糟糕,我回答了错误的问题。正如评论所指出的那样,问题是,为什么显式调用foo<int>()
不能解析为foo()
?答案是,foo<int>()
是对显式模板实例化的调用,而不是对重载函数的调用。考虑:
template <class Ty>
void f(Ty) { }
void f(int);
void g(int);
f(3.14); // calls f<double> (overloaded function call)
f(1); // calls f(int) (overloaded function call)
f<int>(3.14); // calls f<int> (explicit call of template instantiation)
g(3.14); // calls g(int)
在此示例中,f<int>
是模板专门化的名称。它不是不是名为f
的常规函数,因此不需要像调用g(3.14)
那样考虑重载。