Check out this simple program:
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
}
When compiled with MSVC 2015 using the default options (cl /W4
, version 19.00.23918), I get the following messages:
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'
This program compiles fine with Clang 3.0-3.8 and GCC 4.5.4-6.1.0 (tested with http://melpon.org/wandbox), with only warnings for unused variables. Further, removing/commenting out lines f4
and f6
result in successful compilation (with only the one warning for line f2
).
Initially it looks like MSVC is just telling me that 7.2 can't be represented precisely as a float
, so it's a narrowing conversion (which is illegal in brace initialization). However, the standard (draft N3337), section 8.5.4, note 7, says this:
A narrowing conversion is an implicit conversion...
- from
long double
todouble
orfloat
, or fromdouble
tofloat
, except where the source is a constant expression and the actual value after conversion is within the range of values that can be represented (even if it cannot be represented exactly)
Emphasis mine. Since 7.2 is within the range of values representable by float
, its conversion to float
should not be a narrowing conversion according to the standard. Is MSVC in the wrong here, and should I file a bug?
/W4
as well please. – Elboaf
at the end of the literals? – Monophysite