为什么我不能使用任意嵌套的大括号来构造大多数类?

Dav*_*one 7 c++ c++11

给出以下代码:

struct A;

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

struct A {
    A() {}
    A(B &&) {}
};
Run Code Online (Sandbox Code Playgroud)

然后我可以使用任意数量的大括号来构造Aor B

// default construct A
auto a = A{};
// default construct B, forward to A
auto b = A{{}};
// default construct A, forward to B, forward to A
auto c = A{{{}}};
// etc.
auto d = A{{{{}}}};
auto e = A{{{{{}}}}};
Run Code Online (Sandbox Code Playgroud)

同样,给定

struct C {
    C(std::initializer_list<C>) {}
};
Run Code Online (Sandbox Code Playgroud)

那么我也可以使用任意数量的大括号

// default construct C
auto f = C{};
// construct from initializer_list of one default constructed C
auto g = C{{}};
// construct from initializer_list of one C constructed from empty initializer_list
auto h = C{{{}}};
// etc.
auto i = C{{{{}}}};
auto j = C{{{{{}}}}};
Run Code Online (Sandbox Code Playgroud)

为什么同样的论点对于真正无聊的人不起作用?

struct D {
};
Run Code Online (Sandbox Code Playgroud)

或者,为了清楚起见重写:

struct D {
    D() {}
    D(D &&) {}
};
Run Code Online (Sandbox Code Playgroud)

即使在

auto k = D{{}};
Run Code Online (Sandbox Code Playgroud)

为什么这不默认构造D带有最内层大括号的 a,然后将该右值传递给 的移动构造函数D

现场观看: https: //godbolt.org/z/E763EPGh1

Igo*_*nik 6

有一种特殊情况可以排除D{{}}。这是一组非常特殊的条件,所以我想它是专门为了防止这种精确的递归而存在的。

\n
\n

[over.best.ics]/4但是,如果目标是
\n(4.1) \xe2\x80\x94 构造函数的第一个参数
\n...
\n并且构造函数 ... 是候选者
\n ... \n(4.5) \xe2\x80\x94 [over.match.list]
的第二阶段,此时初始化列表恰好有一个元素本身就是初始化列表,并且目标是构造函数的第一个参数的 class ,并且转换为或引用cv,\n不考虑用户定义的转换序列。XX X

\n
\n

D{{}}是一个列表初始化。D(D&&)构造函数由其第二阶段考虑(第一阶段查看初始化列表构造函数,如C(std::initializer_list<C>)第二个示例中所示)。但要使其可行,需要从{}到 的隐式转换D&&,并且[over.best.ics]/4会抑制它。

\n