为什么这个含糊不清?
template<class T> void g(T) {} // 1
template<class T> void g(T&) {} // 2
int main() {
int q;
g(q);
}
我知道这是部分排序上下文。我的,可能是错误的想法是:任何T&amp;从#2开始可以放在#1中,但#1中的任何T都不是#2中的合法。因此,部分订购应该有效。
答案 0 :(得分:7)
行。我认为这就是你要找的东西。没有深入参与参数与参数类型比较的两次应用,标准中的以下内容跳出来了:
C ++11§14.8.2.4p5
在完成部分排序之前,会对用于部分排序的类型执行某些转换:
- 如果P是引用类型,则P将被引用的类型替换。
- 如果A是引用类型,则A将被引用的类型替换。
C ++11§14.8.2.4p6继续谈论当两个都是引用类型时会发生什么,但这在这里不适用(尽管也是一个有趣的读物)。在你的情况下,只有一个,所以它被剥离。从那里:
C ++11§14.8.2.4p7
删除所有顶级cv限定符:
- 如果P是cv限定类型,则P将被cv非限定版本的P替换。
- 如果A是cv限定类型,则A将被cv非限定版本的A替换。
现在两者完全相同,因此你有歧义,我认为这是从C ++11§14.8.2.4p10中巩固的。 C ++11§14.8.2.4p9的文本涵盖了两种引用类型,而这种情况并非如此:
C ++11§14.8.2.4p10
如果考虑的每种类型,给定的模板至少对所有类型都是专用的,对某些类型的集合更专用,而另一种模板对于任何类型都不是更专用的,或者至少不适用于任何类型,那么给定的模板比其他模板更专业。 否则,两个模板都不比另一个更专业。
但是阅读本节中的标准就像解密希腊语一样,所以我可能方式偏离基础。 (希腊人没有违法行为= P)。
但是,如果给出相同的调用条件const T&
,它确实让我认为“对T
g(q)
”,如果我刚刚阅读的所有内容都被强制执行,那么它也应该是不明确的书面。”果然,我试过了,并且标记了同样的含糊不清。
答案 1 :(得分:4)
当这两种类型在类模板部分特化的部分排序中竞争时,你的推理是正确的,它就是那里的工作方式。
但是当一个引用类型与一个非引用类型进行比较时,一般的要点是它们在一个调用场景中是不明确的,如果没有别的东西让一个优先于另一个。也就是说,当与另一个进行比较时,引用类型的引用类型在重载决策中无关紧要,因此部分排序也不考虑它。