为啥没有 _Remove_reference 时 std::move() 不起作用?
Posted
技术标签:
【中文标题】为啥没有 _Remove_reference 时 std::move() 不起作用?【英文标题】:Why does std::move() not work without _Remove_reference?为什么没有 _Remove_reference 时 std::move() 不起作用? 【发布时间】:2011-11-29 07:28:21 【问题描述】:_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】:给定
template<class _Ty> inline
typename _Remove_reference<_Ty>::_Type&&
move(_Ty&& _Arg)
当您执行move(a1)
时,_Ty
被推断为int&
。由于引用折叠规则,_Ty&&
仍将是 int&
,因此您需要先删除引用以获取 int
,然后才能使其成为右值引用。
这是模板参数推导规则的一个特例。如果你有一个函数参数是T&&
,其中T
是一个模板参数,那么如果你将一个左值(即命名对象或左值引用)传递给函数,那么T
被推导出为X&
,其中X
是左值对象的类型。如果您将右值(临时或右值引用)传递给函数,则 T
将被推断为 X
。
例如move(a1)
推导出_Ty
为int&
,而move(42)
推导出_Ty
为int
。
顺便说一句:我猜你是从编译器的标准库中获取的代码 --- 用前导下划线和大写字母 _Like 装饰的名称 _Like _This 是为编译器和标准库实现保留的。
【讨论】:
谢谢。我很感激。但想知道为什么我需要取消注释代码?如果 _remove_reference 的目的是将它们转换为 T,我为什么需要那些模板专业化版本? 专业化是_Remove_reference
的工作方式。主模板匹配任何东西,并返回相同的类型,所以_Remove_reference<int>::type
就是int
。引用的部分特化执行引用删除。 _Remove_reference<int&>
匹配第一个部分特化,因此使用它代替主模板。 在这个专业化中,_Ty
就是int
(所以_Ty&
就是int&
),所以_Remove_reference<int&>::type
是int
的类型定义。
关于引用折叠,请参阅thbecker.net/articles/rvalue_references/section_08.html。事实上,从第 1 页开始,整篇文章都值得一读。从头开始阅读以了解事物的上下文。以上是关于为啥没有 _Remove_reference 时 std::move() 不起作用?的主要内容,如果未能解决你的问题,请参考以下文章
为啥 pytest 在测试模型创建时会抛出“AttributeError:'NoneType'对象没有属性'_meta'”错误?