c++ - Initializer_list 作为非模板上下文中数组引用参数的参数

标签 c++ c++11 initializer-list overload-resolution

我的问题涉及这个非常简单且简短的代码,其中尝试在接受数组引用参数的两个非模板函数之间进行重载解析。该问题已在其他地方发布,但在模板扣除上下文中。代码如下:

#include <iostream>

void foo ( const int (&x) [3] ) { std::cout << "3\n"; }
void foo ( const int (&x) [2] ) { std::cout << "2\n"; }

int main()
{
    foo({1,2,3});
}

g++ 4.8.3 编译此代码,选择第一个函数作为(我想)唯一可行的, 而 clang 3.4 没有编译它,说对 foo 的调用是模棱两可的(为什么?)。

哪个编译器做正确的事?

即使删除第二个重载,clang 也不会编译代码:似乎根本不接受 initializer_list 来初始化数组引用。

这是 buggy 吗?

最佳答案

我认为虽然 GCC 的行为更有用,但对于 C++11 来说正确的是 clang 的行为:

13.3.3.1.5 List-initialization sequence [over.ics.list]

2 If the parameter type is std::initializer_list<X> or "array of 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.

这个转换顺序不关注数组长度。两个函数重载都给出了一个隐式转换序列,即恒等转换:都引用了 int 的数组。 , 函数参数中的每个元素都是 int .

然后重载解析会看到两次身份转换,虽然标准确实有一些异常(exception)来解决同等等级转换的冲突,但没有一个注意数组的长度:

13.3.3.2 Ranking implicit conversion sequences [over.ics.rank]

3 Two implicit conversion sequences of the same form are indistinguishable conversion sequences unless one of the following rules applies:

后面是一个根本没有提到数组的列表。

Jonathan Wakely 指出,这已经改变了。您的问题正是促使该更改的原因,相应的 DR 是 #1307 .在 C++14 中,您的代码有效,但在 C++11 中无效。

关于c++ - Initializer_list 作为非模板上下文中数组引用参数的参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27397701/

相关文章:

c++ - cout 流变坏

c++ - 适合在线嵌入的SVM库

c++ - 函数模板重载clang++

c++ - 限制可变参数函数模板仅接受一个可变参数类模板的嵌套可变参数类模板的变体?

c++ - lambda 函数的类型

c++ - 使用静态成员函数初始化初始化列表中的常量成员变量有什么问题吗?

c++ - 有没有办法在编译时检查 std::initializer_list 参数的数量?

c++ - 如何删除 QPlainTextEdit 及其内容之间的空格?

c++ - 如何制作图形用户界面?

c++ - 什么是段错误?我该如何解决?