这实际上是模棱两可的吗?

Is This Actually Ambiguous?

所以我知道代码中的大括号不仅仅意味着 initializer_list

但是他们默认应该做什么?

比如我定义了一个重载函数:

void foo(const initializer_list<int>& row_vector) { cout << size(row_vector) << "x1 - FIRST\n"; }
void foo(const initializer_list<initializer_list<int>>& matrix) { cout << size(matrix) << 'x' << size(*begin(matrix)) << " - SECOND\n"; }

如果我调用 foo({ 1, 2, 3 }) 显然会调用 1st。如果我调用 foo({ { 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 9 } }) 显然会调用 2nd

但是如果我调用:

foo({ { 1 }, { 2 }, { 3 } })

那些嵌套的大括号是 int 初始化器还是 initializer_list<int> 初始化器? gcc says it's ambiguous But if you take that code and run it on http://webcompiler.cloudapp.net/ Visual Studio 说它只是构造一个 initializer_list<int>。谁是对的?这里应该有默认值吗?

规则在[over.ics.list]:

Otherwise, if the parameter type is std::initializer_list<X> and all the elements of the initializer list can be implicitly converted to X, the implicit conversion sequence is the worst conversion necessary to convert an element of the list to X, or if the initializer list has no elements, the identity conversion.

在你的两个重载中,最糟糕的必要转换是身份转换。所以我们有两个具有等级标识的隐式转换序列。 [over.match.best] 中有一条规则更喜欢 std::initializer_list<X> 的列表初始化而不是替代方案(因此 std::initializer_list<int> 优于 int {1}),但是有没有任何迹象表明该规则应该递归应用。

由于没有任何东西可以消除两个转换序列的歧义,因此调用是不明确的。 gcc 和 clang 正确拒绝。