This seems inconsistent. I have 3 functions f
overloaded for signed types short
, int
and long long
. If you pass an unsigned short
then it gets promoted to the next biggest signed type int
. However if you pass unsigned int
then it doesn't get promoted to signed long long
which is what I would expect, rather compiler complains about ambiguous call to overloaded function.
void f(short x) { std::printf("f(short)\n"); }
void f(int x) { std::printf("f(int)\n"); }
void f(long long x) { std::printf("f(long long)\n"); }
int main()
{
f((unsigned short)0); // Fine: calls f(int)
// f((unsigned int)0); // Ambiguous: could be f(short), f(int) or f(long long)
}
It is inconsistent, yes, but it is The Way The Language Is, and you have to cope, e.g. if you want f((unsigned int)0)
to call the long long
overload, then provide a wrapper,
inline void f(unsigned int x) { f((long long)x); }
The designers of C++ would have ideally liked to make both of your cases fail overload resolution. But there was this legacy thing (dating all the way back to "K&R" C), called "default argument promotion", that, essentially, says the compiler will implicitly convert all integer types narrower than int
to int
if necessary to match a function signature, and all floating point types narrower than double
to double
ditto.
So it's the f((unsigned short)0)
case that is the odd man out, really.