narrowing conversion from unsigned to 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 adouble
?
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.
Narrowing conversion from double to float
Can someone explain why that is and how to correct it?
Narrowing: Float is smaller than double, in a way analogous to int8_t is smaller than int16_t. The biggest float is quite a bit smaller than the biggest double.
Note also: a smaller int will auto magically be promoted to a larger int. Similarly, your compiler did not protest about "double x_pos = clownfish->xPos();", a double is always big enough to contain a float.
how to correct:
If you are confident that float (the smaller) is sufficient for your needs, or you are not allowed to change the clownfish code, then you might consider using a cast.
clownfish->xPos(static_cast<float>(x_pos)).
If you are willing and not prohibited from changing the clownfish code, ensure that the clownfish x position (i.e. what "clownfish->xPos()" returns) is a double, and that the function "clownfish->xPos()" returns a double.
Narrowing conversion from char to double
It is narrowing because the standard says so.
7 A narrowing conversion is an implicit conversion
[...]
(7.3) — from an integer type or unscoped enumeration 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 [...]
Narrowing is not allowed in list-initialization. Use an explicit conversion (cast).
double a{static_cast<double>(c)};
Yes, theoretically it is allowed for char
to be not exactly representable as double
, e.g. when both are 32-bit types. This is contrived but the standard allows for such an implementation.
Narrowing conversion of 'int' value to 'short' is not allowed here
Ideally, all GUID
fields should be declared unsigned (see for instance this Microsoft documentation). But some languages (Java, for instance) don't support unsigned integers. So it looks like your C++ GUID
structure was defined by a Java programmer.
If you can change the definition of GUID
, do that. If not, I am afraid you are going to have to apply your (short)
cast to all occurrences of the DEFINE_GUID
macro (unless your compiler has some way of disabling this error, as suggested in the comments to your original post). Java programmers have to do this all the time.
Narrowing conversions in C++0x. Is it just me, or does this sound like a breaking change?
I ran into this breaking change when I used GCC. The compiler printed an error for code like this:
void foo(const unsigned long long &i)
{
unsigned int a[2] = {i & 0xFFFFFFFF, i >> 32};
}
In function
void foo(const long long unsigned int&)
:error: narrowing conversion of
(((long long unsigned int)i) & 4294967295ull)
fromlong long unsigned int
tounsigned int
inside { }error: narrowing conversion of
(((long long unsigned int)i) >> 32)
fromlong long unsigned int
tounsigned int
inside { }
Fortunately, the error messages were straightforward and the fix was simple:
void foo(const unsigned long long &i)
{
unsigned int a[2] = {static_cast<unsigned int>(i & 0xFFFFFFFF),
static_cast<unsigned int>(i >> 32)};
}
The code was in an external library, with only two occurrences in one file. I don't think the breaking change will affect much code. Novices might get confused, though.
Why int is narrowed to float?
That is because of the precision of the float, which is only 7-digit, despite it has larger range than int.
So if you try to represent int number with more than 7-digit precision to float you might likely get some loss. - in this sense it is called narrowed. Though float has wider range than int, it has less precision.
Besides, floating point representation is approximation - that is, it does not represent exact number (except for power of 2). In that sense, the int is also narrowed.
Related Topics
Why Is a C++ Vector Called a Vector
Differencebetween Const_Iterator and Iterator
Default Member Values Best Practice
Opengl: Glflush() VS. Glfinish()
When to Use Const Char * and When to Use Const Char []
Difference Between Steady_Clock VS System_Clock
Class Members and Explicit Stack/Heap Allocation
Does C++11 Unique_Ptr and Shared_Ptr Able to Convert to Each Other's Type
Difference Between Std::Function<> and a Standard Function Pointer
String::Size_Type Instead of Int
Passing Object by Reference in C++
Svm Classifier Based on Hog Features for "Object Detection" in Opencv
Usage of Std::Forward VS Std::Move
Disabling Warnings Generated via _Crt_Secure_No_Deprecate
Creating JSON Arrays in Boost Using Property Trees
Understanding the Difference Between F() and F(Void) in C and C++ Once and for All