static_assert(sizeof(unsigned) == 4, ":(");
static_assert(sizeof(double) == 8 ,":(");
unsigned u{42};
double x{u};
g++ 4.7.1 complains about this code:
warning: narrowing conversion of 'u' from 'unsigned int' to 'double' inside { }
Why is this a narrowing conversion? Isn't every unsigned
perfectly representable as a double
?
Why is this a narrowing conversion?
Because the definition includes (with my emphasis):
C++11 8.5.4/7 A narrowing conversion is an implicit conversion
[...] from an integer type [...] to a floating-point type, except where the source is a constant expression and the actual value after conversion will fit into the target type and will produce the original value when converted back to the original type.
u
is not a constant expression, so it's a narrowing conversion whether or not all possible values of the source type might be representable in the target type.
Isn't every unsigned
perfectly representable as a double
?
That's implementation defined. In the common case of 32-bit unsigned
and double
with a 52-bit mantissa, that is the case; but some implementations have larger unsigned
and/or smaller double
representations, so code that depends on that assumption is not portable.
The warning you have because you initialize x with non-constant expression
Ilyas-iMac:TestC++11 sandye51$ cat main.cpp
int main()
{
static_assert(sizeof(unsigned) == 4, ":(");
static_assert(sizeof(double) == 8 ,":(");
constexpr unsigned u{42};
double x{u};
return 0;
}Ilyas-iMac:TestC++11 sandye51$ gcc -o main main.cpp -std=c++11
Ilyas-iMac:TestC++11 sandye51$
As you can see the code above works without any warning or errors
(Let's try:) double
has exactly 52 bits of significant (binary) digits (according to ieee standard), whereas unsigned int
may have good 64 bits on some other system. So the actual unsigned int
's width on your system may be of no value for this check.