为啥没有 _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&amp;。由于引用折叠规则,_Ty&amp;&amp; 仍将是 int&amp;,因此您需要先删除引用以获取 int,然后才能使其成为右值引用。

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

例如move(a1) 推导出_Tyint&amp;,而move(42) 推导出_Tyint

顺便说一句:我猜你是从编译器的标准库中获取的代码 --- 用前导下划线和大写字母 _Like 装饰的名称 _Like _This 是为编译器和标准库实现保留的。

【讨论】:

谢谢。我很感激。但想知道为什么我需要取消注释代码?如果 _remove_reference 的目的是将它们转换为 T,我为什么需要那些模板专业化版本? 专业化是_Remove_reference 的工作方式。主模板匹配任何东西,并返回相同的类型,所以_Remove_reference&lt;int&gt;::type 就是int。引用的部分特化执行引用删除。 _Remove_reference&lt;int&amp;&gt; 匹配第一个部分特化,因此使用它代替主模板。 在这个专业化中_Ty 就是int(所以_Ty&amp; 就是int&amp;),所以_Remove_reference&lt;int&amp;&gt;::typeint 的类型定义。 关于引用折叠,请参阅thbecker.net/articles/rvalue_references/section_08.html。事实上,从第 1 页开始,整篇文章都值得一读。从头开始阅读以了解事物的上下文。

以上是关于为啥没有 _Remove_reference 时 std::move() 不起作用?的主要内容,如果未能解决你的问题,请参考以下文章

为啥 pytest 在测试模型创建时会抛出“AttributeError:'NoneType'对象没有属性'_meta'”错误?

为啥使用@IBAction func时UI没有及时更新?

当查询找不到用户时,为啥页面没有重定向?

为啥我的oracle目录下没有client_1文件夹?

为啥我不能将 __getattr__ 与 Django 模型一起使用?

为啥切换语言环境时我的会话没有加载?