std::move 实现

发布于 2024-12-03 08:17:01 字数 806 浏览 1 评论 0原文

我从 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 &&'"

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

I got next snippet from 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);

and i get an error "error C2440: 'return' : cannot convert from 'remote_integer' to 'remote_integer &&'"

something changed in compilers? With std::move all goes right.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

痴情 2024-12-10 08:17:01

Move 不起作用的原因是 t 始终是 左值(即使当 T&&例如,解析为 int&&)。尽管看起来很奇怪,命名的右值引用确实是左值。

Move 返回时,您尝试将左值隐式绑定到右值引用,这是标准 (§8.5.3) 所禁止的。正如评论中所指出的,您必须显式地将 t 转换为右值引用。

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

一般来说,这条规则的作用是命名右值引用
被视为左值,并且对对象的未命名右值引用是
视为 x 值;对函数的右值引用被视为
左值,无论是否命名。

正确的实现确实是:

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

据我记得,这段代码在早期的草稿中曾经有效。但由于规则已更改,您现在必须提供显式强制转换(同样适用于 std::forward)。

The reason your Move doesn't work, is because t is always lvalue (even when T&& resolves to, say, int&&). Even though it might seem weird, named rvalue references are indeed lvalues.

When returning from your Move, you attempt to implicitly bind lvalue to rvalue reference, which is forbidden by standard (§8.5.3). As noted in the comments, you have to cast t explicitly to rvalue reference.

Relevant parts of standard are §5/4 and §5/5, but I'm going to quote note §5/6, which sums this nicely:

In general, the effect of this rule is that named rvalue references
are treated as lvalues and unnamed rvalue references to objects are
treated as xvalues; rvalue references to functions are treated as
lvalues whether named or not.

Correct implementation is indeed:

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

As far as I remember, this code used to be valid in earlier drafts. But since the rules have changed, you have to provide explicit cast now (same applies to std::forward).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文