这实际上是模棱两可的吗?
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 正确拒绝。
所以我知道代码中的大括号不仅仅意味着 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 toX
, the implicit conversion sequence is the worst conversion necessary to convert an element of the list toX
, 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 正确拒绝。