【发布时间】:2019-12-12 02:26:17
【问题描述】:
template <typename T>
void show(T&); // #1
template <typename T>
void show(T const&); // #2
int main()
{
int a = 0;
show(a); // #1 to be called
}
我对这些偏序规则感到困惑。以下是一些引用:[temp.deduct.partial]/5
在完成部分排序之前,某些转换是 对用于偏序的类型执行:
如果
P是引用类型,则P将替换为引用的类型。如果
A是引用类型,则A将替换为所引用的类型。
如果
P和A都是引用类型(在被替换为 上面提到的类型),确定这两种类型中的哪一种(如果有的话) 比另一个更符合 cv 要求;否则类型是 对于部分排序目的,被认为是同样具有 cv 资格的。 下面将使用此确定的结果。
删除所有顶级 cv 限定符:
如果
P是 cv 限定类型,则P将替换为P的 cv 不限定版本。如果
A是 cv 限定类型,A将替换为A的 cv 不限定版本。
首先,void show(T&)和void show(T const&)都可以通过传递int左值来调用,所以我们需要使用偏序规则来决定哪个函数更匹配。然后,根据上面的引用,我们做一些转换。第 1 步:
T& => T #3
T const& => T const #4
第 2 步:
T => T #5
T const => T #6
#5 => #6,#6 => #5,双向推演成功。
然后以下规则起作用:[temp.deduct.partial]/9
如果,对于给定的类型,推论在两个方向上都成功(即, 上述转换后类型相同)和
P和A是引用类型(在被引用的类型替换之前 到上面):
如果参数模板中的类型是左值引用,而参数模板中的类型不是,则参数类型为 不被认为至少与参数类型一样专业;
否则,如果参数模板中的类型比参数模板中的类型更具 cv 限定(如所述 上),参数类型至少不被认为是 专门作为参数类型。
所以#4 比#3 更专业。对于给定值a,应该调用#2 函数,但实际上调用了#1 函数。为什么?我的理解有问题吗?
【问题讨论】:
-
我也很好奇这个答案,是不是因为
const&不是你声明和传递的?所以它只将值作为参考。如果您使用const int = 0,我认为第二个显示功能,const&将被调用。 -
@Raymond 如果你注释掉这些方法中的任何一个,剩下的函数也是匹配的,所以它们应该根据部分排序规则来决定哪个更匹配,但是部分排序规则选择#2,编译器选择#1,可能是对这些部分排序规则的补充让编译器使用#1,需要知道的人告诉我们
-
嗨,jack X。我已经编辑了您的问题,以包含指向标准相关部分的链接。这有助于其他人收集上下文。请在以后的问题中做同样的事情。谢谢!
标签: c++ language-lawyer template-argument-deduction function-templates partial-ordering