Неявное преобразование и перегрузка оператора - PullRequest
0 голосов
/ 02 марта 2019

Итак, я написал что-то вроде этого

#include <iostream>
using namespace std;

void f(int32_t i)
{
    cout << "int32: " << i << endl;
}

void f(int16_t i)
{
    cout << "int16: " << i << endl;
}

void f(int8_t i)
{
    cout << "int8: " << i << endl;
}

void f(uint32_t i)
{
    cout << "uint32: " << i << endl;
}

void f(uint16_t i)
{
    cout << "uint16: " << i << endl;
}


int main() {
    uint8_t i = 0u;
    f(i);
    return 0;
}

И он напечатал

int32: 0

Я немного запутался:

  • Является ли это четко определенным поведением или оно зависит от реализации?

  • Какие правила определяют, какая перегрузка используется здесь и в какой тип преобразуется переменная?

Ответы [ 2 ]

0 голосов
/ 02 марта 2019

Поведение четко определено, , но зависит от реализации.С 16-битным int все было бы иначе.

В стандарте приведены конкретные правила:

[over.best.ics] для разрешения перегрузки, [conv.prom] для комплексного продвижения.

0 голосов
/ 02 марта 2019

При сравнении преобразований, необходимых для различных перегруженных функций, «повышение» считается лучшей последовательностью преобразования, чем стандартное «преобразование».Каждый арифметический тип может повышать до одного другого типа.(Акции также используются при передаче аргумента в переменную функцию в стиле C, например printf. Унарный оператор + может использоваться для принудительного продвижения арифметического выражения, например +n.)

Для целочисленных типов, которые не являются типами символов или bool, повышенный тип:

  • Если int может представлять все значения исходного типа, тогда int;
  • В противном случае, если unsigned int может представлять все значения исходного типа, то unsigned int;
  • В противном случае, сам исходный тип (продвижение ничего не делает)

В вашем примере, при сравнении перегруженных функций, «точное соответствие» было бы лучше, но нет функции, принимающей в точности int8_t (или int8_t& или const int8_t&).Повышенный тип uint8_t - int, поскольку требуется поддерживать диапазон, намного больший, чем 0-255.И, очевидно, в вашей системе int32_t является псевдонимом для int, поэтому функция void f(int32_t); требует только повышения аргумента.Все остальные функции являются жизнеспособными, но требуют целочисленного преобразования аргумента.Так что void f(int32_t); считается наилучшей перегрузкой.

Таким образом, технический ответ на этот вопрос заключается в том, что он зависит от реализации, но только из-за связи между типами int и <cstdint>, а не из-заправила разрешения перегрузки.

...