Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

C++ std::array as a parameter of overloaded function is ambiguous

I was expecting the compiler to choose which function to use, depending on the size of the array. It works properly on call funct({1,2,3});, but the others are ambiguous, why? Isn’t array<int,1> a different data type from array<int,2>, array<int,3>, and so on?

Here is my code:

#include<iostream>
#include<array>
using namespace std;
void funct(array<int,1>one)
{
    cout<<"one"<<endl;
}
void funct(array<int,2>two)
{
    cout<<"two"<<endl;
}
void funct(array<int,3>three)
{
    cout<<"three"<<endl;
}
int main()
{
    funct({1,2,3});
    funct({1,2});
    funct({1});
    return(0);
}

Here are my build messages ([redacted] is what i removed for obvious reasons):

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

||=== Build: Debug in ambiguitytest (compiler: GNU GCC Compiler) ===|
[redacted]\ambiguitytest\main.cpp||In function 'int main()':|
[redacted]\ambiguitytest\main.cpp|19|error: call of overloaded 'funct(<brace-enclosed initializer list>)' is ambiguous|
[redacted]\ambiguitytest\main.cpp|8|note: candidate: void funct(std::array<int, 2u>)|
[redacted]\ambiguitytest\main.cpp|12|note: candidate: void funct(std::array<int, 3u>)|
[redacted]\ambiguitytest\main.cpp|20|error: call of overloaded 'funct(<brace-enclosed initializer list>)' is ambiguous|
[redacted]\ambiguitytest\main.cpp|4|note: candidate: void funct(std::array<int, 1u>)|
[redacted]\ambiguitytest\main.cpp|8|note: candidate: void funct(std::array<int, 2u>)|
[redacted]\ambiguitytest\main.cpp|12|note: candidate: void funct(std::array<int, 3u>)|
||=== Build failed: 2 error(s), 0 warning(s) (0 minute(s), 0 second(s)) ===|

>Solution :

An std::array<int, N> can be initialized with a braced initializer list of any length up to N. It performs aggregate initialization and initializes the remaining elements of the array to zero.

So for both funct({1,2}); and funct({1}); multiple overload candidates are viable.

There is no rule that makes an aggregate initialization with more matching elements a better match in overload resolution, so overload resolution is ambiguous.

If you need to determine the length of the initializer list, you can use a template instead:

template<std::size_t N>
void funct(const int (&arr)[N])
{
    if(N == 1)
        cout<<"one"<<endl;
    else if(N == 2)
        cout<<"two"<<endl;
    else if(N == 3)
        cout<<"one"<<endl;
    else
        cout<<"something else"<<endl;
}

(Note that this only works with references to built-in arrays as function parameter. It doesn’t work with std::array. Built-in arrays have special deduction rules that allow this.)

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading