std :: move实现

时间:2011-09-08 13:17:47

标签: c++ std c++11 move-constructor

我从microsoft

获得了下一个片段
template <typename T> struct RemoveReference {
     typedef T type;
};

template <typename T> struct RemoveReference<T&> {
     typedef T type;
};

template <typename T> struct RemoveReference<T&&> {
     typedef T type;
};

template <typename T> typename RemoveReference<T>::type&& Move(T&& t) {
    return t;
}

...

remote_integer x = frumple(5);
remote_integer&& x1 = Move(x);

我得到一个错误“错误C2440:'return':无法从'remote_integer'转换为'remote_integer&amp;&amp;'”

编译器中发生了哪些变化?使用std :: move一切顺利。

1 个答案:

答案 0 :(得分:3)

Move不起作用的原因是因为t总是左值(即使T&&解析为int&& })。即使它看起来很奇怪,但命名的右值引用确实是左值。

Move返回时,您尝试将左值隐式绑定到右值引用,这是标准(第8.5.3节)禁止的。如评论中所述,您必须明确地将t强制转换为右值参考。

标准的相关部分是§5/ 4和§5/ 5,但是我将引用注释§5/ 6,它总结得很好:

  

通常,此规则的作用是命名的右值引用   被视为左值和对象的未命名右值引用   被视为xvalues;对函数的右值引用被视为   是否命名左值。

确实正确实施:

template <typename T>
typename std::remove_reference<T>::type&& move(T&& t)
{
  return static_cast<typename std::remove_reference<T>::type&&>(t);
}

据我记忆,此代码曾在之前的草稿中有效。但由于规则已经改变,你必须立即提供显式转换(同样适用于std :: forward)。