我的问题涉及这个非常简单且简短的代码,其中尝试在接受数组引用参数的两个非模板函数之间进行重载解析。该问题已在其他地方发布,但在模板扣除上下文中。代码如下:
#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 ofX
" 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
.
这个转换顺序不关注数组长度。两个函数重载都给出了一个隐式转换序列,即恒等转换:都引用了 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/