Почему компилятор соответствует "char" на "int", но не "короткий"?

У меня есть небольшая программа:

#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;
}

Он печатает int. Я чувствовал, что, если это связано с "Целом продвижение", почему не short предпочтительнее?

Я также знаю, что целочисленное продвижение происходит в выражении (например, A = B). Но у меня нет выражения при вызове f(), правильно?

Если это связано с правилом разрешения перегрузки, почему передача char в f приведет к компиляторам, предпочитающим int - short?

Если я удалю f(int), тогда f(c) вызовет f(short)!

Итак, в заключение, мой вопрос в том, связано ли это с "Целом продвижение" или просто с "правилом разрешения перегрузки"? И почему?

Ответ 1

(Интеграл) Продвижение предпочтительнее (интегрального) преобразования разрешение перегрузки

Рейтинг неявных последовательностей преобразования

1) Точное совпадение: не требуется преобразование, преобразование lvalue-в-rval, преобразование квалификации, преобразование указателя функции (начиная с С++ 17), определяемое пользователем преобразование типа класса в один класс

2) Продвижение: интегральное продвижение, продвижение с плавающей запятой

3) Конверсия: интегральное преобразование, преобразование с плавающей запятой, преобразование с плавающим интегралом, преобразование указателя, преобразование указателя в член, логическое преобразование, пользовательское преобразование производного класса в его база

Таким образом, продвижение от char до int предпочтительнее, чем преобразование от char до short.


Что такое продвижение? вы можете спросить. Это особый вид конверсии, описанный стандартом.

Почему char - short не продвижение?, вы можете продолжить. Интегральное продвижение всегда соответствует int или большему типу. Для short нет рекламных акций.

Следующие неявные преобразования классифицируются как интегральные рекламные акции:

  • подписанный char или подписанный короткий может быть преобразован в int;

  • unsigned char или unsigned short может быть преобразован в int, если он может содержать весь диапазон значений, а unsigned int иначе;

  • char может быть преобразован в int или unsigned int в зависимости от базового типа: подписанный char или unsigned char (см. выше);

  • wchar_t, char16_t и char32_t могут быть преобразованы в первый тип из следующего списка, способного удерживать весь диапазон значений: int, unsigned int, long, unsigned long, long long, unsigned long long;     тип неперечисленного перечисления, базовый тип которого не фиксирован, может быть преобразован в первый тип из следующего списка, способного удерживать весь диапазон значений: int, unsigned int, long, unsigned long, long long или unsigned long long. Если диапазон значений больше, интегральные промо-акции не применяются;

  • неперечисленный тип перечисления, основной тип которого фиксирован, может быть преобразован в его продвинутый базовый тип;

    (поскольку С++ 11)

  • тип битового поля может быть преобразован в int, если он может представлять весь диапазон значений битового поля, в противном случае - беззнаковый int, если он может представлять весь диапазон значений битового поля, в противном случае не применяются целые акции;     тип bool может быть преобразован в int с значением false, становящимся 0, а true становится 1.


Стандартные ссылки (текущий стандартный черновик):

[over.ics.scs] § 3

[conv.prom] § 1

Ответ 2

Из Неявное преобразование (cppreference):

Следующие неявные преобразования классифицируются как интегральные рекламные акции:

  • [...]
  • char можно преобразовать в int или unsigned int в зависимости от базового типа: signed char или unsigned char (см. выше);
  • [...]

Итак, если есть функция f(int) и f(short), компилятор сначала попытается выполнить целочисленную рекламу, если это невозможно, она вернется к целочисленное преобразование.

char to int является целым продвижением (см. выше), поэтому компилятор выберет его.

Если не существует f(int), компилятор не сможет найти функцию, в которой он может выполнять целую рекламу, и будет возвращаться к целочисленному преобразованию. Он находит f(short), а char можно преобразовать в short, поэтому он выберет его.