c++arraysc++14overloadingbraced-init-list

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


Here is a demonstrative program where there are declared two functions that both accept a 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;
}

As it is seen the first function declaration is

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

and the second function declarations is

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

And the function call expression is

f( { 1, 2, 3 } );

Trying to compile this program using the compiler C++14 (gcc 8.3) at www,ideone.com I get the error

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

Is the program incorrect?


Solution

  • The program is correct. It is a bug of the compiler.

    According to the C++ 14 Standard (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.

    Thus according to the quote the overloaded function

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

    will be called.