2011-09-08 64 views
0

我下一个片段从microsoft的std ::移动实现

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: '回归':无法从 'remote_integer' 转换到'remote_integer & &''

在编译器中有所改变吗?随着std :: move一切顺利。

+1

移动只接受一个右值,x是一个左值。你必须使用stdmove(小写)。 – RedX

+0

http://social.msdn.microsoft.com/Forums/en-US/vs2010ctpcpp/thread/ab120b3c-4ecf-4a0d-8f64-f24925ac39a9/ - Jonathan Caves(Visual C++编译器团队)编写实现std :: move和我的Move一样。并移动我从微软网站抓住,在问题的链接?那里没有问题,但是在VC10中它不起作用。 – Yola

+0

模板类型名称RemoveReference ::类型&&移动(T && T){ 回报(RemoveReference ::类型&&)t; } - 现在一切工作正常,一些与类型转换这里 – Yola

回答

3

的原因,你的Move行不通,是因为t总是左值(即使T&&解决,比方说,int&&)。即使它看起来很奇怪,命名右值引用确实是左值。

Move返回时,试图将左值隐式绑定到右值引用,这是标准(第8.5.3节)所禁止的。正如评论中指出的那样,你必须明确地将t转换为右值引用。

标准的相关部分中§5/ 4和§5/ 5,但我要引用笔记§5/ 6,其中总结这很好:

一般情况下,这样的效果规则是名为右值引用 被视为左值,而对对象的未命名右值引用则被视为xvalue;对函数的右值引用被视为 左值是否被命名。

正确的执行确实是:

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

据我记得,用这个代码是在早期草稿有效。但是,由于规则发生了变化,现在必须提供明确的演员表(同样适用于std :: forward)。