71

I've got a small program:

#include<iostream>
using namespace std;

void f(int)   { cout << "int\n";   }
void f(short) { cout << "short\n"; }

int main(void){
    char c = 0;
    f(c);
    return 0;
}

It prints int. I felt that, if this is because of "Integer promotion", why is not short preferred?

I also know that integer promotion happens in an expression (like A=B). But I don't have expression in call to f(), right?

If this is related to overload resolution rule, why passing char to f will result into compilers preferring int to short?

If I delete f(int), then f(c) will call f(short)!

So in summary, my question is, is it related to "Integer promotion" or just "overload resolution rule"? And why?

Geezer
  • 5,600
  • 18
  • 31
Hind Forsum
  • 9,717
  • 13
  • 63
  • 119
  • Is there a problem you're trying to solve or is this just pure curiousity? – Karoly Horvath May 11 '16 at 14:51
  • 4
    The _(a bit dubious)_ rationale, for not having a short promotion, is that `int` is considered the optimal processor/register size, `short` just a packed memory layout. Hence an int ("register") is used to process a `char`. It is assumed that an short subtraction would not be more efficient than an int subtraction. – Joop Eggen May 11 '16 at 15:19
  • 4
    @JoopEggen - that's not a rationale (dubious or otherwise), it's a design decision: in C and C++, `int` is supposed to be the natural size for the architecture, so it's what should be used when there isn't a good reason to prefer something else. – Pete Becker May 11 '16 at 16:03
  • 4
    @PeteBecker I wanted to formulate the _reason_ for that design decision. As there were already answers citing references I did not want a legalistic statement. – Joop Eggen May 11 '16 at 17:46
  • 1
    excellent question +1 !!! – Destructor May 12 '16 at 13:04

2 Answers2

67

(Integral) Promotion is preferred to other (integral) conversions by overload resolution

Ranking of implicit conversion sequences

1) Exact match: no conversion required, lvalue-to-rvalue conversion, qualification conversion, function pointer conversion, (since C++17) user-defined conversion of class type to the same class

2) Promotion: integral promotion, floating-point promotion

3) Conversion: integral conversion, floating-point conversion, floating-integral conversion, pointer conversion, pointer-to-member conversion, boolean conversion, user-defined conversion of a derived class to its base

So, the promotion from char to int is preferred over conversion from char to short.


What is promotion? you may ask. It is a special kind of conversion described by the standard.

Why is char to short not a promotion?, you may continue. Integral promotion is always to int or a larger type. There are no promotions to short.

The following implicit conversions are classified as integral promotions:

  • signed char or signed short can be converted to int;

  • unsigned char or unsigned short 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);

  • wchar_t, char16_t, and char32_t can be converted to the first type from the following list able to hold their entire value range: int, unsigned int, long, unsigned long, long long, unsigned long long; an unscoped enumeration type whose underlying type is not fixed can be converted to the first type from the following list able to hold their entire value range: int, unsigned int, long, unsigned long, long long, or unsigned long long. If the value range is greater, no integral promotions apply;

  • an unscoped enumeration type whose underlying type is fixed can be converted to its promoted underlying type;

    (since C++11)

  • a bit field type can be converted to int if it can represent entire value range of the bit field, otherwise to unsigned int if it can represent entire value range of the bit field, otherwise no integral promotions apply; the type bool can be converted to int with the value false becoming ​0​ and true becoming 1.


Standard references (current standard draft):

[over.ics.scs] § 3

[conv.prom] § 1

eerorika
  • 232,697
  • 12
  • 197
  • 326
  • Why is the literal 0 perceived as a char instead of an integral type? – shasan Nov 04 '19 at 22:09
  • @shasan Literal 0 is not perceived as a char. It is (usually) "perceived" as int. Also, char *is* an integral type. – eerorika Nov 04 '19 at 23:15
  • See my question again in the context of the original question and answer. The question asks why the function call with `0` calls the int overload. The answer explains how "the promotion from char to int is preferred over conversion from char to short". – shasan Nov 05 '19 at 00:25
  • `The question asks why the function call with 0 calls the int overload.` No it doesn't. It asks why calling the overloaded function with `c` chooses the `int` overload rather than `short`. `c` is not literal 0; it is a `char` lvalue. And the reason is that one conversion (promotion) is preferred to the other conversion (not promotion.) – eerorika Nov 05 '19 at 00:42
23

From Implicit conversion (cppreference):

The following implicit conversions are classified as integral promotions:

  • [...]
  • char can be converted to int or unsigned int depending on the underlying type: signed char or unsigned char (see above);
  • [...]

So, if there is a function f(int) and f(short), the compiler will try to do an integer promotion first, if it is not possible, it will fallback to a integer conversion.

char to int is an integer promotion (see above), so the compiler will choose it.

If there isn't any f(int), the compiler will fail to find a function where it can do integer promotion, and will fallback to integer conversion. It finds a f(short), and a char can be converted into a short, so it will choose it.

Community
  • 1
  • 1
Rakete1111
  • 47,013
  • 16
  • 123
  • 162
  • 1
    Why did they use the word "converted" in the list itself when establishing a difference between integer promotion and conversion? That seems like a potential source of ambiguity/confusion, especially when quoted. – JAB May 11 '16 at 19:51
  • @JAB good question :) I think what they mean is that promotion is a special type of conversion. But because it's still a conversion, they partly call it like that – Rakete1111 May 11 '16 at 19:55
  • They do establish that integral promotions fall under the category of implicit conversions at the start of your quote, so that makes sense. – JAB May 11 '16 at 20:02