float和double文字的模板类中的函数特化

时间:2012-06-18 17:34:48

标签: c++ function templates literals specialization

我正在尝试找到一个解决方案,在模板类方法中包含常量数字文字。我正在制作一些与float或double类型一起使用的数学模板类。问题是文字因数据类型而异(例如浮点数为“0.5f”,双数字为“0.5”)。到目前为止,我提出了两个解决方案。第一个假设代码:

template <typename T>
class SomeClass
{
    public:
        T doSomething(T x);
};

template <>
float SomeClass<float>::doSomething(float x)
{
    float y = 0.5f;
    /*
     * Do computations...
    */
    return x;
}

template <>
double SomeClass<double>::doSomething(double x)
{
    double y = 0.5;
    /*
     * Do computations...
    */
    return x;
}

上述方法强制重写与其一起使用的每种类型的整个方法。

另一种方法:

template <typename T>
class SomeClass
{
    public:
        T doSomething(T x);

    private:
        T getValue();
};

template <typename T>
T SomeClass<T>::doSomething(T x)
{
    T y = getValue();
    /*
     * Do computations...
    */
    return x;
}

template <>
float SomeClass<float>::getValue()
{
    return 0.5f;
}

template <>
double SomeClass<double>::getValue()
{
    return 0.5;
}

这个方法不需要为特定类型多次编写相同的方法,但需要为方法内部需要使用的每个“幻数”设置很多getValue()方法。

还有另一种“更优雅”的解决方法吗?

3 个答案:

答案 0 :(得分:1)

假设实际上有必要在两个特化中使用不同的值(例如,对于0.5和0.5f不是必需的),那么打字的次数要少得多:

template <typename T>
class SomeClass
{
  public:
    T doSomething(T x);

  private:
    static const T magic_number_1;
};

template <typename T>
T SomeClass<T>::doSomething(T x)
{
  T y = magic_number_1;
  /* 
   * Do computations...
  */
  return x;
}

template <>
const float SomeClass<float>::magic_number_1 = 0.5f;

template <>
const double SomeClass<double>::magic_number_1 = 0.5;

答案 1 :(得分:1)

谢谢大家的回答和评论。我允许自己对迄今所说的内容进行总结并加上我的结论。

我将实现一些数学类模板来实例化以用于float或double类型。需要在类中内部使用一些数字文字。它们将是一些常用的数字文字和常量,例如0.0,0.5,1.0,pi等。我正在寻找一种解决方案,使类实例化根据其类型在不同的文字上工作。

是否使用float和double literals?

关于是否要为float和double使用单独的文字而烦恼的话题。这可能是由我在我的问题中给出的一个不幸的例子引起的。在示例中,无论如何,文字将在编译时转换为正确的类型,因此不会造成任何损害。但总的来说,有些情况需要在表达中使用字面值,例如:

float foo(float x)
{
    return x * 3.14;
}

这会强制编译器将x转换为double,进行计算,然后将结果转换回float。这种行为的利弊:

优点:

  • 精确增益,因为实际计算将以double进行 精度。

缺点:

  • 如果性能问题,这可能会导致更快 执行速度较慢,具体取决于环境和平台。这个 根据实现引入了一些性能变化 就我而言,是坏事。
  • 介绍计算不一致,因为有些操作会 根据文字使用,在浮点数和一些双打上完成。这个 也可能会暴露一些漏洞。
  • 它首先打破了专门用于浮动类的想法 因为内部计算无论如何都会在双打上完成。

总之,目标是使类实例化在适当的类型上工作,而无需任何额外的转换。在任何地方都使用双重类型文字的想法,例如0.5和处理正确转换到编译器不是一种选择。

有关此主题的更多信息:Should we generally use float literals for floats instead of the simpler double literals?

可能的解决方案?

  • 为每个模板实例化类型专门化方法 必须使用文字。这可能是最糟糕的解决方案因为它 强制两次写相同的代码,并对其进行微小的更改 文字。
  • 制作专门的getValue<type>()方法,或Jonathan Wakely posted - 专用 成员。这可能会导致一些愚蠢的命名成员或方法 在课堂上,例如getZeroPointFive<float>()
  • Mohammad和Tony Delroy指出用每个文字包装 static_cast<T>()会做到这一点。转换为适当的类型将 在编译时完成。

答案 2 :(得分:0)

您只需要担心这一点 - 使用0.5,如果类型为float,编译器仍会以最佳方式将其初始化为与使用0.5f时相同的值。

这有点啰嗦,但您可能希望通过“我支持多态”的其他机制来阅读我的答案:Polymorphism in c++

对于整个函数中float常量的更一般用法 - 特别是在比较和表达式中 - 值得阅读下面的bluemess提及的链接....