最近我一直试图理解移动语义并提出了一个问题。
问题已经讨论过here。
我实现了第一个变体并检查它是否返回l值或r值:
#include <iostream>
using namespace std;
template <typename T>
T&& my_forward(T&& x) {
return static_cast<T&&> (x);
}
int main() {
int a = 5;
&my_forward(a); // l-value
return 0;
}
因此,如果我传递l值,它会返回l值(编译,因为我可以从l值中获取地址)并且如果我这样做:
&my_forward(int(5)); // r-value with int&& type
我的代码无法编译,因为my_forward返回了r值。在上面的问题中,他们说这个实现和标准之间的区别(使用std :: remove_reference和2个不同的参数分别带有&amp;和&amp;&amp;&amp;),我的实现总是返回l值,但是当我已经显示它返回r值和l值。
所以我想知道,为什么我不能像那样实现std :: forward?在具体情况下,它会显示标准之间的区别吗?另外,为什么我应该将T指定为模板,并且不能让它用参数类型定义自己?
答案 0 :(得分:3)
尝试在真正的上下文中像std forward一样。你的不起作用;
void test(std::vector<int>&&){}
template<class T>
void foo(T&&t){
test(my_forward<T>(t));
}
foo( std::vector<int>{} );
以上不编译。它适用于std::forward
。
除了块引用生命周期扩展之外,您的转发没有任何用处。同时,std::forward
是条件std::move
。
具有名称的所有内容都是左值,但是向前移动带有名称的右值引用。
带名称的右值引用是左值。
答案 1 :(得分:1)
不幸的是,在您的上下文中使用该地址并不是一项有用的操作,因为它会查看错误类型的值类别:
您可以获取glvalue的地址,但不能获取prvalue的地址。 glvalue代表&#34;位置&#34; (即,对象所在的位置),prvalue代表&#34;初始化&#34; (即对象具有什么价值)。
您可以从右值窃取资源,但不能从左值窃取资源。左值引用绑定到左值,右值引用绑定到右值。 std::forward
的要点是在提供右值时将参数强制转换为右值,并在提供左值时将参数强制转换为左值。
当std::forward
返回一个右值时,它实际上返回一个xvalue,而xvalues都是rvalues和glvalues:
lvalue f() for "T& f();", decltype(f()) is T&
/
glvalue
/ \
value xvalue f() for "T&& f();", decltype(f()) is T&&
\ /
rvalue
\
prvalue f() for "T f();", decltype(f()) is T