Reputation: 101
Basically, if I want something like this,
double b = sin(2.2);
but accidentally write something like this,
double b = sin(2.2f);
there is no error or even warning message, even though this clearly leads to a different, inaccurate, and therefore incorrect result. This type of error could be prevented, by forcing the compiler to not do any implicit conversions of float to double. Is there any way to achieve this, be it through a compilation switch (preferably in Visual Studio), some smart macros, or a class which behaves like float/double variables and declares its own operators?
Edit: I am also interested in solving similar problems using operators (such as e.g. double b = 2.2f*2.2f), or assignments (double b=2.2f).
Upvotes: 8
Views: 13516
Reputation: 2036
I just realized you're using a Microsoft product, but I'll leave this answer since it could help someone else.
Have you looked through the compiler switches? I imagine there is a similar option.
OMG! I just searched for help with Visual Studio Options and Warnings! (link)
I'm SO sorry! I didn't know! That is one of the least helpful listings of options and switches I've ever seen! Even more ironic, they've begun scraping StackOverflow for answers and linking back here.
But I did find some clues:
Compiler Warning (levels 3 and 4) C4244 - conversion' conversion from 'type1' to 'type2', possible loss of data
Used thusly:
// Enable this to find unintended double to float conversions.
// warning C4244: 'initializing' : conversion from 'double' to 'float', possible loss of data
#pragma warning(3 : 4244)
GCC/G++ switches (
Why not let the compiler tell you when you accidentally do this?
From the g++/gcc man page:
-Wdouble-promotion (C, C++, Objective-C and Objective-C++ only)
* Give a warning when a value of type "float" is implicitly promoted to "double".
... some verbage clipped ...
* It is easy to accidentally do computations with "double" because floating-point
literals are implicitly of type "double".
Adding -Wdouble-promotion
to your CXXFLAGS
should provide you with compile-time warnings.
There is also -fsingle-precision-constant
which prohibits implicit conversion of floats to doubles.
Upvotes: 2
Reputation: 5866
Something like that?
class MyDouble{
public:
MyDouble(float _f) {throw "only use double!";}
MyDouble(double _d) : m_data(_d) {}
operator float() const {throw "conversion to float occurred!";}
operator double() const {return m_data;}
private:
double m_data;
};
but yes, you'd have to start using this class in your calls to math functions, making it very ugly:
MyDouble d(3.2);
sin(d);
// or...
cos(MyDouble(2.3));
UPDATE - an example of an operator implementation (binary operator, as unary would have to be part of the class):
MyDouble operator+(const & MyDouble _lhs, const & MyDouble _rhs){
MyDouble rez(_lhs);
rez += _rhs;
return rez;
}
Of course you don't have to implement it that way (through the use of a shortcut operator+=
) but this makes code easier to maintain
Upvotes: 2
Reputation: 21317
You can use a type_assert
utility.
Example:
#include <cmath>
#include <type_traits>
template<typename T, typename U>
const U& type_assert(const U& u) {
static_assert(std::is_same<T, U>::value, "...");
return u;
}
int main() {
double t = type_assert<double>(std::sin(2.2f));
}
If the expected type is different then it'll give you a compiler error. Chances are the compiler could probably optimise this if it passes though, at least it did in my case with -O3
.
Upvotes: 5
Reputation: 14225
You can render the call of sin(float)
ambiguous by defining something like
double sin(float x) { abort(); }
Then calls of sin
on a float
will give you a compile-time error. This works because, in the cmath
header, std::sin
is an overloaded function with float sin(float)
, double sin(double)
, and long double sin(long double)
variants. The compiler cannot know whether you wanted ::sin(float)
or std::sin(float)
, so it throws up its hands in confusion.
I wouldn't necessarily recommend leaving this sort of thing around in your codebase, but it can be useful if you're trying to find all instances of a mistake like this and correct them.
Upvotes: 4