为什么这是模棱两可的?
template<class T> void g(T) {} // 1
template<class T> void g(T&) {} // 2
int main() {
int q;
g(q);
}
我知道这是部分排序上下文。而我的,可能是错误的想法是:#2 中的任何 T& 都可以放入 #1,但 #1 中的任何 T 都不是合法的 #2。所以部分排序应该有效。
为什么这是模棱两可的?
template<class T> void g(T) {} // 1
template<class T> void g(T&) {} // 2
int main() {
int q;
g(q);
}
我知道这是部分排序上下文。而我的,可能是错误的想法是:#2 中的任何 T& 都可以放入 #1,但 #1 中的任何 T 都不是合法的 #2。所以部分排序应该有效。
好的。我想这就是你要找的。没有深入研究参数与参数类型比较的两次应用,标准中的以下内容让我眼前一亮:
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 被 P 的 cv 非限定版本替换。
- 如果 A 是 cv 限定类型,则 A 将替换为 A 的 cv 非限定版本。
现在两者完全相等,因此您有歧义,我相信它是从 C++11 §14.8.2.4p10 固化的。C++11 §14.8.2.4p9 的文本涵盖了这两种引用类型,同样,这里不是这种情况:
C++11 §14.8.2.4p10
如果对于每个被考虑的类型,一个给定的模板至少对所有类型都是专门化的,并且对某些类型集更专门化,而另一个模板对任何类型都没有更专门化,或者至少对任何类型都没有专门化,那么给定模板比其他模板更专业。否则,两个模板都不比另一个模板更专业。
但是阅读本节中的标准对我来说就像是在解读希腊语,所以我可能会大错特错。(对希腊人没有冒犯=P)。
然而,它确实让我认为“如果我刚刚阅读的所有内容都按书面形式强制执行,那么在给定相同的调用条件的情况下,aconst T&
对 a也应该是模棱两可的。” 果然,我试过了,同样的模棱两可被标记出来。T
g(q)
当这两种类型在类模板部分专业化的部分排序中竞争时,您的推理是正确的,这就是事情的运作方式。
但是,当将引用类型与非引用类型进行比较时,一般的要点是,如果没有其他因素使一个比另一个更受青睐,那么它们在调用场景中是模棱两可的。也就是说,当与另一个比较时,引用类型的引用类型在重载决议中并不重要,因此部分排序也不考虑它。