大括号的数量如何影响统一初始化?

时间:2019-02-03 15:33:12

标签: c++ c++11 language-lawyer uniform-initialization list-initialization

请考虑以下代码段:

#include <iostream>

struct A {
  A() {}
  A(const A&) {}
};

struct B {
  B(const A&) {}
};

void f(const A&) { std::cout << "A" << std::endl; }
void f(const B&) { std::cout << "B" << std::endl; }

int main() {
  A a;
  f(   {a}   ); // A
  f(  {{a}}  ); // ambiguous
  f( {{{a}}} ); // B
  f({{{{a}}}}); // no matching function
}

为什么每个调用都构造相应的输出?大括号的数量如何影响统一初始化?括号删除如何影响所有这些?

1 个答案:

答案 0 :(得分:15)

Overload resolution很有趣。

  1. {a}具有用于初始化const A&参数(临时)的完全匹配等级,该参数胜过用户定义的转换B(const A&){a}的实现。 在C ++ 14中添加了此规则,以解决列表初始化中的歧义(以及对聚合的调整)。

    请注意,名义上的临时性是从未创建:在重载解析选择f(const A&)之后,引用就是initialized to refer to a,而对于can apply的解释也是multiple user-defined conversions可复制的类型。

  2. 允许为 const A&A的构造函数初始化B参数(如上),因此调用是模棱两可的。
  3. 禁止以apoc.periodic.iterate的形式重复调用复制构造函数(此处为A(const A&)),而不是允许每个级别的重载解析进行一次此类转换。因此,在第二种情况下,最外面的花括号必须将B中初始化的A中的{{a}}初始化为(允许)。 (大括号的中间层可以初始化B,但是将其复制到外层是被禁止的,没有其他尝试初始化的方法。)
  4. 每种解释都涉及不允许的额外转换。

不涉及括号删除-我们不知道允许使用的最外面的目标类型。