函数重载优先级(引用)

时间:2017-01-06 11:52:10

标签: c++ reference language-lawyer rvalue-reference overloading

void func(const int &) { std::cout << "c lv ref\n"; }
void func(int &&) { std::cout << "rv ref\n"; }

func(1);

由于const lvalue引用能够接受各种数据(const和非lval,const和非rvalue),我想知道上面代码打印“rv ref”的保证是什么。它是标准化的还是编译器依赖的?

1 个答案:

答案 0 :(得分:6)

我之前的解释是错误的 - 如T.C. mentioned in the comments,两个重载都具有相同的隐式转换序列,并且消歧是作为标准中定义的特殊打破平局发生的。

  

§13.3.3.1.4 [over.ics.ref],par。 1

     
    

当引用类型的参数直接将([dcl.init.ref])绑定到参数表达式时,隐式转换序列是标识转换,除非参数表达式具有type是参数类型的派生类,在这种情况下,隐式转换序列是派生到基础的转换([over.best.ics])。 [...]

  

如果参数类型相同,则应用于两个重载的隐式转换序列标识转换。这还没有消除这两个功能的歧义。

消歧在这里被指定为打破平局:

  

§13.3.3.2 [over.ics.rank],参见3.2.3

     
    

[标准转换序列 S1是比标准转换序列S2更好的转换序列,如果 ...] S1和S2是参考绑定 ([dcl.init.ref])并且都没有引用没有ref-qualifier声明的非静态成员函数的隐式对象参数,和S1将rvalue引用绑定到rvalue并且S2绑定左值引用< / strong>即可。 [...]

  

引用意味着,在两个身份隐式转换序列的情况下:

  • 将右值与右值参考绑定的序列是最佳的。

  • 将右值与左值参考值绑定的序列比上述值更差。

  

[...]如果S1和S2是参考绑定[...]

需要const将rvalues绑定到const&的原因可以在这里找到:

  

§8.6.3 [dcl.init.ref],标准杆5.2

     
    

对“cv1 T1”类型的引用由“cv2 T2”类型的表达式初始化,如下所示:

         

[如果引用是左值引用和初始化表达式...]

         

否则,引用应为非易失性const类型的左值引用(即,cv1应为const),或引用应为右值引用。

         

如果初始化表达式 [...] 是右值(但不是位字段)或函数左值和“cv1 T1”是引用 - 与“cv2 T2”兼容