Определенные реализацией сужающие преобразования?
C++11 формализовал понятие сужающегося преобразования и запретил использовать его на верхнем уровне при инициализации списка.
Мне интересно, если, учитывая два типа T
а также U
, это может быть определено реализацией, является ли преобразование из T
в U
сужается. Согласно моему прочтению стандарта, это так. Вот мои рассуждения:
- Согласно пункту 7 dcl.init.list (8.5.4), один из способов сужения преобразования - это неявное преобразование "целочисленного типа или перечислимого типа с незаданной областью в целочисленный тип, который не может представлять все значения оригинала. тип".
- Рассмотрим неявное преобразование из
unsigned int
вlong
, - Что касается относительных размеров
int
а такжеlong
, C++ требует только, чтобыsizeof(int) <= sizeof(long)
, - Рассмотрим реализацию А, где
sizeof(int) == sizeof(long)
, На этой реализации,long
не может представлять все значенияunsigned int
, поэтому конверсия будет сужаться. - Рассмотрим реализацию B, где
sizeof(int) < sizeof(long)
, На этой реализации,long
может представлять все значенияunsigned int
, поэтому конверсия не будет сужаться.
Правильно ли я в своем анализе, что это может быть определено реализацией, сужается ли конверсия? Это желательно?
2 ответа
Я бы действительно предпочел, чтобы "сужающее преобразование" было определено для самих типов. Таким образом, чтобы int i{long(non_constant_expression)}
никогда не разрешается компилировать. Причина проста: либо вам не нужен большой радиус действия, вам следует использовать int
во-первых, или вы действительно хотите "вырезать", что кажется мне достаточно редким случаем, когда требуется явное преобразование типа или приведение. Чтобы ответить на первый вопрос: это определение реализации.
Но, если честно, я почти никогда не использую этот сырой тип, просто size_t
, int32_t
, uint16_t
и т.д., и это решает проблему автоматически. (uint16_t {uint8_t()}
всегда сужается, uint16_t{uint16_t()}
никогда.) Нужно только вдумчиво преобразовать size_t
во что-то другое, но это всегда так.
В моем случае для этого фрагмента кода:char *pointer = strchr(s1, s2[I]);
int start = pointer - s1;
Это помогло изменитьint
тип данных дляlong
:long start = pointer - s1;
«Компилятор не может определить, насколько велико или мало значение для определенного типа данных; следовательно, компилятор не может определить, помещается ли указанное значение в новое поле, которому вы его присваиваете. Если вы уверены, что нет переполнения, явно введите значение, чтобы избежать предупреждения». - источник: https://www.ibm.com/docs/en/ztpf/2020?topic=warnings-narrowing-conversion .