Cla*_*diu 6 c++ templates overloading overload-resolution
我有以下代码,可能看似令人费解,但来自真正的代码:
#include <iostream>
using namespace std;
template <class Hrm, class A>
void foo(Hrm& h, A& a)
{
cout << "generic" << endl;
}
template <template <bool> class Hrg>
void foo(Hrg<false>& h, int& a)
{
cout << "specialized int" << endl;
}
template <template <bool> class Hrg>
void foo(Hrg<true>& h, const int& a)
{
cout << "specialized const-int" << endl;
}
template <bool W>
struct what;
template<> struct what<true> { };
template<> struct what<false> { };
int main() {
what<true> wt;
what<false> wf;
int i = 5;
const int& ri = i;
foo(wt, i); // 1) generic
foo(wf, i); // 2) specialized int
foo(wt, ri); // 5) specialized const-int
foo(wf, ri); // 6) generic
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我明白了4
:有没有专门针对虚假Hrg
与const int
,所以仿制药就会被调用.
我的问题是,为什么给定的函数调用其他情况?3
似乎称为专门的const版本,因为const int
匹配"更直接" A
.我想知道为什么会更具体地发生这种情况.
而且,那1
和2
?特别是,1
对我来说非常惊讶:为什么要generic
调用版本而不是专门的const-int?
另外需要注意:如果我将两个foo
专业更改为:
template <template <bool> class Hrg>
void _foo(Hrg<false>& h, int& a)
{
cout << "specialized int" << endl;
}
template <template <bool> class Hrg>
void _foo(Hrg<true>& h, const int& a)
{
cout << "specialized const-int" << endl;
}
template <class Hrg>
void foo(Hrg& h, int& a)
{
return _foo(h, a);
}
template <class Hrg>
void foo(Hrg& h, const int& a)
{
return _foo(h, a);
}
Run Code Online (Sandbox Code Playgroud)
然后输出变为:
foo(wt, i); // a) specialized const-int
foo(wf, i); // b) specialized int
foo(wt, ri); // c) specialized const-int
//foo(wf, ri); // d) compilation error
Run Code Online (Sandbox Code Playgroud)
这对我来说是一个更直观的结果.
重载解析按以下步骤进行:
请务必记住,第 4 步是在第 3 步之后进行的;“通用性”或“模板性”完全是一个打破平局的规则。
让我们回顾一下第一个代码块中的所有示例。
(1) 第一次、第三次超载扣除成功;Hrg
无法推导出第二个。因此,候选人是第一和第三(规则 1)。两者都是可行的(规则 2)。第一个重载将绑定i
到int&
,而第三个重载将绑定i
到const int&
。首选结合简历资格较少的参考文献(规则 3)。(巴里有标准中的具体引用。)第一个(通用)重载获胜。
(2)Hrg
无法针对第三个超载推出,因此它不是候选者(规则 1)。第一个和第二个是候选者并且是可行的(规则2)。第一个和第二个重载都完全匹配,不需要转换,并且根据规则 3 无法区分。第二个重载获胜,因为它更专业(规则 4)。
(5) 第二次超载扣除Hrg
失败,因此不是候选者,而第一和第三次超载则为候选者(规则1)。请注意,对于第一个重载,A
被推导为const int
,产生与第三个重载相同的签名。它们都是可行的(规则 2),并且在规则 3 结束时无法区分。第三个超载获胜,因为它更专业(规则 4)。
(6) 第三次超载扣除Hrg
失败,因此不是候选者,而第一次和第二次是候选者(规则1)。第二个重载不可行(规则 2),因为int&
无法绑定到ri
,即const
。第一个重载(通用重载)是唯一可行的函数,因此它获胜。
我将重载解析留在第二个代码块中作为读者的练习。
[1] 正如 TC 在评论中指出的那样,这里有一个微妙之处。仅当对于给定的函数对,从实参初始化参数所需的隐式转换序列对于每对对应的参数具有相同的排名时,才适用平局规则。如果第一个函数对于一个参数具有更好的隐式转换序列,而第二个函数对于另一个参数具有更好的隐式转换序列,则不应用平局规则,并且歧义仍然存在。不过,这种情况不会出现在问题的示例中。