将所有浮点文字声明为 double 会在 C++ 中导致真正的问题吗?

Are there any real life situations where declaring all floating point literals as double causes real problems in C++?

意思是,在“正常”情况下,类型提升的性能损失无关紧要,没有人检查浮点数是否相等,也没有人声明任何有趣的东西,比如

void f(float x) {/*do something*/};
void f(double x) {/*do something completely different*/};

等等。

我知道“C++ f 后缀为什么?”的一般问题。已被问过一千次,但所有的答案总是关于技术细节和人为的例子。我还没有找到任何令人满意的答案来显示实际相关的情况,其中区别很重要。

我手头没有一个很好的“现实生活中”的例子。相反,我想尝试用一个简单的例子来说服你。

让我们假设所有函数都为 floatdouble 重载做“正确的事”:

void f(float x) {/*do something*/};
void f(double x) {/*do the same thing*/};

此外,当只有一个重载可用时,我们可以使用任一类型的文字来调用它:

void f_float(float x) {/*do something*/};
void f_double(double x) {/*do the same thing*/};
f_float(3.0);    // ok
f_float(3.0f);   // ok
f_double(3.0);   // ok
f_double(3.0f);  // ok

floats 转换为 doubles,反之亦然。


如果所有代码都可以使用 floatdouble,那么故事就此结束。但是,您不需要做一些“有趣”的事情来破解代码。


I haven't found any satisfactory answer that shows an actually relevant situation, where the distinction is important.

当文字的类型用于推断其他事物的类型时,这种区别很重要。能够在 doublefloat 之间转换并不是您需要能够用 double 文字替换任何 float 文字而不破坏代码的全部。

在上面的示例中,f_float 可以用 3.03.0f 调用。现在假设您有一个只接受 std::vector<float>:

的函数
void bar(const std::vector<float>& x){}

以及给定单个值的东西构造一个向量:

template <typename T>    
std::vector<T> make_vect(const T& t){ return {T{}}; }

然后文字的类型使代码要么失败要么通过:

bar(make_vect(0.3f));
//bar(x.make_vect(0.3)); // ERROR

Complete Example.

TL;DR 整点只是你可以在floatdouble之间转换,但一般来说some_template<float>some_template<double>之间没有可用的转换。文字的类型可能是相关的,即使您不介意 floatdouble 之间的转换。将 3.0f 更改为 3.0 可以使代码中断,否则没问题