Как объяснено в http://en.cppreference.com/w/cpp/language/implicit_cast:
Prvalues малых интегральных типов (например, char
могут быть превращены в prvalues более крупных интегральных типов (таких, как int
) В частности, арифметические операторы не принимают типа меньше. чем int
в качестве аргументов и интегральных акций автоматически применяется после именующих к RValue конверсии, если это применимо. Это преобразование всегда сохраняет значение.
[акцент мой; ссылка удалена]
Таким образом, вы не можете делать то, что хотите.
Причина, по которой int16_t w = x + y;
работает, заключается в том, что она делает преобразование обратно в int16_t
в конце. Из этого же источника:
Если тип адресата подписан, значение не изменяется, если исходное целое число может быть представлено в целевом типе. В противном случае результат определяется реализацией. (Обратите внимание, что это отличается от знакового целого числа арифметического переполнения, которое не определено)
[ссылка удалена]
Отредактировано добавить: То есть, я должен отметить, что не существует никакой реальной причина делать то, что вы хотите. Это правда, что int16_t w = x + y;
означает int16_t w = static_cast<int16_t>(static_cast<int>(x) + static_cast<int>(y));
вместо того, чтобы начинать с 16-битного добавления; но результат один и тот же. Единственное различие заключается в том, что если x + y
выходит за пределы 16-разрядных целых чисел, то int16_t w = x + y;
по-прежнему будет достаточно хорошо себя вести (давая результат, определенный реализацией), потому что сам +
не запускает переполнение.