7

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) 
}
Jarod42
  • 203,559
  • 14
  • 181
  • 302
George Skelton
  • 1,095
  • 1
  • 10
  • 22

2 Answers2

7

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.

zwol
  • 135,547
  • 38
  • 252
  • 361
4

http://en.cppreference.com/w/cpp/language/implicit_conversion

Integral promotion does not get you from unsigned int to long long.

Integral promotion does get you from unsigned short to int.

Integral conversion from unsigned int is considered equally good for your overloads.

Promotion ends at int and/or unsigned int unless your source type is an enum that requires a larger integral type to fit it.

Promotion is preferred to conversion, so your first case is unambiguous. In the second case, there is no promotion path, so your code is ambiguous.

Yakk - Adam Nevraumont
  • 262,606
  • 27
  • 330
  • 524