Почему это сужающее преобразование не обнаружено?

при создании переменных с использованием инициализации списка (например, 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 для всех компиляций.


Я отправил отчет об ошибке здесь


person Stack Danny    schedule 19.06.2019    source источник
comment
clang выдает ошибку, а gcc выдает предупреждение.   -  person interjay    schedule 19.06.2019
comment
какие флаги компиляции вы используете? Используются ли -Wall или -Wnarrowing? (или их визуальные студийные эквиваленты.)   -  person Tarick Welling    schedule 19.06.2019
comment
Похоже, что ответ Бьяджо Феста правильный с ошибкой визуальной студии.   -  person Tarick Welling    schedule 19.06.2019


Ответы (1)


да. Вы правы: программа неправильная.

В таком случае (стандартный §1.4):

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

Действительно, gcc выдает предупреждающее сообщение. clang напрямую отклоняет код как ошибку компилятора.

Эта конкретная тема уже обсуждалась здесь для gcc1.

Visual Studio должен выдавать диагностическое сообщение (рекомендую вам проверить параметры компиляции. Вы отключили предупреждения? Вы компилируете с помощью C++(14/11/17)?, ...). Если это не так, это ошибка реализации.

Обновление:

Visual Studio v19.20 не выдает никаких диагностических сообщений (даже с флагом /Wall).

Здесь был заполнен отчет об ошибке .


1 Дополнительную информацию о реализации gcc для сужения см. здесь.

person BiagioF    schedule 19.06.2019
comment
Какой стандарт С++ вы используете? Если вы заполняете отчет об ошибке, я думаю, было бы полезно добавить ссылку в качестве комментария к этому ответу. Спасибо - person BiagioF; 19.06.2019
comment
На самом деле я переключался между C++11 - C++14 - C++17, чтобы посмотреть, есть ли разница, но ничего не было, поэтому я просто отметил C++11 для публикации. - person Stack Danny; 19.06.2019
comment
Да, вам просто нужен С++ 11 или выше - person BiagioF; 19.06.2019
comment
И да, я написал краткое резюме, а также ссылку на этот пост. Будет ли это полезно. - person Stack Danny; 19.06.2019