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).
精彩评论