类中移动构造函数的位置/顺序很重要?与移动构造函数结合使用的模板化强制转换运算符

Posted

技术标签:

【中文标题】类中移动构造函数的位置/顺序很重要?与移动构造函数结合使用的模板化强制转换运算符【英文标题】:Position/Order of move constructor within class matters? Templated cast operator in conjunction with move constructor 【发布时间】:2012-09-11 07:29:58 【问题描述】:

这看起来像一个编译器错误,但案例是如此简单我有点怀疑,所以我正在寻找一个确认。 VS2010 和 VS2012 均可重现。 下面的示例无法编译。给出此错误:

错误 1 ​​错误 C2440:“类型转换”:无法从 'ConvertibleToAny' 到 'OtherType<_ty>' test.cpp 40

如果将移动构造函数OtherType(ThisType &amp;&amp;)的位置移动到构造函数OtherType( int )之上,它会突然编译。

#include "stdafx.h"
#include <string>

using namespace std;

template<class _Ty>
struct OtherType

  typedef OtherType<_Ty>  ThisType;

  OtherType()
   
  

  OtherType( int )
   
  

  // The move constructor
  OtherType(ThisType && )
  
  
;

struct ConvertibleToAny
    
  template <class AnyType>
  operator AnyType()
  
    return AnyType();
  
;

int _tmain(int argc, _TCHAR* argv[])


  (OtherType<wstring>) ConvertibleToAny();

    return 0;

这是一个错误还是这是预期的行为?如果符合预期,请引用 C++11 规范中的相关段落。 我已经在 Microsoft Connect click here to open it 上将此作为错误发布。

【问题讨论】:

“如果将移动构造函数的位置移动到 [other] 构造函数之上” - 如果这确实是解决方案,那么这绝不是预期的行为。 是的,我也是这么想的,但是这个案子太简单了,我觉得有点难以相信它只是滑倒了,而且是一个错误。 @EddieBytes MSVC 中的错误是 move c-tor 修复问题。根据 C++ 标准,您的代码不正确。 @ForEveR 对不起,我不确定我是否理解。能详细点吗? 注意:构造函数的位置/顺序等无关紧要。您看到的行为是 MSVC compiler not compiling templates correctly 的结果。它有助于使用更好的编译器(例如 gcc 或 clang)来解决这些类型的问题。 【参考方案1】:

你的表情

(OtherType<wstring>) ConvertibleToAny()

是从临时用户定义类型到用户定义类型的一元显式转换 (5.4),按照 5.4:4 解释为 static_cast:

static_cast<OtherType<wstring>>(ConvertibleToAny())

根据 5.2.9:4 具有初始化临时变量t 的有效性:

OtherType<wstring> t(ConvertibleToAny())

这是直接初始化 (8.5:15),因此 (8.5:16) OtherType 的所有单参数构造函数都根据 13.3.1.3 中的规则参与重载解析。

在 13.3:2 之后,int 和 move 构造函数都可用并且在 13.3.2 中是可行的,因此对于单个参数,我们有两个可能的隐式转换序列 (13.3.3.1):

ConvertibleToAny [temporary] -> int
ConvertibleToAny [temporary] -> OtherType<wstring> &&

在 13.3.3.1.2 之后,这些序列之间没有排序,因此没有最佳可行函数,重载决议失败 (13.3:3),并且程序格式错误。


如果将转换函数 (12.3.2) 设为 explicit (12.3.2:2),则仅考虑直接初始化。尽管隐式转换序列 (13.3.3.1) 是隐式转换 (4:3),因此涉及复制初始化,但 12.3.2:2 示例中标准的意图显然是在这种情况下应考虑显式转换函数;因此,重载解决方案似乎再次失败。

【讨论】:

以上是关于类中移动构造函数的位置/顺序很重要?与移动构造函数结合使用的模板化强制转换运算符的主要内容,如果未能解决你的问题,请参考以下文章

移动构造函数和移动赋值与拷贝构造函数和赋值构造函数的比较

C++11移动构造函数详解

为啥在我的代码中调用复制构造函数而不是移动构造函数?

C#的构造函数在基类和父类中执行顺序

在构造函数中移动 yandex 映射控制器

是否有一个总括术语来对“从头开始”构造函数进行分组,将它们与复制和移动构造函数区分开来?