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一切顺利。
答案 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)。