直接初始化中的转换运算符

时间:2019-06-20 16:34:51

标签: c++ constructor language-lawyer implicit-conversion overload-resolution

C ++ 14标准(N4296)在8.5 / 17.6.1中表示

  

如果初始化为直接初始化[...],则考虑构造函数。列举适用的构造函数,最好的   通过过载解析选择一个。 [...]如果没有构造函数   适用,或者重载解决方案不明确,初始化格式不正确。

因此,在直接初始化中,仅考虑构造函数-忽略转换函数。在以下代码中,没有适用的A构造函数,只有B的转换函数。但是,代码可以编译,为什么?

struct A{};
struct B{
    operator A(){ return A{}; }
};

int main() {
    B b;
    A a(b);  // direct-initialization
}

1 个答案:

答案 0 :(得分:7)

您是正确的,在进行A时仅考虑A a(b);的构造函数。 [over.match.ctor]/1状态

  

当直接初始化类类型的对象,从相同或派生类类型的表达式([dcl.init])的副本复制初始化或默认初始化时,重载决议会选择构造函数。对于不在复制初始化上下文中的直接初始化或默认初始化,候选函数是要初始化的对象的类的所有构造函数。对于复制初始化(包括默认初始化)在复制初始化的上下文中,候选函数是该类的所有转换构造函数([class.conv.ctor])。参数列表是初始化程序的表达式列表或赋值表达式。

强调我的

这意味着A()A(const A&)A(A&&)是候选列表。然后我们有[over.match.viable]/4

  

[...]第三,为了使F成为可行的函数,每个自变量都应存在一个隐式转换序列,该序列将该自变量转换为F。[..]

的相应参数。

这允许将b隐式转换为A,以便可以调用A(A&&)