根据Is a member of an rvalue structure an rvalue or lvalue?:
如果E1
是左值,那么E1.E2
是左值,只有当该参数绑定到右值时,才将其参数转发到右值。在下面的函数void foo(Obj &&obj)
中,obj
是左值,因此obj.i
是左值,为什么std::forward<int>(obj.i)
是左值?
class Obj
{
public:
int i;
};
void foo(int &i)
{
cout<<"foo(int&)"<<endl;
}
void foo(int &&i)
{
cout<<"foo(int&&)"<<endl;
}
void foo(Obj &&obj)
{
foo(std::forward<int>(obj.i));
foo(obj.i);
}
int main()
{
Obj obj;
foo(std::move(obj));
return 0;
}
输出
foo(int&&)
foo(int&)
答案 0 :(得分:0)
下面的函数void foo(Obj&amp;&amp; obj):
obj是左值,所以obj.i是左值,
嗯,您是否在函数proto中将obj
声明为右值参考,然后坚持认为它是左值?
答案 1 :(得分:0)
根据std::forward
的规范,返回类型很简单,应用于模板类型的右值引用。因此返回类型std::forward<int>
为int&&
- 以这种方式使用它与std::move
具有完全相同的效果。
使用std::forward
的常规方法是使用通用引用:
template<typename T>
void f(T&& val)
{
other_func(std::forward<T>(val));
}
这适用于引用,因为在这种情况下左值引用的推导类型也是左值引用。在你的情况下,你是硬编码类型(到int
)而不是推导它 - 如果使用上述模式,推导出的类型实际上是int&
,而不是int
。
您会看到,如果您将foo(std::forward<int>(obj.i))
更改为foo(std::forward<int&>(obj.i))
,您将得到您期望的结果
答案 2 :(得分:0)
你实际上是在转发错误的东西。在这个功能中:
void foo(Obj &&obj)
{
foo(std::forward<int>(obj.i));
foo(obj.i);
}
obj
有名字,所以它是左值。在这两种情况下,obj.i
都是左值,只是在第一次将它明确地转换为右值时!当forward
获得引用类型时,您会获得左值。当它获得非引用类型时,您将得到一个右值。你给它一个非引用类型,所以这里的forward
相当于:foo(std::move(obj.i));
这会让你更清楚为什么得到一个右值?
但是,您链接的问题是关于 rvalues 的成员。为此,您需要将obj
本身转换为右值:
foo(std::move(obj).i);
此处,由于std::move(obj)
是左值,std::move(obj).i
也是左值。
无论如何,在通过非转发引用参数时使用forward
有点奇怪。这是一个更一般的例子:
template <class O>
void foo(O&& obj) {
foo(std::forward<O>(obj).i);
}
foo(obj); // calls foo(int&)
foo(std::move(obj)); // calls foo(int&&)
在前一种情况下,std::forward<O>(obj)
是左值,因为O
是Obj&
,这使得std::foward<O>(obj).i
成为左值。在后一种情况下,它们都是左值。