为什么有歧义?
template<class T> void g(T) {} // 1
template<class T> void g(T&) {} // 2
int main() {
int q;
g(q);
}
我知道这是部分排序上下文。而我的想法(可能是错误的)是:任何T中的T可以放到#1中,但#1中的T不能放到#2中。所以部分排序应该是可行的
OK。我认为这就是你要找的。在不深入研究两次应用形参与实参类型比较的情况下,标准中的以下内容引起了我的注意:
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-qualified类型,则P被替换为P的cv-qualified版本。
- 如果A是cv-qualified类型,则将A替换为A的cv-qualified版本。
现在两者是完全相等的,因此你有了你的歧义,我相信这是从c++ 11§14.8.2.4p10中固化的。c++ 11§14.8.2.4p9的文本涵盖了两者都是引用类型,而这里的情况并非如此:
c++ 11§14.8.2.4p10
如果对于所考虑的每种类型,给定模板至少对所有类型都是专门化的,对某些类型集更专门化,而另一个模板对任何类型都不是专门化的,或者至少对任何类型都不是专门化的,则给定模板比另一个模板更专门化。否则,没有一个模板比另一个模板更专门化
但是阅读本节中的标准对我来说就像破译希腊语一样,所以我可能方式偏离了基础。(无意冒犯希腊人=P)。
它确实,然而,让我认为"一个const T&
对一个T
,给定相同的调用条件g(q)
,也应该是模棱两可的,如果我刚刚读到的一切都是强制写入的。"果然,我尝试了一下,同样的模糊性也被标记出来了。
当这两种类型在类模板部分专门化的部分排序中竞争时,你的推理是正确的,事情就是这样工作的。
但是,当将引用类型与非引用类型进行比较时,一般的要点是,如果没有其他因素使一种类型优于另一种类型,则它们在调用场景中是不明确的。也就是说,与其他引用类型相比,引用类型的引用类型在重载解析中无关紧要,因此偏排序也不考虑它。