Consider simple code :
#include<iostream>
struct A {
operator double(){
std::cout<<"Conversion function double chosen."<<std::endl;
return 1.1;
}
operator char(){
std::cout<<"Conversion function char chosen."<<std::endl;
return 'a';
}
} a;
void foo(int){}
void foo (char){}
int main() {
foo(a);
}
Above code works fine, and as expected gcc, clang and VC++ chooses foo(char)
.
Now lets modify the code little bit :
#include<iostream>
struct A {
operator double(){
std::cout<<"Conversion function double chosen."<<std::endl;
return 1.1;
}
operator char(){
std::cout<<"Conversion function char chosen."<<std::endl;
return 'a';
}
} a;
void foo(int){}
void foo (double){} //parameter changed from char to double
int main() {
foo(a);
}
Now this should have choose foo(double)
, but seems only VC++ is happy with the code while clang and gcc are unhappy with the above code.
main.cpp:11:10: error: call of overloaded 'foo(A&)' is ambiguous
foo(a);
^
main.cpp:8:6: note: candidate: void foo(int)
void foo(int){}
^
main.cpp:9:6: note: candidate: void foo(double)
void foo (double){} //parameter changed from char to double
^
Can anyone explain why above code fails? or is it bug?.
One more question: Do gcc and clang share code of overload resolution?
The process of selecting the most appropriate overloaded function or operator is called overload resolution. Suppose that f is an overloaded function name. When you call the overloaded function f() , the compiler creates a set of candidate functions.
Function Overloading in C++When a function name is overloaded with different jobs it is called Function Overloading. In Function Overloading “Function” name should be the same and the arguments should be different. Function overloading can be considered as an example of a polymorphism feature in C++.
The return type of a function has no effect on function overloading, therefore the same function signature with different return type will not be overloaded. Example: if there are two functions: int sum() and float sum(), these two will generate a compile-time error as function overloading is not possible here.
There are two ways to resolve this ambiguity: Typecast char to float. Remove either one of the ambiguity generating functions float or double and add overloaded function with an int type parameter.
A -> char
is A -> char
.
A -> int
is A -> char -> int
(because char
to int
is a promotion and so beats the double
to int
conversion).
A -> double
is A -> double
.
Two user-defined conversion sequences are only comparable if they involve the same user-defined conversion function. Thus, A -> char
is a better conversion sequence than A -> int
, so your first case is unambiguous. Neither A -> int
nor A -> double
is better than the other, so the second case is ambiguous.
TL;DR: The difference is that in the first case, as opposed to the second, the user-defined conversion sequences (A -> char
, A -> int
) call the same conversion function (operator char
). That enables us to break the tie via [over.ics.rank]/(3.3).
The best conversion operators for particular functions are selected by [over.match.best]/(1.4) (comparing the conversion sequences of their return types).
Hence the better conversion function for foo(int)
is operator char
followed by a promotion to int
, as opposed to operator double
followed by a floating point conversion.
Now consider both variants of the second overload:
The best ICS to foo(char)
is also via operator char
(identity better than floating point conversion). Thus [over.ics.rank]/(3.3) is applicable:
User-defined conversion sequence
U1
is a better conversion sequence than another user-defined conversion sequenceU2
if they contain the same user-defined conversion function […] and in either case the second standard conversion sequence ofU1
is better than the second standard conversion sequence ofU2
.
Hence the overall conversion to F2
is deemed better, and it is selected.
The best ICS to foo(double)
is via operator double
. We end up with two conversion sequences employing distinct conversion functions; nothing really applies, and we just get an ambiguity.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With