鉴于下面的代码,为什么foo(T*)选择该功能?
如果我删除它(foo(T*)代码)代码仍然编译并正常工作,但G ++ v4.4.0(以及可能还有其他编译器)将生成两个foo()函数:一个用于char [4],另一个用于char [7].
#include <iostream>
using namespace std;
template< typename T >
void foo( const T& )
{
cout << "foo(const T&)" << endl;
}
template< typename T >
void foo( T* )
{
cout << "foo(T*)" << endl;
}
int main()
{
foo( "bar" );
foo( "foobar" );
return 0;
}
Run Code Online (Sandbox Code Playgroud)
形式上,在比较转换序列时,忽略左值变换.转化分为几个类别,如资格调整(T*- > T const*),左值转换(int[N]- > int*,void()- > void(*)())等.
两个候选人之间的唯一区别是左值变换.字符串文字是转换为指针的数组.第一个候选者通过引用接受数组,因此不需要左值变换.第二个候选人需要左值变换.
因此,如果有两个候选者,通过仅查看转换,两个函数模板特化都同样可行,那么规则是通过对两者进行部分排序来选择更专业的一个.
让我们通过查看它们的函数参数列表的签名来比较它们
void(T const&);
void(T*);
Run Code Online (Sandbox Code Playgroud)
如果我们选择一些特殊类型的Q第一个参数列表,并试图匹配第二个参数列表中,我们是匹配的Q反对T*.这将失败,因为Q它不是指针.因此,第二个至少与第一个一样专业.
如果我们做的其他方式,我们一致Q*反对T const&.删除引用并忽略顶级限定符,其余的T变为Q*.这是用于部分排序的精确匹配,因此第二候选的第二候选变换参数列表的推断成功.由于另一个方向(相对于第二个)没有成功,第二个候选者比第一个更专业 - 因此,如果否则会出现歧义,则重载决策将更喜欢第二个.
在13.3.3.2/3:
标准转换序列S1是比标准转换序列S2更好的转换序列,如果[...]
- S1是S2的正确子序列(比较13.3.3.1.1定义的规范形式的转换序列,不包括任何左值变换;身份转换序列被认为是任何非同一性转换序列的子序列),或者,如果不是那个 [...]
然后 13.3.3/1
- 让ICSi(F)表示隐式转换序列,它将列表中的第i个参数转换为可行函数F的第i个参数的类型.13.3.3.1定义了隐式转换序列,13.3.3.2定义了它的含义一个隐式转换序列是一个比另一个更好的转换序列或更差的转换序列.
鉴于这些定义,可行函数F1被定义为比另一个可行函数F2更好的函数,如果对于所有自变量i,ICSi(F1)不是比ICSi(F2)更差的转换序列,然后[...]
- F1和F2是功能模板特化,F1的功能模板比F2的模板更专业,根据14.5.5.2中描述的偏序规则,或者,如果不是,[...]
最后,这里是可能参与标准转换序列的隐式转换表13.3.3.1.1/3.
转换序列http://img259.imageshack.us/img259/851/convs.png
| 归档时间: |
|
| 查看次数: |
2100 次 |
| 最近记录: |