防止在C++中从float到double的隐式转换

use*_*612 7 c++ floating-point implicit floating-accuracy implicit-conversion

基本上,如果我想要这样的东西,

double b = sin(2.2);
Run Code Online (Sandbox Code Playgroud)

但不小心写了这样的东西,

double b = sin(2.2f);
Run Code Online (Sandbox Code Playgroud)

没有错误甚至是警告信息,即使这显然会导致不同的,不准确的,因此不正确的结果.通过强制编译器不执行float到double的任何隐式转换,可以防止这种类型的错误.有没有办法实现这一点,无论是通过编译开关(最好是在Visual Studio中),一些智能宏,还是一个行为像float/double变量并声明自己的运算符的类?

编辑:我也有兴趣使用运算符(例如double b = 2.2f*2.2f)或赋值(double b = 2.2f)解决类似的问题.

Rap*_*ptz 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));
}
Run Code Online (Sandbox Code Playgroud)

如果预期的类型不同,那么它会给你一个编译器错误.有可能编译器可能会优化它,如果它通过,至少它在我的情况下做了-O3.


tmy*_*ebu 4

sin(float)您可以通过定义类似的内容来渲染不明确的调用

double sin(float x) { abort(); }
Run Code Online (Sandbox Code Playgroud)

然后调用sinafloat会给你一个编译时错误。这是有效的,因为在cmath标头中,是一个带有、和变体std::sin的重载函数。编译器无法知道您是否想要或,因此它会困惑地举手。float sin(float)double sin(double)long double sin(long double)::sin(float)std::sin(float)

我不一定建议将此类内容留在代码库中,但如果您试图找到此类错误的所有实例并纠正它们,它可能会很有用。