显然,不允许在ref-qualifiers上重载 - 如果您删除&
或&&
(只是令牌,而不是令牌),此代码将无法编译他们的职能):
#include <iostream>
struct S {
void f() & { std::cout << "Lvalue" << std::endl; }
void f() && { std::cout << "Rvalue" << std::endl; }
};
int main()
{
S s;
s.f(); // prints "Lvalue"
S().f(); // prints "Rvalue"
}
换句话说,如果您有两个名称和类型相同的函数,则必须定义两者,如果您定义。我认为这是故意的,但原因是什么?例如,为什么不允许为rvalues调用&&
版本(如果已定义),以及&#34; primary&#34; f()
关于以下变体中的所有其他内容(反之亦然 - 尽管这会令人困惑):
struct S {
void f() { std::cout << "Lvalue" << std::endl; }
void f() && { std::cout << "Rvalue" << std::endl; }
};
换句话说,让它们的行为类似于主模板的模板特化。
答案 0 :(得分:9)
以下情况没有任何不同:
struct S {};
void g(S s);
void g(S& s);
int main()
{
S s;
g(s); // ambiguous
}
过载分辨率一直都是这样的;通过引用传递不是优先传递值(反之亦然)。
(ref-qualified函数的重载解析就好像它是一个带有隐式第一个参数的正常函数,其参数为*this
; lvalue-ref qualified就像第一个参数S &
,{{ 1}}就像const &
等。)
我想你是说S const &
应该调用g(s)
而不是模棱两可。
我不知道确切的基本原理,但是重载决策很复杂,因为它没有添加更多特殊情况(特别是那些可能无声编译而不是编码器所期望的情况)。
正如您在问题中所述,使用g(S&)
和S &
这两个版本可以轻松避免此问题。
答案 1 :(得分:4)
你可以同时拥有两者或两者。 There is no specific requirement to include both if you implement the one
问题是未使用限定符标记的成员方法(非静态成员)适合与左值和右值一起使用。 一旦使用ref-qualifier重载方法,除非你也标记其他方法,否则会遇到模糊问题。
在重载解析期间,类
X
的非静态cv限定成员函数被视为一个函数,如果没有引用,则将带有lvalue类型的隐式参数引用到cv-qualifiedX
-qualifiers或者如果它具有左值ref-qualifier。否则(如果它有rvalue ref-qualifier),它被视为一个函数,它采用类型为rvalue的隐式参数引用cv-qualifiedX
。
所以基本上,如果你有一个合格的方法(例如对于左值&
)和一个不合格的方法,规则是有效的,因此它们都是合格的,因此是模棱两可的。
类似的基本原理适用于const
限定符。您可以实现一个方法,并为const
对象提供一个“版本”,为非const
对象提供一个“版本”。标准库容器就是很好的例子,特别是begin()
,end()
和其他与迭代器相关的方法。
一个特定的用例是当对象是临时(或过期)对象和不是对象时,应用于方法的逻辑是不同的。如果您知道生命周期即将结束,您可能希望在内部优化某些调用和数据处理。
另一种方法是将方法的使用限制为左值。如果实体即将到期或是临时的,某个应用程序或对象逻辑可能没有意义或有用。
§13.4.1/ 4标准中的措辞(取自N4567草案)是:
对于非静态成员函数,隐式对象参数的类型为
- 对于用&amp;&amp ;;声明的函数,
对于没有引用限定符或使用&amp;而声明的函数的“对cv X的左值引用” REF-限定符
“对cv X的rvalue引用” REF-限定符
答案 2 :(得分:1)
让我们从定义一个没有任何ref限定符的基本非静态成员函数的意义开始。
§13.3.1[4]
对于非静态成员函数,隐式对象参数的类型为
对于声明没有引用限定符或使用&amp; ref-qualifier 的函数,- “左值引用cv X ”
- 使用&amp;&amp;&ref-qualifier
声明的函数的“rvue对cv X的引用”
但等等,还有更多。
[5] 对于未使用ref-qualifier声明的非静态成员函数,适用其他规则:
即使隐式对象参数不是const限定的,也可以将rvalue绑定到参数 as 只要在所有其他方面,参数都可以转换为隐式对象参数的类型。
因此