这实际上是不明确的吗?

时间:2016-08-05 18:03:26

标签: c++ nested initializer-list ambiguous list-initialization

所以我知道代码中的大括号不仅仅意味着initializer_listWhat Is a Curly-Brace Enclosed List If Not an intializer_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 }),显然会调用1 st 。如果我拨打foo({ { 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 9 } }),显然会调用2 nd

但是如果我打电话怎么办?

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

那些嵌套大括号int - 初始化器或initializer_list<int>初始化器吗? gcc says it's ambiguous但是,如果您使用该代码并在http://webcompiler.cloudapp.net/上运行它,Visual Studio说它只是构建initializer_list<int>。谁是对的?这里应该有默认值吗?

1 个答案:

答案 0 :(得分:6)

规则在[over.ics.list]

  

否则,如果参数类型为std::initializer_list<X>并且初始化列表的所有元素都可以隐式转换为X,则隐式转换序列是转换列表元素所需的最差转换到X,或者如果初始化列表没有元素,则为身份转换。

在两个重载中,最糟糕的转换是身份转换。所以我们有两个带有秩同一性的隐式转换序列。 [over.match.best]中有一条规则优先选择std::initializer_list<X>列表初始化,因此std::initializer_list<int>优先于int {1},但有Developer options没有任何迹象表明这条规则应该递归应用。

由于无法消除两个转换序列的歧义,因此调用不明确。 gcc和clang是正确的拒绝。