When compiling C++ with overloaded function definitions why is the promotion behaviour different between signed and unsigned integer types? Is this expected behaviour?
In the example below, the call to "fail" in main is ambiguous but the call to "pass" is not.
unsigned int fail(unsigned int a) {
  return a;
}
unsigned int fail(unsigned short a) {
  return a;
}
int pass(int a) {
  return a;
}
int pass(short a) {
  return a;
}
int main(){
  unsigned char a;
  char b;
  fail(a);
  pass(b);
  return 0;
}
Sample output (from clang, VS compiler gives something similar):
fail.cpp:22:3: error: call to 'fail' is ambiguous
  fail(a);
  ^~~~
fail.cpp:1:14: note: candidate function
unsigned int fail(unsigned int a) {
             ^
fail.cpp:5:14: note: candidate function
unsigned int fail(unsigned short a) {
             ^
1 error generated.
                According to integral promotion (emphasis mine):
The following implicit conversions are classified as integral promotions:
signed char[...] can be converted toint;unsigned char[...] can be converted tointif it can hold its entire value range, andunsigned intotherwise;charcan be converted tointorunsigned intdepending on the underlying type:signed charorunsigned char(see above);Note that all other conversions are not promotions; for example, overload resolution chooses
char->int(promotion) overchar->short(conversion).
In your case, given that int is able to hold the entire value range of both signed char and unsigned char, only int pass(int a) is a promotion which is more preferable than the remaining three which are conversions, and there is no preference among the conversions.
Those implicit conversions indeed follow different rules.
char -> int   is a promotion
char -> short is a conversion 
and promotion is chosen over conversion because it forbids any precision loss. That's why pass passes.
Whereas
unsigned char -> unsigned int is a promotion only if int can't represent the full range of values unsigned chars can; if not, the promotion is unsigned char -> int. I suspect that, in your case, int can indeed represent all values in the range of unsigned char. This means that fail has a choice between two two-steps conversion paths: unsigned char -> int -> unsigned int and unsigned char -> int -> unsigned short and can't decide between them.
source: http://en.cppreference.com/w/cpp/language/implicit_conversion
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With