0

我从微软那里得到了下一个片段

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 &&'”

编译器发生了什么变化?使用 std::move 一切顺利。

4

1 回答 1

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)。

于 2011-09-08T17:21:38.387 回答