C++ 为什么在选择具有相同签名的模板函数和非模板函数时没有歧义?
以下代码传递断言:C++ 为什么在选择具有相同签名的模板函数和非模板函数时没有歧义?,c++,templates,language-lawyer,C++,Templates,Language Lawyer,以下代码传递断言: int foo() { return 1; } template<typename T> int foo() { return 2; } int main() { assert( 1 == foo() ); assert( 2 == foo<int>() ); return 0; } intfoo(){return 1;} 模板 int foo(){return 2;} int main(){ 断言(1==foo()); 断言(2==
int foo() { return 1; }
template<typename T>
int foo() { return 2; }
int main() {
assert( 1 == foo() );
assert( 2 == foo<int>() );
return 0;
}
intfoo(){return 1;}
模板
int foo(){return 2;}
int main(){
断言(1==foo());
断言(2==foo());
返回0;
}
但据我所知,根据C++11标准第13.3.3/1段:
[…]根据这些定义,一个可行函数F1
被定义为比另一个可行函数F2
更好的函数,如果对于所有参数i
,ICSi(F1)
不是比ICSi(F2)
更糟糕的转换序列,那么[…]F1
是非模板函数,F2
是函数模板专用化[…]
不应该这样,因为签名最终是相同的。那么为什么调用
foo()
时没有歧义呢?我错过了什么 你引用的文本相当密集;你必须仔细阅读。“F1优于F2,如果对于所有参数i
,ICSi(F1)不是比ICSi(F2)更差的转换序列”--这里是这样,因为两个转换序列是相同的,因此,都不比另一个更差。现在转到最后一部分:“然后F1是非模板函数,F2是函数模板专用化”。这是真的,所以F1比F2更匹配。将F1和F2分别替换为foo()
和foo()
,规则表明foo()
比foo()
更匹配
哎呀,我回答错问题了。正如评论所指出的,问题是,为什么显式调用foo()
不能解析为foo()
?答案是,foo()
是对显式模板实例化的调用,而不是对重载函数的调用。考虑:
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(Ty){}
无效f(int);
无效g(int);
f(3.14);//调用f(重载函数调用)
f(1);//调用f(int)(重载函数调用)
f(3.14);//调用f(模板实例化的显式调用)
g(3.14);//呼叫g(int)
在本例中,
f
是模板专门化的名称。一般的函数名为<代码> f>代码>,所以不需要考虑重载,就像调用<代码> g(3.14)< /代码> .< /p> < p>您所引用的文本相当密集;你必须仔细阅读。“F1优于F2,如果对于所有参数i
,ICSi(F1)不是比ICSi(F2)更差的转换序列”--这里是这样,因为两个转换序列是相同的,因此,都不比另一个更差。现在转到最后一部分:“然后F1是非模板函数,F2是函数模板专用化”。这是真的,所以F1比F2更匹配。将F1和F2分别替换为foo()
和foo()
,规则表明foo()
比foo()
更匹配
哎呀,我回答错问题了。正如评论所指出的,问题是,为什么显式调用foo()
不能解析为foo()
?答案是,foo()
是对显式模板实例化的调用,而不是对重载函数的调用。考虑:
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(Ty){}
无效f(int);
无效g(int);
f(3.14);//调用f(重载函数调用)
f(1);//调用f(int)(重载函数调用)
f(3.14);//调用f(模板实例化的显式调用)
g(3.14);//呼叫g(int)
在本例中,
f
是模板专门化的名称。一般的函数名为<代码> f>代码>,所以没有重载要考虑,就像调用<代码> g(3.14)< /代码> .< /p>我没有得到的是为什么调用fo < int >,因为它归结为与FoE()相同的签名。或者它们被认为是不同的?@z3dd是的,它们是不同的:foo
是一个模板实例化。因此,它不能与非模板foo
相同。不能通过提供模板参数引用非模板。我不明白为什么允许调用foofoo
是一个模板实例化。因此,它不能与非模板foo
相同。不能通过提供模板参数引用非模板。所以没有歧义。