Why are the following overloaded function calls ambiguous?? With the compile error:
call of overloaded 'test(long int)' is ambiguous,candidates are: void test(A)| void test(B)|
The code:
class A
{
public:
A(int){}
A(){}
};
class B: public A
{
public:
B(long){}
B(){}
};
void test(A a)
{
}
void test(B b)
{
}
void main()
{
test(0L);
return;
}
You got an error because overload resolution has to choose from two equally viable functions (both have user-defined conversions). Function overload resolution is a very complicated subject. For more details on the overload resolution see e.g. this recent lecture by Stephan T. Lavavej. It's generally best to make single-argument constructors explicit
, and then to call your function with an explicit constructor argument.
test(0L)
is not an exact match to any overload because there is no overload test(long)
. The two overloads you provided both have user-defined conversions on their arguments, but the compiler considers them equally viable. The A
overload has to do a standard conversion (long to int) followed by a user-defined conversion (int to A), and the B
overload a user-defined conversion (long to B). But both are implicit user-defined conversion sequences.
How are these ranked? The Standard says in 13.3.3.2 Ranking implicit conversion sequences [over.ics.rank]
Standard conversion sequence S1 is a better conversion sequence than standard conversion sequence S2 if S1 is a proper subsequence of S2
These type of tie-breaking e.g. apply if A would be a derived class from B (or vice versa). But here neither conversion sequence is a subsequence of the other. Therefore they are equally viable and the compiler cannot resolve the call.
class A
{
public:
explicit A(int){}
A(){}
};
class B: public A
{
public:
explicit B(long){}
B(){}
};
void test(A a)
{}
void test(B b)
{}
int main()
{
test(A(0L)); // call first overload
test(B(0L)); // call second overload
return 0;
}
NOTE: it's int main()
, not void main()
.