转发前向参考的个别成员

时间:2018-05-03 08:07:30

标签: c++11 move-semantics class-members forwarding-reference

我有一个可能通过其成员移动泛型参数的函数。这些选项中哪些更正确:

  1. 这似乎更自然但很奇怪,因为参数可能会移动两次[a],这很奇怪,因为对象可能变得无效。

    template<class T> 
    void fun(T&& t){
        myhead_ = std::forward<T>(t).head_;
        myrest_ = std::forward<T>(t).rest_;
    }
    
  2. 这可能不正确,但可能无法移动任何内容。

    template<class T> void fun(T&& t){
        myhead_ = std::forward<decltype(t.head_)>(t.head_);
        myrest_ = std::forward<decltype(t.rest_)>(t.rest_);
    }
    
  3. 这看似正确但代码太多了。

    template<class T> void fun(T& t){
        myhead_ = t.head_;
        myrest_ = t.rest_;
    }
    template<class T> void fun(T&& t){
        myhead_ = std::move(t.head_);
        myrest_ = std::move(t.rest_);
    }
    
  4. [a]这句话是不正确的,因为@Angew指出,只有看起来好像被移动了两次。 std::forward(如std::move)实际上并没有移动任何东西。最多移动成员(通过后续操作decltype(myhead)::operator=,但这正是目标。)

1 个答案:

答案 0 :(得分:3)

你的第一个代码非常好:

template<class T> 
void fun(T&& t){
    myhead_ = std::forward<T>(t).head_;
    myrest_ = std::forward<T>(t).rest_;
}

这是因为标准保证当a.ba是xvalue(例如转发的右值引用)时,a.b的结果也是一个exvalue(即can被转移)。另请注意,std::forwardstd::move不会自行执行移动,它们只是强制转换。因此,在代码中从t移动两次是没有风险的。