开发者

std::move realisation

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.


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

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