在课堂上移动构造函数的位置/顺序很重要?模板化的转换操作符与移动构造函数一起使用

Edd*_*tes 3 c++ visual-studio-2010 visual-c++ c++11 visual-studio-2012

这看起来像编译器错误,但案件很简单,我有点怀疑,所以我正在寻找确认.可与VS2010和VS2012一起重现.以下示例无法编译.给出了这个错误:

错误1错误C2440:'type cast':无法从'ConvertibleToAny'转换为'OtherType <_Ty>'test.cpp 40

如果将移动构造函数的位置移动到构造函数OtherType(ThisType &&)上方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;
}
Run Code Online (Sandbox Code Playgroud)

这是一个错误还是这个预期的行为?如果是预期的,请引用C++ 11规范中的相关段落.我已将此作为Microsoft Connect中的错误发布,请单击此处将其打开.

eca*_*mur 6

你的表达

(OtherType<wstring>) ConvertibleToAny()
Run Code Online (Sandbox Code Playgroud)

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

static_cast<OtherType<wstring>>(ConvertibleToAny())
Run Code Online (Sandbox Code Playgroud)

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

OtherType<wstring> t(ConvertibleToAny())
Run Code Online (Sandbox Code Playgroud)

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

在13.3:2之后,int每个13.3.2都可以使用和移动构造函数,因此我们有两个可能的隐式转换序列(13.3.3.1)用于单个参数:

ConvertibleToAny [temporary] -> int
ConvertibleToAny [temporary] -> OtherType<wstring> &&
Run Code Online (Sandbox Code Playgroud)

在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的意图显然是在这种情况下应考虑显式转换函数; 因此,再次出现重载解析应该失败.