при создании переменных с использованием инициализации списка (например, int x{ 5 };
) стандарт §8.5.4 гласит:
Если для преобразования какого-либо из аргументов требуется сужающее преобразование […], программа имеет неправильный формат. (7) Сужающее преобразование — это неявное преобразование — (7.4) из целочисленного типа или типа перечисления с незаданной областью в целочисленный тип, который не может представлять все значения исходного типа. , за исключением случаев, когда источником является константное выражение, значение которого после целочисленных преобразований соответствует целевому типу.
Итак, почему это компилируется?
char c{ 'A' };
char x{ c + c };
Напоминаем, что c + c
дает int
static_assert(std::is_same_v<decltype(c + c), int>, "");
поэтому компилятор должен жаловаться на сужающее преобразование, которое, конечно, не является константным выражением.
Интересно, что правильное объявление x
unsigned char
не компилируется:
char c{ 'A' };
unsigned char x{ c + c };
Преобразование C2397 из «int» в «unsigned char» требует сужающего преобразования
Как и введение временного:
char c{ 'A' };
int sum{ c + c };
char x{ sum }; //C2397 conversion from 'int' to 'char' requires [...]
Так почему же компилируется первая версия? Я использую Visual Studio Community 2017 версии 15.9.5 и компилирую его с помощью /wall
, и все предупреждения являются ошибками, включенными в сборке отладки x64
. Установка стандарта C++11, C++14 и C++17 для всех компиляций.
Я отправил отчет об ошибке здесь а>сильный>
-Wall
или-Wnarrowing
? (или их визуальные студийные эквиваленты.) - person Tarick Welling   schedule 19.06.2019