C++ 在两个都具有数组引用类型参数的函数之间选择重载函数

C++ 在两个都具有数组引用类型参数的函数之间选择重载函数,c++,arrays,c++14,overloading,braced-init-list,C++,Arrays,C++14,Overloading,Braced Init List,这里是一个演示程序,其中声明了两个函数,它们都接受对数组的引用 #include <iostream> void f( const int ( &a )[5] ) { std::cout << "void f( const int ( &a )[5] )\n"; } void f( const int ( &a )[6] ) { std::cout << "void f( const i

这里是一个演示程序,其中声明了两个函数,它们都接受对数组的引用

#include <iostream>

void f( const int ( &a )[5] )
{
    std::cout << "void f( const int ( &a )[5] )\n";
}

void f( const int ( &a )[6] )
{
    std::cout << "void f( const int ( &a )[6] )\n";
}

int main() 
{
    f( { 1, 2, 3 } );
    
    return 0;
}
第二个函数声明是

void f( const int ( &a )[6] );
函数调用表达式是

f( { 1, 2, 3 } );
试图使用编译器
C++14(gcc 8.3)
在www.ideone.com上编译这个程序时,我得到了错误

prog.cpp:15:17: error: call of overloaded ‘f(<brace-enclosed initializer list>)’ is ambiguous
  f( { 1, 2, 3 } );
                 ^
prog.cpp:3:6: note: candidate: ‘void f(const int (&)[5])’
 void f( const int ( &a )[5] )
      ^
prog.cpp:8:6: note: candidate: ‘void f(const int (&)[6])’
 void f( const int ( &a )[6] )
prog.cpp:15:17:错误:重载“f()”的调用不明确
f({1,2,3});
^
程序cpp:3:6:注:候选:“void f(const int(&)[5])”
空f(常数整数(&a)[5])
^
程序cpp:8:6:注:候选者:“void f(const int(&)[6])”
空f(常数整数(&a)[6])

程序不正确吗?

程序正确。这是编译器的一个bug

根据C++ 14标准(133.3.2排序隐式转换序列)

3相同形式的两个隐式转换序列 不可区分的转换序列,除非满足以下条件之一 规则适用于:

(3.1)-列表初始化序列L1是更好的转换 序列大于列表初始化序列L2,如果

(3.1.2)-L1转换为“N1 T阵列”类型,L2转换为 “N2 T阵列”,N1比N2小,即使其中一个 否则,本款中的规则将适用

因此,根据引号,重载函数

void f( const int ( &a )[5] );

将被调用。

程序正确。这是编译器的一个bug

根据C++ 14标准(133.3.2排序隐式转换序列)

3相同形式的两个隐式转换序列 不可区分的转换序列,除非满足以下条件之一 规则适用于:

(3.1)-列表初始化序列L1是更好的转换 序列大于列表初始化序列L2,如果

(3.1.2)-L1转换为“N1 T阵列”类型,L2转换为 “N2 T阵列”,N1比N2小,即使其中一个 否则,本款中的规则将适用

因此,根据引号,重载函数

void f( const int ( &a )[5] );

将被调用。

某些编译器可能会在

f({1,2,3})

对函数f的调用是不明确的。但是程序应该编译。
它将调用重载函数
void f(const int(&a)[5])只要函数调用包含长度数组某些编译器可能会在

f({1,2,3})

对函数f的调用是不明确的。但是程序应该编译。 它将调用重载函数
void f(const int(&a)[5])只要函数调用包含长度数组
void f( const int ( & )[5] ){}