conversion from 'double' to 'float' requires a narrowing conversion - c++

I have the following lines of code:
std::vector<float> qualities = { 0.5, 0.6, 0.7, 0.8 };
std::vector<float> percentages = { 0.15, 0.16, 0.17, 0.18 };
I get the error mentioned in the title for each element.
Why is that?

You get the message because a constant of the form (e.g.) 0.5 is a double, and assigning a double to a float is a narrowing conversion.
To fix this, append f to each of your constants, e.g. 0.5f.

conversion from 'double' to 'float' requires a narrowing conversion
I get the error mentioned in the title for each element. Why is that?
Because you are constructing a vector of floats using double literals. Such conversion is narrowing.
That said, such conversions are allowed in this context and the example is well-formed and should compile. I suspect that you've used some compiler options to ask the compiler to not compile some well-formed programs.
You can write a float literal by appending f to a double literal.

Related

How to disable implicit conversion changes signedness warning in CMAKE

Does anybody know if there is a way to disable this kind of warning given by clang in CMAKE please ?
std::vector<float> v{1.f, 2.f, 1.f};
int i = 1;
float foo = v[i]; // Here we get the warning, variable i should be a size_t
...
Implicit conversion changes signedness: 'int' to 'std::__1::vector<float>::size_type' (aka 'unsigned long')
Clang compiler gives me a warning on v[i] as it wants me to cast it as a size_t which is quite verbose if I do explicit casting everywhere.
Also, I don't want to use size_t. For me this type it is error prone as it breaks the standard substraction when getting negative results. (my vectors will never exceed 2^31 btw)

Clang-Tidy Narrowing Conversion from uint8_t to float

I'm getting a clang-tidy warning that reads narrowing conversion from 'int' to 'float' when I convert from a uint8_t to a float, which to my understanding is not a narrowing conversion since float can represent every integer that a uint8_t can.
Code example:
uint8_t testVar = 8;
float test2 = 2.0f * testVar;
clang-tidy flags the second line of that with the warning cppcoreguidelines-narrowing-conversions: narrowing conversion from 'int' to 'float'. In my IDE, the squiggle shows up under the testVar.
According to the reference, this warning should be flagged if we convert from an integer to a narrower floating-point (e.g. uint64_t to float), but to the best of my knowledge, float is not narrower than uint8_t.
Am I fundamentally misunderstanding these data types, or is something else going on here?
I'm on LLVM version 11.0.0 if that matters.

Is it necessary to cast literal constants in templated functions?

I am writing a code that has to compile in single and double precision. The original version was only in double precision, but I am trying to enable single precision now by using templates.
My question is: is it necessary to cast the 1. and the 7.8 to the specified type with static_cast<TF>(1.) for instance, or will the compiler take care of it? I find the casting not remarkably pretty and prefer to stay away from it. (I have other functions that are much longer and that contain many more literal constants).
template<typename TF>
inline TF phih_stable(const TF zeta)
{
// Hogstrom, 1988
return 1. + 7.8*zeta;
}
Casting and implicit conversions are two things. For this example, you could treat the template function as if it were two overloaded functions, but with the same code within. At the interface level (parameters, return value) the compiler will generate implicit conversions.
Now, the question you will have to ask yourself is this: Do those implicit conversions do what I want? If they do, just leave it as it is. If they don't, you could try to add explicit conversions (maybe use the function-style casting like TF(1.)) or, you could specialize this function for double and float.
Another option, less general but maybe it works here, is that you switch the code around, i.e. that you write the code for single-precision float and then let the compiler apply its implicit conversions. Since the conversions usually only go to the bigger type, it should fit for both double and float without incurring any overhead for float.
When you do:
return 1. + 7.8*zeta;
The literals 1. and 7.8 are double, so when if zeta is a float, it will first be converted to double, then the whole computation will be done in double-precision, and the result will be cast back to float, this is equivalent to:
return (float)(1. + 7.8 * (double)zeta);
Otherwise said, this is equivalent to calling phih_stable(double) and storing the result in a float, so your template would be useless for float.
If you want the computation to be made in single precision, you need the casts1:
return TF(1.) + TF(7.8) * zeta;
What about using 1.f and 7.8f? The problem is that (double)7.8f != 7.8 due to floating point precision. The difference is around 1e-7, the actual stored value for 7.8f (assuming 32-bits float) is:
7.80000019073486328125
While the actual stored value for 7.8 (assuming 64-bits double) is:
7.79999999999999982236431605997
So you have to ask yourself if you accept this loss of precision.
You can compare the two following implementations:
template <class T>
constexpr T phih_stable_cast(T t) {
return T(1l) + T(7.8l) * t;
}
template <class T>
constexpr T phih_stable_float(T t) {
return 1.f + 7.8f * t;
}
And the following assertions:
static_assert(phih_stable_cast(3.4f) == 1. + 7.8f * 3.4f, "");
static_assert(phih_stable_cast(3.4) == 1. + 7.8 * 3.4, "");
static_assert(phih_stable_cast(3.4l) == 1. + 7.8l * 3.4l, "");
static_assert(phih_stable_float(3.4f) == 1.f + 7.8f * 3.4f, "");
static_assert(phih_stable_float(3.4) == 1. + 7.8 * 3.4, "");
static_assert(phih_stable_float(3.4l) == 1.l + 7.8l * 3.4l, "");
The two last assertions fail due to the loss of precision when doing the computation.
1 You should even downcast from long double to not lose precision when using your function with long double: return TF(1.l) + TF(7.8l) * zeta;.

