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