У меня есть следующий код:
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, но неправильное утверждение не выполняется даже после явного приведения здесь.
Дополнение выполнит обычные арифметические преобразования на его операндах, которые в этом случае приведут к тому, что операнды будут повышены до ИНТ из-за целочисленные акции и результат тоже будет ИНТ.
Ты можешь использовать 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 бит
Арифметические операции не работают на любом типе меньше, чем int
, Так что если uint16_t
меньше чем int
, это будет способствовало в int
(или, возможно, больший тип, если необходимо, чтобы соответствовать другому операнду) перед выполнением сложения.
Результатом добавления будет повышенный тип. Если вы хотите другой тип, вам придется конвертировать потом.