Почему приведенное ниже выражение характеризует сужение конверсии?

Это выражение можно найти в примере в §8.5.4 / 7 в стандарте (N3797)

unsigned int ui1 = {-1}; // error: narrows

Учитывая §8.5.4 / 7 и его четвертый пункт маркированного списка:

Сужающее преобразование — это неявное преобразование:

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

Я бы сказал, что здесь нет сужения, так как -1 — это константное выражение, значение которого после интегрального продвижения помещается в беззнаковое целое.

Смотрите также §4.5 / 1 о Интегральное продвижение:

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

Из 4.13 мы имеем, что ранг -1 (целое число) равен рангу целого без знака, и поэтому он может быть преобразован в целое число без знака.

редактировать

к несчастью Джерри Гроб удалил свой ответ из этой ветки. Я полагаю, что он был на правильном пути, если мы примем тот факт, что текущее чтение пункта 4 пули в §8.5.4 / 7 неверно, после этого менять в стандарте.

8

Решение

Изменение в формулировке стандарта призвано подтвердить понимание того, что преобразование отрицательного значения в тип без знака является и всегда было сужающим преобразованием.

Неформально, -1 не может быть представлен в диапазоне любого беззнакового типа, и битовый шаблон, который представляет это, не представляет то же самое значение, если сохранено в беззнаковом int. Поэтому это сужение конверсии и продвижение / расширение не участвует.

Это о изящном искусстве чтения стандарта. Как обычно, компилятор знает лучше.

1

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

Там нет целостного продвижения от int в unsigned intдля этого он все еще плохо информирован.

Это было бы интеграл преобразование.

7

Сужение — это неявное преобразование целочисленного типа в целочисленный тип, который не может представлять все значения исходного типа.

Преобразование из целочисленного типа int целочисленный тип unsigned intКонечно, не может представлять все значения исходного типа — стандарт здесь совершенно однозначен. Если вам это действительно нужно, вы можете сделать

 unsigned int ui1 = {-1u};

Это работает без каких-либо ошибок / предупреждений, так как 1u является литералом типа unsigned int который затем отрицается. Это четко определено как [Expr.unary.op] в стандартных штатах:

Отрицательное число без знака вычисляется путем вычитания его значения из 2N, где n — количество битов в повышенном операнде.

-1 однако является int до и после отрицания и, следовательно, оно становится сужающимся обращением. Там нет отрицательных литералов; увидеть этот ответ для деталей.

По неофициальной рекламе копирование одного и того же значения в более просторное пространство, поэтому его не следует путать с размерами ( signed а также unsigned) равны. Даже если вы попытаетесь преобразовать его в какой-то тип большего размера, скажем, unsigned long long это все еще сужающееся преобразование, поскольку оно не может действительно представлять отрицательное число.

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