Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ Overloading different with signed and unsigned int

Tags:

c++

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.
like image 798
Matthew Milford Avatar asked Apr 13 '18 12:04

Matthew Milford


2 Answers

According to integral promotion (emphasis mine):

The following implicit conversions are classified as integral promotions:

  • signed char [...] can be converted to int;
  • unsigned char [...] can be converted to int if it can hold its entire value range, and unsigned int otherwise;
  • char can be converted to int or unsigned int depending on the underlying type: signed char or unsigned char (see above);

Note that all other conversions are not promotions; for example, overload resolution chooses char -> int (promotion) over char -> 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.

like image 128
Lingxi Avatar answered Oct 02 '22 17:10

Lingxi


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

like image 24
papagaga Avatar answered Oct 02 '22 16:10

papagaga