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

Posted

技术标签:

【中文标题】在两个函数之间选择一个重载函数,这两个函数都有一个数组引用类型的参数【英文标题】:Selecting an overloaded function between two functions that both have a parameter of the type reference to an array 【发布时间】:2021-08-12 00:54:03 【问题描述】:

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

#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,ideone.com 上的编译器 C++14 (gcc 8.3) 编译此程序我收到错误

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] )

程序不正确吗?

【问题讨论】:

【参考方案1】:

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

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

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

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

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

因此根据引用重载函数

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

将被调用。

【讨论】:

【参考方案2】:

一些编译器可能会在

处给出警告

f( 1, 2, 3 );

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

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

【讨论】:

以上是关于在两个函数之间选择一个重载函数,这两个函数都有一个数组引用类型的参数的主要内容,如果未能解决你的问题,请参考以下文章

如何实现JS函数的重载

[ C++ ] C++类与对象(中) 类中6个默认成员函数 -- 运算符重载

vc9 和 gcc 之间的不同析构函数行为

简单的自绘CListBox,重载虚MeasureItem和DrawItem这两个虚函数

在两个构造函数之间进行选择的 RAII 方式

条款21 重载与重写并不相同