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

Jan*_*šil 6 c++ constructor language-lawyer overload-resolution implicit-conversion

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
}
Run Code Online (Sandbox Code Playgroud)

Nat*_*ica 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. [..]的对应参数。

允许将隐式转换为bA以便A(A&&)可以调用。

  • 因为可以将B转换为prvalue A,所以也不会考虑移动构造器吗? (2认同)
  • @ 0x499602D2是的。忘记了move构造函数。答案已更新。 (2认同)