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):
||=== 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)) ===|
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.)