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

时间:2018-01-02 07:58:15

标签: c++ templates generics

在我的职能中:

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来初始化它并没有什么区别?

3 个答案:

答案 0 :(得分:7)

在C ++中,0.5的类型为double,而0.5f的类型为float。无法指定作为模板参数的类型的文字。在这种情况下,演员阵容是可以接受的。

我推荐static_cast而不是功能样式。 decltype是不必要的,相关类型已经有一个名称T

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

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

答案 1 :(得分:4)

  

没有转换发生?

如果T是浮点数,那么就会发生转化。 0.5是一个双常数。投射它是一种转换。那是纯粹的语言意义。

唯一的问题是,您没有转换为T,而是转换为T const&(这是decltype给出的)。基本上,你实现了一个临时的。

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

答案 2 :(得分:0)

如果(事实上不太可能)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强制转换为{{1}}。