Clang不能将支撑初始化用于用户定义的转换

时间:2015-08-21 16:13:13

标签: c++ c++11

代码如下。

struct A {
  A() {}
};

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

struct C {
  A a;
  C(B b) : a{b} {}
};

我有一个struct A,它不是可聚合构造的(因为它定义了一个构造函数)。 struct B也是如此。但它也有一个显式的用户定义转换运算符struct A。现在struct C的构造函数使用struct B,并使用它来构造struct A。与cppreference一样,转换运算符可以参与直接初始化,我认为struct C的成员初始化就是这种情况。它传递给GCC 5.2(C ++ 11)。但是它在Clang 3.6上失败了。我尝试使用C ++ 11,C ++ 14和C ++ 1z。

如果我将a{b}更改为a(b),则会传递给Clang和GCC。

我想知道这是一个Clang bug还是我误解了标准?

1 个答案:

答案 0 :(得分:1)

由于DR1467(cfr。22259),clang最近发生了变化

gcc和clang的最新版本都做了正确的事情:编译你的代码没有错误。

在成员初始化程序列表的第一轮重载解析中,A的构造函数被丢弃,因为它们不是初始化列表构造函数。

之后 [over.match.list] / p1 接管

  
      
  • 如果找不到可行的初始化列表构造函数,则重载解析   再次执行,其中候选函数都是   类T的构造函数和参数列表由   初始化列表的元素。
  •   

这次A的构造函数被考虑在内。 A的复制和移动构造函数具有足够的参数来匹配重载解析过程,并且它们不会导致任何用户定义的转换抑制,因为13.3.1.3甚至13.3.1.7(仍在Clang's code中)不适用于这些构造

因此,它们已输入重载分辨率集, [over.best.ics] 适用。