std :: forward实现之间的区别

时间:2017-02-19 15:44:25

标签: c++ c++11 move-semantics c++-standard-library lvalue-to-rvalue

最近我一直试图理解移动语义并提出了一个问题。

问题已经讨论过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指定为模板,并且不能让它用参数类型定义自己?

2 个答案:

答案 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