L-value-ref的部分排序

时间:2013-01-22 07:48:26

标签: c++ templates function-overriding partial-ordering

为什么这个含糊不清?

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中的合法。因此,部分订购应该有效。

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)

当这两种类型在类模板部分特化的部分排序中竞争时,你的推理是正确的,它就是那里的工作方式。

但是当一个引用类型与一个非引用类型进行比较时,一般的要点是它们在一个调用场景中是不明确的,如果没有别的东西让一个优先于另一个。也就是说,当与另一个进行比较时,引用类型的引用类型在重载决策中无关紧要,因此部分排序也不考虑它。