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