我一直在编写以下代码来支持对rvalue的函数调用,而不必在返回值上显式地std::move
。
struct X {
X& do_something() & {
// some code
return *this;
}
X&& do_something() && {
// some code
return std::move(*this);
}};
但是这导致必须在函数内部重复代码。最好,我会做类似的事情
struct X {
X& do_something() & {
// some code
return *this;
}
X&& do_something() && {
return std::move(do_something());
}};
这是有效的转换吗?为什么或为什么不呢?
[此外,我不禁感到引用裁判限定词存在一些知识鸿沟。是否有一种通用的方法(或一组规则)来确定类似这样的代码是否有效?
这是有效的转换吗?
是。在成员函数*this
中始终是一个左值。即使该函数是右值引用限定的。与
void foo(bar& b) { /* do things */ }
void foo(bar&& b) {
// b is an lvalue inside the function
foo(b); // calls the first overload
}
因此,您可以使用左值ref限定函数来共享实现。
并且在结果上使用std::move
也没有问题。第一个重载只能返回一个左值引用,因为据它所知,它是在一个左值上调用的。同时,第二个重载具有额外的信息,它知道它最初是在右值上调用的。因此,它会根据其他信息进行额外的转换。
std::move
只是将左值转换为右值的命名转换。其目的是发信号通知指定的对象可以被视为即将过期。由于您是在知道其为真的上下文中进行此转换的(该成员最初是在绑定到右值引用的对象上调用的),因此它不会造成问题。