C++ COORD error

I'm currently trying to create a Tetris game and when I call this:
void PrintChar(int x, int y, char ch, Colors color) {
COORD c = { y,x };
FillConsoleOutputCharacterW(GameData::handle, ch, 1, c, NULL);
FillConsoleOutputAttribute(GameData::handle, color, 1, c, NULL);
}
this Warning comes up:
C4838 - conversion from 'int' to 'SHORT' requires a narrowing
conversion.
Could someone please explain what is happening here and a small example would be greatly appreciated.
You should use explicit typecast
COORD c = { static_cast<short>(x), static_cast<short>(y) };
You are using copy-list-initialization, a language feature introduced in C++11, that prevents implicit (potentially) lossy conversions. In a C++11-compliant compiler, this construct should really produce an error (not just a warning)1.
One possible solution is to use a static_cast (with direct-list-initialization as a bonus), if you know that the input will never overflow the range of the destination type:
COORD c{ static_cast<SHORT>( x ), static_cast<SHORT>( y ) };
1 Visual Studio issues a warning C4838, in case there is a potentially lossy narrowing conversion, that cannot be evaluated at compile time. If a narrowing conversion of a constant expression does cause loss of information, error C2397 is issued instead. I don't know whether this is compliant with C++11 and C++14, though.

explicit/implicit type conversion c++

I have a line of code
double i = 1 + (long)1.5* 5.0f
My question is what is the conversion order and the result? Been searching for examples like this, but to no avail. Any good guides out there that may help me understand it?
My question is what is the conversion order and the result?
The cast is applied to 1.5, giving a long with value 1.
That's converted to float for multiplication with 5.0f, giving a float with value 5.0f.
1 is converted to float for addition with that value, giving a float with value 6.0f.
Finally, that's promoted to double (retaining the value 6.0) to assign to i.
This assumes a non-crazy floating point format that can represent small integers exactly; otherwise, there may be rounding errors.
If you wanted to cast the result of the multiplication, then use parentheses to control the operator precedence:
double i = 1 + (long)(1.5* 5.0f); // = 8.0
or use a C++-style cast, which forces the use of parentheses:
double i = 1 + static_cast<long>(1.5* 5.0f)
Any good guides out there that may help me understand it?
Here's one: http://en.cppreference.com/w/cpp/language/operator_precedence. Note that the type cast has a higher precedence than multiplication, which is in turn higher than addition (3 vs. 5 vs. 6).
As you can see from this table, the cast operator has higher precedence than multiplication, but follow the advice to use parentheses.
This precedence table should tell you everything you need to know.
Casting: 1.5 is cast to a long
Multiplication: 1.5 * 5.0f, which casts this product as a float
Addition: 1 + ( ((long) 1.5) * 5.0f)
Assignment: i = 1 + ((long) 1.5 * 5.0f)
If you're not sure what the precedence of the casting operator is then rewrite the expression (in your head)
(long)1.5 * 5.0
to
5.0 * (long)1.5
Here its pretty obvious what has precedence and its the same with the first version