大括号的数量如何影响统一初始化?
How does the number of braces affect uniform 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
}
为什么每次调用都会伪造相应的输出?大括号的数量如何影响统一初始化?大括号省略如何影响这一切?
Overload resolution这样很好玩
{a}
具有 完全匹配 等级用于初始化(临时) const A&
参数,这胜过用户定义的转换 B(const A&)
作为 {a}
的实现。此规则已 添加到 C++14 中以解决列表初始化中的歧义(以及聚合调整)。
请注意,名义上的临时对象 从未创建 :在重载解析选择 f(const A&)
之后,即使对于不可复制的类型,引用也只是 initialized to refer to a
, and this interpretation can apply。
- 允许为
A
或 B
的构造函数初始化一个 const A&
参数(如上所述),所以调用不明确。
- 禁止像 multiple user-defined conversions 那样重复调用复制构造函数(此处为
A(const A&)
)——而不是允许每个级别的重载决策进行一次这样的转换。因此最外层的大括号必须从 A
初始化一个 B
,从 {{a}}
初始化为第二种情况下的(允许)。 (中间层大括号可以初始化一个B
,但是和外层一起复制是被禁止的,没有别的东西可以尝试初始化。)
- 每个解释都涉及这种不允许的额外转换。
不涉及大括号省略——我们不知道允许它的最外层目标类型。
考虑以下代码片段:
#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
}
为什么每次调用都会伪造相应的输出?大括号的数量如何影响统一初始化?大括号省略如何影响这一切?
Overload resolution这样很好玩
{a}
具有 完全匹配 等级用于初始化(临时)const A&
参数,这胜过用户定义的转换B(const A&)
作为{a}
的实现。此规则已 添加到 C++14 中以解决列表初始化中的歧义(以及聚合调整)。请注意,名义上的临时对象 从未创建 :在重载解析选择
f(const A&)
之后,即使对于不可复制的类型,引用也只是 initialized to refer toa
, and this interpretation can apply。- 允许为
A
或B
的构造函数初始化一个const A&
参数(如上所述),所以调用不明确。 - 禁止像 multiple user-defined conversions 那样重复调用复制构造函数(此处为
A(const A&)
)——而不是允许每个级别的重载决策进行一次这样的转换。因此最外层的大括号必须从A
初始化一个B
,从{{a}}
初始化为第二种情况下的(允许)。 (中间层大括号可以初始化一个B
,但是和外层一起复制是被禁止的,没有别的东西可以尝试初始化。) - 每个解释都涉及这种不允许的额外转换。
不涉及大括号省略——我们不知道允许它的最外层目标类型。