在两个函数之间选择一个重载函数,这两个函数都有一个数组引用类型的参数

Selecting an overloaded function between two functions that both have a parameter of the type reference to an array

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

#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 )[5] );

第二个函数声明是

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

函数调用表达式为

f( { 1, 2, 3 } );

尝试使用 www 上的编译器 C++14 (gcc 8.3) 编译此程序,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] )

程序有误吗?

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

根据 C++ 14 标准(13.3.3.2 Ranking implicit conversion sequences)

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

(3.1) — List-initialization sequence L1 is a better conversion sequence than list-initialization sequence L2 if

(3.1.2) — L1 converts to type “array of N1 T”, L2 converts to type “array of N2 T”, and N1 is smaller than N2, even if one of the other rules in this paragraph would otherwise apply.

因此根据引用重载函数

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

会被调用。

一些编译器可能会在

处给出警告

f( { 1, 2, 3 } );

对函数 f 的调用不明确。但程序应该编译。 只要函数调用包含长度 <=5 的数组,它就会调用重载函数 void f( const int ( &a )[5] );。 一旦你在数组中引入第 6 个元素,它就会调用 void f( const int ( &a )[6] ); 还要提及传递的参数,因为 a 在两个定义中都未使用。如果您没有使用该参数,那么以下定义也适用。

void f( const int ( & )[5] ){}