2

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

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

尝试使用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] )

程序不正确吗?

4

2 回答 2

3

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

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

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

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

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

因此根据引用重载函数

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

将被调用。

于 2021-05-23T12:41:05.150 回答
1

一些编译器可能会在

f( { 1, 2, 3 } );

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

void f( const int ( & )[5] ){}
于 2021-05-23T13:20:37.540 回答