Search code examples
c++integer-promotion

C++ ambiguous call to overloaded function with unsigned int


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) 
}

Solution

  • 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.