函数重载优先级(参考)

Function overloads priority (references)

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

func(1);

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

我之前的解释不正确 - 因为 ,两个重载具有相同的 隐式转换序列 ,并且消歧是作为标准。


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

When a parameter of reference type binds directly ([dcl.init.ref]) to an argument expression, the implicit conversion sequence is the identity conversion, unless the argument expression has a type that is a derived class of the parameter type, in which case the implicit conversion sequence is a derived-to-base Conversion ([over.best.ics]). [...]

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

此处将消歧指定为决胜局:

§13.3.3.2 [over.ics.rank], par 3.2.3

[Standard conversion sequence S1 is a better conversion sequence than standard conversion sequence S2 if...] S1 and S2 are reference binding ([dcl.init.ref]) and neither refers to an implicit object parameter of a non-static member function declared without a ref-qualifier, and S1 binds an rvalue reference to an rvalue and S2 binds an lvalue reference. [...]

引号暗示,在两个身份隐式转换序列的情况下

  • 将右值绑定到右值引用的序列是最好的。

  • 将右值引用绑定到左值引用的序列比前面提到的更糟糕。


[...] if S1 and S2 are reference binding [...]

可以在此处找到 const 将右值绑定到 const& 的原因:

§8.6.3 [dcl.init.ref], par 5.2

A reference to type “cv1 T1” is initialized by an expression of type “cv2 T2” as follows:

[If the reference is an lvalue reference and the initializer expression...]

Otherwise, the reference shall be an lvalue reference to a non-volatile const type (i.e., cv1 shall be const), or the reference shall be an rvalue reference.

If the initializer expression [...] is an rvalue (but not a bit-field) or function lvalue and “cv1 T1” is reference-compatible with “cv2 T2”