虽然不能将右值传递给接受非常量引用的函数,但可以对右值调用成员函数,但成员函数不知道它是如何调用的。如果返回对当前对象的引用,则可以将右值转换为左值:
class scratchpad_t
{
// ...
public:
scratchpad_t& self()
{
return *this;
}
};
void foo(scratchpad_t& r)
{
}
int main()
{
foo(scratchpad_t().self());
}
请注意如何调用self()
即使产生左值表达式scratchpad_t
是一个右值。
如果我错了,请纠正我,但右值引用参数不接受左值引用,因此使用它们需要向暂存器的所有使用者添加重载,这也是不幸的。
嗯,你可以使用模板...
template <typename Scratch> void foo(Scratch&& scratchpad)
{
// ...
}
如果你打电话foo
带有右值参数,Scratch
将被推导为scratchpad_t
, 因此Scratch&&
将scratchpad_t&&
.
如果你打电话foo
带有左值参数,Scratch
将被推导为scratchpad_t&
,并且由于参考折叠规则,Scratch&&
也将是scratchpad_t&
.
注意形式参数scratchpad
是一个名称,因此也是一个左值,无论其类型是左值引用还是右值引用。如果你想通过scratchpad
对于其他函数,您不再需要这些函数的模板技巧,只需使用左值引用参数即可。
顺便说一句,您确实意识到临时暂存器涉及xyz.initialize_computation(scratchpad_t(1, 2, 3));
将尽快被摧毁initialize_computation
完成了,对吗?将引用存储在xyz
对于后来的用户来说,对象将是一个非常糟糕的主意。
self()
不需要是成员方法,它可以是模板函数
是的,这也是可能的,尽管我会重命名它以使意图更清晰:
template <typename T>
T& as_lvalue(T&& x)
{
return x;
}