【问题标题】:Why conversion can involve two user defined conversion function/constructor?为什么转换可以涉及两个用户定义的转换函数/构造函数?
【发布时间】:2018-02-21 22:00:25
【问题描述】:

我试图了解标准中的哪些规则证明下面的编译器行为是正确的。所以这个问题只是为了得到语言律师的答案。

让我们考虑这两个类:

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

以下代码编译:

 B b;
 A a{b};

变量a 直接由b 初始化。根据[dlc.init]/17.6.3

否则(即,对于剩余的复制初始化情况),可以从源类型转换到目标类型或(当使用转换函数时)到其派生类的用户定义转换序列被枚举为描述在[over.match.copy]中,

我了解直接初始化过程将列出所有用户定义的转换序列,这些转换序列可以执行从B(源类型)到A(目标类型)的转换。 [over.match.copy] 说明在哪里可以找到用户定义的转换函数。

一个用户定义的转换序列只能涉及1个用户定义的转换函数或构造函数。但唯一的转换路径是调用转换构造函数A::A(int) 和转换函数B::operator int()

因此没有用户定义的转换序列允许从B 转换为A

为什么按照标准初始化A a{b};可以很好的形成?

【问题讨论】:

  • 这里只有一次转化:B -> int -> A...
  • 显式调用带有参数的构造函数不是用户定义的转换。 b 被转换为 int 并且 int 用于调用 a 的构造函数。
  • @Oliv 你看错了部分。此初始化包含在上一个项目符号中:timsong-cpp.github.io/cppwp/n4659/dcl.init#17.6.2
  • @Oliv 没问题。阅读标准可能会……令人筋疲力尽。
  • 1) “(即,对于剩余的复制初始化情况)”非常清楚地表明您在错误的项目符号中。 2)实际上,@NathanOliver 也是错误的子弹。第一个项目符号 [dcl.init]/17.1 涵盖了这一点。这里的实际初始化由[dcl.init.list]/3.6控制。

标签: c++ type-conversion language-lawyer


【解决方案1】:

格式正确,因为它使用一次转换将 B 转换为 int。然后显式调用 A 的构造函数,使用 int 作为参数。

这将是您有两个用户定义的转换的情况:

  void f( A a ) {}
  B b;
  f( b  );      

【讨论】:

  • 但标准规定只考虑用户定义的从 B 到 A 的转换序列。不是用户定义的从 B 到与 A 的构造函数匹配的参数的转换序列。
  • 答案是 NathanOliver 评论,我错过了之前适用的标准项目符号。
猜你喜欢
  • 2016-02-08
  • 2021-12-04
  • 2012-06-28
  • 2012-07-19
  • 1970-01-01
  • 1970-01-01
  • 2018-10-29
  • 1970-01-01
相关资源
最近更新 更多