为什么没有_Remove_reference,std :: move()不起作用?

时间:2011-11-29 07:28:22

标签: c++ c++11 rvalue-reference

如你所知,

_Remove_reference存在于转换T&到T或T&&到T。

我以一种俏皮的心情制作了以下代码,它根本不符合我的预期,但不知道为什么。

template<class _Ty>
struct _Remove_reference
{   // remove reference
    typedef _Ty _Type;
    static void func(){ cout << "1" << endl; } 
};

// template<class _Ty>
// struct _Remove_reference<_Ty&>
// {    // remove reference
//  typedef _Ty _Type;
//  static void func(){ cout << "2" << endl; }
// };
// 
// template<class _Ty>
// struct _Remove_reference<_Ty&&>
// {    // remove rvalue reference
//  typedef _Ty _Type;
//  static void func(){ cout << "3" << endl; }
// };

template<class _Ty> inline
    typename _Remove_reference<_Ty>::_Type&&
    move(_Ty&& _Arg)
{   // forward _Arg as movable
    typename _Remove_reference<_Ty>::func();
    return ((typename _Remove_reference<_Ty>::_Type&&)_Arg);
}

int main(){
    int a1= 3;
    int&& a2 = move(a1); // can't convert the a1 to int&&
    return 0;
}

我想这都是关于参考折叠规则和模板参数推导但我很困惑。我对此的好奇心必须让我睡不着觉。

提前致谢。

1 个答案:

答案 0 :(得分:8)

鉴于

template<class _Ty> inline
typename _Remove_reference<_Ty>::_Type&&
move(_Ty&& _Arg)

当您执行move(a1)时,_Ty被推断为int&。由于参考折叠规则,_Ty&&因此仍然是int&,因此您需要删除引用以获取int,然后才能使其成为右值参考。

这是模板参数推导规则的特例。如果你有一个T&&函数参数,其中T是一个模板参数,那么如果你将一个左值(即命名对象或左值引用)传递给函数,那么T是推导为X&,其中X是左值对象的类型。如果您将rvalue(临时或右值引用)传递给函数,则T只是推导为X

e.g。 move(a1)_Ty推断为int&,而move(42)推导_Tyint

BTW:我猜你从编译器的标准库中获取了这个代码 - 用前导下划线和大写字母装饰的名字_Like _这是为编译器和标准库实现保留的。