这是为浮点数/双精度函数泛型的正确方法吗?

Is this the correct way to genericise a function for floats/doubles

本文关键字:方法 泛型 函数 浮点数 双精度      更新时间:2023-10-16

在我的函数中:

template <typename T>
T lerpMidway(const T& a, const T& b)
{
    T result;
    result = (b - a) * 0.5 + a;
    return result;
}
int main()
{
    lerpMidway(4.f, 6.f);
}

如果我将浮点值传递给这个函数,我认为 0.5 会将所有其他浮点数提升为双精度,然后在需要返回它时将其转换回浮点数。

我试了这行:

result = (b - a) * decltype(a)(0.5) + a;

它摆脱了编译器消息说双精度以浮点可能丢失数据,但在这里,如果"a"是浮点数,并且我用双精度初始化它,则不会发生转换吗?我也可以用 0.5f 初始化它,它不会有什么区别吗?

在C++中,0.5的类型为 double0.5f 的类型为 float 。无法指定作为模板参数的类型的文本。在这种情况下,石膏是可以接受的。

我推荐static_cast而不是功能性风格的演员表。 decltype是不必要的,则相关类型已经有一个名称,T

因此,static_cast<T>(0.5)完全没问题。

从纯粹抽象的角度来看,有一个从doublefloat(或T表示的任何类型的(的转换。实际上,这种转换是无操作的。从编译器的角度来看,这是一个持续折叠的简单情况。

没有发生转换?

如果T是浮点数,则会发生转换。 0.5是一个双重常数。铸造它是一种转换。这是从纯粹的语言意义上说的。

唯一的问题是,你不是转换为T,而是转换为T const&(这就是decltype给出的(。从本质上讲,你实现了暂时的。

按值传递将避免这种情况,并使decltype(a)决心T。如果Tfloat,您将获得演员float(0.5)。这很可能会解析为与0.5f相同的常数。

以防万一(诚然不太可能(T 是易失性浮点数的情况,我可能倾向于将函数写成这样:

#include <type_traits>
template <typename T>
auto lerpMidway(const T& a, const T& b) -> std::decay_t<T>
{
    using type = std::decay_t<T>;
    const auto factor = type(0.5);
    type result;
    result = (b - a) * factor + a;
    return result;
}

因为decltype(a)const volatile float&,你不能把double 0.5 投射到那个。