Ash*_*hot 21 c++ templates function overload-resolution
#include <iostream>
template <class U, class T>
void foo(U&, T&)
{
std::cout << "first";
}
template <class T>
void foo(int&, const T&)
{
std::cout << "second";
}
int main()
{
int a;
double g = 2.;
foo(a, g); // prints "first"
return 0;
}
Run Code Online (Sandbox Code Playgroud)
要调用第二个foo重载,编译器只需执行一次模板类型推导,但对于第一次重载,它需要执行两次.你能解释为什么第一次超载被调用了吗?
Bar*_*rry 18
过载分辨率分多步完成.
首先,通过名称查找,我们选择可行的候选人列表.在这种情况下,即:
template <class U, class T>
void foo(U&, T&); // with U = int, T = double
template <class T>
void foo(int&, const T&) // with T = double
Run Code Online (Sandbox Code Playgroud)
接下来,我们确定每个可行候选者的每个参数所需的转换序列.这是[over.ics.rank]:
如果[...] 标准转换序列
S1是比标准转换序列更好的转换序列S2
- S1是S2的正确子序列(比较13.3.3.1.1定义的规范形式的转换序列,不包括任何左值变换;身份转换序列被认为是任何非同一性转换序列的子序列),或者,如果不是那个,
- S1的等级优于S2的等级,或者S1和S2具有相同的等级,并且可以通过下面段落中的规则区分,或者,如果不是,
对于第一次调用,转换序列是(Identity,Identity).对于第二次调用,转换序列是(Identity,Identity).所以我们在那里是平等的.这两个要点都没有区分这两个要求.所以我们继续前进.
- S1和S2是引用绑定(8.5.3),并且都不引用没有ref-qualifier声明的非静态成员函数的隐式对象参数,S1将rvalue引用绑定到rvalue,S2绑定左值引用.
无关紧要.
- S1和S2是引用绑定(8.5.3),S1将左值引用绑定到函数左值,S2将右值引用绑定到函数左值.
不.
- S1和S2的区别仅在于它们的资格转换并且分别产生类似的类型T1和T2(4.4),并且类型T1的cv资格特征签名是T2类型的cv资格特征的适当子集.
资格转换是一个指针的事情,不.
- S1和S2是引用绑定(8.5.3),引用引用的类型除了顶级cv限定符之外是相同的类型,并且S2引用的引用所引用的类型比cv更合格.由S1初始化的引用所引用的类型.
在这种情况下,第一个重载采用第二个参数,double&而第二个重载采用a const double&.前者是少品种比后者-qualified,所以我们在这里停止-喜欢foo(U&,T&).
只有在确定哪个转换序列更好的步骤之后,我们才能进入更专业的模板首选的步骤.[over.match.best]中的完整规则排序是:
给定这些定义,可行函数F1被定义为比另一个可行函数F2更好的函数,如果对于所有自变量i,ICSi(F1)不是比ICSi(F2)更差的转换序列,然后
- 对于某些参数j,ICSj(F1)是比ICSj(F2)更好的转换序列,或者,如果不是,
这就是我们刚刚经历的事情.
- 上下文是用户定义的转换初始化[...]
- 上下文是通过转换函数初始化直接引用绑定[...]
- F1不是函数模板特化,F2是函数模板特化,或者,如果不是,
- F1和F2是功能模板特化,根据14.5.6.2中描述的偏序规则,F1的功能模板比F2的模板更专业.
这就是我们选择的原因foo(U&, T&).const但是,如果删除了,则两个转换序列在所有步骤中都是相同的 - 所以在这一点上,更专业的模板(foo(int&, T&))将获胜.
请注意,更专业的是 确定最佳候选人的最后一种机制.这是决胜局的最后决定.
另请注意,模板扣除的数量无关紧要.它可以不管在过载是一个模板和过载这不是一个模板之间进行选择-但它不会在具有过载之间选择无关紧要X模板参数和具有过载Y> X模板参数.
你在第二个函数中声明第二个参数是const.下面的应用修正示例调用第二个示例:
#include <iostream>
template <class U, class T>
void foo(U&, T&)
{
std::cout << "first";
}
template <class T>
void foo(int&, T&)
{
std::cout << "second";
}
int main()
{
int a;
double g = 2.;
foo(a, g);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
另一方面,当您显式声明第二个参数const时main(),应用程序将按照预期在上面的示例中调用第二个函数:
#include <iostream>
template <class U, class T>
void foo(U&, T&)
{
std::cout << "first";
}
template <class T>
void foo(int&, const T&)
{
std::cout << "second";
}
int main()
{
int a;
const double g = 2.;
foo(a, g);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2181 次 |
| 最近记录: |