【问题标题】:Conversion operator in direct-initialization直接初始化中的转换运算符
【发布时间】:2019-11-03 12:52:15
【问题描述】:

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】:

您是正确的,在执行A a(b); 时只考虑A 的构造函数。 [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&&)

【讨论】:

  • 感谢您的更正,我已删除我的答案,因为这是正确的段落
  • 难道不会考虑(和首选)移动构造函数,因为B 可以转换为prvalue A
  • @0x499602D2 是的。忘记了移动构造函数。答案已更新。
猜你喜欢
  • 1970-01-01
  • 2020-01-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-12-15
  • 1970-01-01
  • 1970-01-01
  • 2020-02-08
相关资源
最近更新 更多