基本上,如果我想要这样的话,
double b = sin(2.2);
但是不小心写了这样的东西,
double b = sin(2.2f);
没有错误甚至是警告信息,即使这显然会导致不同的,不准确的,因此不正确的结果。通过强制编译器不执行float到double的任何隐式转换,可以防止这种类型的错误。有没有办法实现这一点,无论是通过编译开关(最好是在Visual Studio中),一些智能宏,还是一个行为类似浮点/双变量并声明自己的运算符的类?
编辑:我也有兴趣使用运算符解决类似问题(例如双b = 2.2f * 2.2f)或赋值(double b = 2.2f)。
答案 0 :(得分:5)
您可以使用type_assert
实用程序。
示例:
#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));
}
如果预期的类型不同,那么它会给你一个编译器错误。有可能编译器可能会优化它,如果它通过,至少在我的情况下使用-O3
。
答案 1 :(得分:4)
您可以通过定义类似
的内容来呈现sin(float)
不明确的调用
double sin(float x) { abort(); }
然后在sin
上调用float
会给您一个编译时错误。这是有效的,因为在cmath
标题中,std::sin
是一个包含float sin(float)
,double sin(double)
和long double sin(long double)
变体的重载函数。编译器无法知道您是否需要::sin(float)
或std::sin(float)
,因此它会引起混乱。
我不一定会建议在您的代码库中留下这类内容,但如果您尝试查找此类错误的所有实例并进行更正,则会非常有用。
答案 2 :(得分:2)
那样的东西?
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;
};
但是,是的,你必须在调用数学函数时开始使用这个类,这非常难看:
MyDouble d(3.2);
sin(d);
// or...
cos(MyDouble(2.3));
UPDATE - 运算符实现的一个示例(二元运算符,因为一元必须是类的一部分):
MyDouble operator+(const & MyDouble _lhs, const & MyDouble _rhs){
MyDouble rez(_lhs);
rez += _rhs;
return rez;
}
当然,您不必以这种方式实现(通过使用快捷方式operator+=
),但这使代码更易于维护
答案 3 :(得分:1)
我刚刚意识到你正在使用 Microsoft 产品,但我会留下这个答案,因为它可以帮助其他人。
你看过编译器开关了吗?我想有类似的选择。
OMG!我刚刚搜索了Visual Studio选项和警告的帮助! (link)
我 SO 抱歉! 我不知道!这是至少之一我见过的选项和开关列表!更具讽刺意味的是,他们已经开始抓取StackOverflow寻找答案并将其链接回来。
但我确实找到了一些线索:
Compiler Warning (levels 3 and 4) C4244 - 转换'从'type1'转换为'type2',可能会丢失数据
因此使用:
// 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 ++ 切换(
为什么不让编译器告诉你什么时候不小心这样做?
来自g ++ / gcc手册页:
-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".
将-Wdouble-promotion
添加到CXXFLAGS
应该会为您提供编译时警告。
还有-fsingle-precision-constant
禁止将浮点数隐式转换为双精度数。