支撑数如何影响均匀初始化?

use*_*080 31 c++ language-lawyer uniform-initialization c++11 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
}
Run Code Online (Sandbox Code Playgroud)

为什么每个调用都会编写相应的输出?支撑数如何影响均匀初始化?支撑精益如何影响这一切?

Dav*_*ing 17

过载分辨率很有趣.

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

    请注意,永远不会创建名义临时:在重载决策选择之后f(const A&),引用只是初始化以引用a,并且即使对于非可复制类型,此解释也适用.

  2. 允许将const A&参数(如上所述)初始化为构造函数的任何一个 AB,因此调用是不明确的.
  3. A(const A&)禁止重复调用复制构造函数(此处)作为多个用户定义的转换 -而不是在每个重载分辨率级别允许一次此类转换.因此,最外面的大括号必须在第二种情况下BA初始化的{{a}}as(允许)初始化a .(大括号的中间层可以初始化a B,但是禁止使用外层复制它,并且没有其他任何东西可以尝试初始化.)
  4. 每一种解释都涉及到这种不允许的额外转换.

不涉及支撑锥度 - 我们不知道允许它的最外层目标类型.