请考虑以下代码段:
#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
}
为什么每个调用都构造相应的输出?大括号的数量如何影响统一初始化?括号删除如何影响所有这些?
答案 0 :(得分:15)
{a}
具有用于初始化const A&
参数(临时)的完全匹配等级,该参数胜过用户定义的转换B(const A&)
, {a}
的实现。 在C ++ 14中添加了此规则,以解决列表初始化中的歧义(以及对聚合的调整)。
请注意,名义上的临时性是从未创建:在重载解析选择f(const A&)
之后,引用就是initialized to refer to a
,而对于can apply的解释也是multiple user-defined conversions可复制的类型。
const A&
或A
的构造函数初始化B
参数(如上),因此调用是模棱两可的。 apoc.periodic.iterate
的形式重复调用复制构造函数(此处为A(const A&)
),而不是允许每个级别的重载解析进行一次此类转换。因此,在第二种情况下,最外面的花括号必须将B
中初始化的A
中的{{a}}
初始化为(允许)。 (大括号的中间层可以初始化B
,但是将其复制到外层是被禁止的,没有其他尝试初始化的方法。)不涉及括号删除-我们不知道允许使用的最外面的目标类型。