Проверьте эту простую программу:
int main() {
float f2 = 7.2; // OK, with warning
float f3 = 7.199999809265137; // OK, no warning
float f4{ 7.2 }; // Fails
float f5{ 7.199999809265137 }; // OK, no warning
float f6 = { 7.2 }; // Fails
float f7 = { 7.199999809265137 }; // OK, no warning
}
При компиляции с MSVC 2015 с использованием параметров по умолчанию (cl /W4
, версия 19.00.23918), я получаю следующие сообщения:
FloatTest.cpp(2): warning C4305: 'initializing': truncation from 'double' to 'float'
FloatTest.cpp(4): error C2397: conversion from 'double' to 'float' requires a narrowing conversion
FloatTest.cpp(4): warning C4305: 'initializing': truncation from 'double' to 'float'
FloatTest.cpp(6): error C2397: conversion from 'double' to 'float' requires a narrowing conversion
FloatTest.cpp(6): warning C4305: 'initializing': truncation from 'double' to 'float'
Эта программа отлично компилируется с помощью Clang 3.0-3.8 и GCC 4.5.4-6.1.0 (протестирована с помощью http://melpon.org/wandbox), и только предупреждения для неиспользуемых переменных. Кроме того, удаление/комментирование строк f4
и f6
приводит к успешной компиляции (только с одним предупреждением для строки f2
).
Изначально это похоже на то, что MSVC просто говорит мне, что 7.2 не может быть представлен точно как float
, поэтому это сужение преобразования (что является незаконным при инициализации скобки). Тем не менее, стандарт (черновик N3337), раздел 8.5.4, примечание 7, говорит следующее:
Сужение преобразования является неявным преобразованием...
- от
long double
доdouble
илиfloat
, или отdouble
доfloat
, за исключением случаев, когда источник является константным выражением, а фактическое значение после преобразования находится в диапазоне значений, которые могут быть представлены (, даже если он не может быть представлен точно)
Акцент мой. Так как 7.2 находится в диапазоне значений, представляемых float
, его преобразование в float
не должно быть сужающим преобразованием в соответствии со стандартом. Является ли MSVC неправильным здесь, и должен ли я указать ошибку?