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

问题描述 投票:0回答:1

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
}
c++ constructor language-lawyer implicit-conversion overload-resolution
1个回答
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&&)

© www.soinside.com 2019 - 2024. All rights reserved.