Инициализация скобки MSVC с двойными символами, кажется, нарушает стандарт?
Проверьте эту простую программу:
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, гласит следующее:
A сужение конверсии это неявное преобразование ...
отlong double
вdouble
или жеfloat
или изdouble
вfloat
за исключением случаев, когда источником является константное выражение, а фактическое значение после преобразования находится в диапазоне значений, которые могут быть представлены (даже если он не может быть представлен точно)Акцент мой. Поскольку 7.2 находится в диапазоне значений, представляемыхfloat
, его преобразование вfloat
не должно быть сужающего преобразования по стандарту. MSVC не в порядке здесь, и я должен сообщить об ошибке?