5

Consider this program:

#include <iostream>

using namespace std;

void f(unsigned char c) {
  cout << c << endl;
}

void f(int c) {
  cout << c << endl;
}

int main() {
  f('a');
}

This prints out 97, suggesting that the f() overload that was selected was the one taking an int. I find this weird; wouldn't intuitively an unsigned char be a better match for a char?

lindelof
  • 34,556
  • 31
  • 99
  • 140

1 Answers1

8

wouldn't intuitively an unsigned char be a better match for a char?

Well, I guess, but not according to the Standard. According to [conv.prom]p1:

A prvalue of an integer type other than bool, char16_­t, char32_­t, or wchar_­t whose integer conversion rank is less than the rank of int can be converted to a prvalue of type int if int can represent all the values of the source type; [...]

Now, the three character types have the same rank, and a signed type has a rank always less than int. This is a combination of [conv.rank]p1.6 and [conv.rank]p1.2:

  • The rank of a signed integer type shall be greater than the rank of any signed integer type with a smaller size.

  • [...]

  • The rank of char shall equal the rank of signed char and unsigned char.

Basically, every character has always a smaller rank than int and they can all be represented in an int, and so the overload with unsigned char is not a better match, because it would involve a conversion from char to unsigned char, instead of a promotion.

If you change your overload to take a char, then there would be an exact match, and so naturally, the "correct" overload (in your eyes) would be chosen.

Community
  • 1
  • 1
Rakete1111
  • 47,013
  • 16
  • 123
  • 162
  • 1
    There is also a good reference [here](http://en.cppreference.com/w/cpp/language/overload_resolution), section *"Ranking of implicit conversion sequences"*. It basically says that integer/floating-point promotion is preferred over conversion. – HolyBlackCat Aug 19 '17 at 20:38