Cri*_*iss 4 c++ overloading reference rvalue-reference language-lawyer
void func(const int &) { std::cout << "c lv ref\n"; }
void func(int &&) { std::cout << "rv ref\n"; }
func(1);
Run Code Online (Sandbox Code Playgroud)
由于const lvalue引用能够接受每种数据(const和非lval,const和非rvalue),我想知道上面的代码将打印"rv ref"的保证是什么.它是标准的还是编译器依赖的?
我之前的解释是错误的 - 正如评论中提到的TC,两个重载具有相同的隐式转换序列,并且消歧作为标准中定义的特殊打破平局发生.
§13.3.3.1.4 [over.ics.ref],par.1
当引用类型的参数直接绑定([dcl.init.ref])到参数表达式时,隐式转换序列是标识转换,除非参数表达式的类型是参数类型的派生类,其中case隐式转换序列是派生到基础的转换([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绑定左值引用.[...]
引号意味着,在两个身份隐式转换序列的情况下:
将rvalue绑定到右值参考的序列是最好的.
将右值与左值参考结合的序列比上述序列更差.
[...]如果S1和S2是参考绑定[...]
可以在此处找到const绑定rvalues 的原因const&:
§8.6.3 [dcl.init.ref],参见 5.2
对类型"cv1 T1"的引用由类型"cv2 T2"的表达式初始化,如下所示:
[如果引用是左值引用和初始化表达式...]
否则,引用应是对非易失性const类型的左值引用(即,cv1应为const),或者引用应为右值引用.
如果初始化表达式 [...] 是rvalue(但不是位字段)或函数lvalue,并且"cv1 T1"与"cv2 T2"引用兼容