这是
CWG 2327
:
举个例子:
struct Cat {};
struct Dog { operator Cat(); };
Dog d;
Cat c(d);
这是11.6[dcl.init]第17.6.2条:
否则,如果初始化是直接初始化,或者如果是复制初始化,而源类型的cv非限定版本与目标类型的类或其派生类是同一类,则将考虑构造函数。枚举适用的构造函数(16.3.1.3[over.match.ctor]),并通过重载解析(16.3[over.match])选择最佳的构造函数。调用所选的构造函数以初始化对象,并将初始值设定项表达式或表达式列表作为其参数。如果没有应用构造函数,或者重载解析不明确,则初始化格式错误。
重载解析选择cat的move构造函数。根据11.6.3[dcl.init.ref]项目符号5.2.1.2,初始化构造函数的cat&参数将导致临时的。这就排除了在本案中删除副本的可能性。
这似乎是一个疏忽的措辞变化,以保证副本删除。在这种情况下,我们应该同时考虑构造函数和转换函数,就像复制初始化一样,但是我们需要确保这不会引入任何新的问题或歧义。
我相信clang实现了这个隐含的更改(因此认为转换函数更匹配),而gcc没有(因此从来没有真正考虑转换函数)。
根据标准,GCC是正确的。