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

问题描述

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

#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,3 } );

尝试在 www,ideone.com 上使用编译器 C++14 (gcc 8.3) 编译此程序时出现错误

prog.cpp:15:17: error: call of overloaded ‘f(<brace-enclosed initializer list>)’ is ambiguous
  f( { 1,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 隐式转换序列)

3 两个相同形式的隐式转换序列是 不可区分的转换序列,除非下列情况之一 适用规则:

(3.1) — 列表初始化序列 L1 是更好的转换 序列比列表初始化序列 L2 如果

(3.1.2) — L1 转换为类型“N1 T 的数组”,L2 转换为类型 “N2 T 的数组”,并且 N1 小于 N2,即使其中一个 否则将适用本段中的规则。

因此根据引用重载函数

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

将被调用。