std::forward 实现之间的差异
Difference between std::forward implementation
最近我一直在尝试理解移动语义并想出了一个问题。
这个问题已经讨论过了here。
我实现了第一个变体并检查它是 returns 左值还是右值:
#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;
}
因此,如果我传递左值,它会 returns 左值(编译,因为我可以从左值获取地址),如果我这样做:
&my_forward(int(5)); // r-value with int&& type
我的代码无法编译,因为 my_forward 返回了右值。在上面的问题中,他们说这个实现和标准实现之间的区别(分别使用 std::remove_reference 和 & 和 && 的 2 个不同参数)是我的实现一直 returns l-value,但是作为我已经显示 returns r 值和 l 值。
所以我想知道,为什么我不能那样实现 std::forward?在什么具体情况下,它会显示标准之间的差异?还有,为什么我要把 T 指定为模板,而不能让它用参数类型定义自己?
尝试在真实环境中像 std forward 一样进行 hsing。你的不行;
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
.
所有有名字的东西都是左值,但是向前移动带名字的右值引用。
带名称的右值引用是左值。
不幸的是,获取地址在您的上下文中不是有用的操作,因为它查看了错误的值类别:
您可以获取左值的地址,但不能获取纯右值的地址。 glvalue 表示 "location"(即对象所在的位置),prvalue 表示 "initialization"(即对象具有什么值)。
您可以从右值窃取资源,但不能从左值窃取资源。左值引用绑定到左值,右值引用绑定到右值。 std::forward
的要点是在提供右值时将参数转换为右值,在提供左值时将参数转换为左值。
当std::forward
returns一个右值时,它实际上returns一个xvalue,xvalues既是右值又是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
最近我一直在尝试理解移动语义并想出了一个问题。
这个问题已经讨论过了here。
我实现了第一个变体并检查它是 returns 左值还是右值:
#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;
}
因此,如果我传递左值,它会 returns 左值(编译,因为我可以从左值获取地址),如果我这样做:
&my_forward(int(5)); // r-value with int&& type
我的代码无法编译,因为 my_forward 返回了右值。在上面的问题中,他们说这个实现和标准实现之间的区别(分别使用 std::remove_reference 和 & 和 && 的 2 个不同参数)是我的实现一直 returns l-value,但是作为我已经显示 returns r 值和 l 值。
所以我想知道,为什么我不能那样实现 std::forward?在什么具体情况下,它会显示标准之间的差异?还有,为什么我要把 T 指定为模板,而不能让它用参数类型定义自己?
尝试在真实环境中像 std forward 一样进行 hsing。你的不行;
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
.
所有有名字的东西都是左值,但是向前移动带名字的右值引用。
带名称的右值引用是左值。
不幸的是,获取地址在您的上下文中不是有用的操作,因为它查看了错误的值类别:
您可以获取左值的地址,但不能获取纯右值的地址。 glvalue 表示 "location"(即对象所在的位置),prvalue 表示 "initialization"(即对象具有什么值)。
您可以从右值窃取资源,但不能从左值窃取资源。左值引用绑定到左值,右值引用绑定到右值。
std::forward
的要点是在提供右值时将参数转换为右值,在提供左值时将参数转换为左值。
当std::forward
returns一个右值时,它实际上returns一个xvalue,xvalues既是右值又是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