Почему auto выводится в int вместо uint16_t

У меня есть следующий код:

uint16_t getLastMarker(const std::string &number);
...
const auto msgMarker = getLastMarker(msg.number) + static_cast<uint16_t>(1);
static_assert(std::is_same<decltype(msgMarker), const int>::value, "Should fail");
static_assert(std::is_same<decltype(msgMarker), const uint16_t>::value, "Should not fail");

и я ожидаю, что первое утверждение потерпит неудачу, а второе — нет. тем не мение gcc 4.9.2 а также clang 3.6 поступай наоборот. Если я использую uint16_t вместо auto в моем коде, правильное утверждение не выполняется, а другое — успешно.

Постскриптум Первоначально я только что 1 вместо static_cast<uint16_t>(1) и подумал, что проблема вызвана тем, что числовой буквальный 1 имеет тип int, но неправильное утверждение не выполняется даже после явного приведения здесь.

19

Решение

Дополнение выполнит обычные арифметические преобразования на его операндах, которые в этом случае приведут к тому, что операнды будут повышены до ИНТ из-за целочисленные акции и результат тоже будет ИНТ.

Ты можешь использовать uint16_t вместо автоматического принудительного преобразования или в общем случае вы можете использовать static_cast,

Для обоснования того, почему тип меньше, чем ИНТ повышены до более крупных типов см Почему краткость должна быть преобразована в int перед арифметическими операциями в C и C ++?.

Для справки, из проекта стандартного раздела C ++ 5.7 Аддитивные операторы:

[…] Обычные арифметические преобразования выполняются для операндов
арифметический или перечислимый тип […]

и из раздела 5 Выражения:

[…] В противном случае интегральные продвижения (4.5) должны выполняться
оба операнда.59 Затем применяются следующие правила
к повышенным операндам […]

и из раздела 4.5 Интегральные акции (акцент мой):

Значение типа integer, отличное от bool, char16_t, char32_t или
wchar_t чей ранг преобразования целых чисел (4.13) меньше, чем ранг
из int может быть преобразовано в значение типа int, если int может представлять
все значения типа источника
; в противном случае исходное значение может
быть преобразовано в значение типа unsigned int.

Если предположить, ИНТ больше 16 бит

16

Другие решения

Арифметические операции не работают на любом типе меньше, чем int, Так что если uint16_t меньше чем int, это будет способствовало в int (или, возможно, больший тип, если необходимо, чтобы соответствовать другому операнду) перед выполнением сложения.

Результатом добавления будет повышенный тип. Если вы хотите другой тип, вам придется конвертировать потом.

8

По вопросам рекламы [email protected]