10

我正在尝试找到在模板类方法中使用常量数字文字的解决方案。我正在制作一些与浮点或双精度类型一起使用的数学模板类。问题是文字因数据类型而异(例如,浮点数为“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() 方法。

还有另一种“更优雅”的方法来解决这个问题吗?

4

3 回答 3

1

谢谢大家的回答和评论。我允许自己对到目前为止所说的内容进行总结并添加我的结论。

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

是否使用 float 和 double 字面量?

关于是否费心为 float 和 double 使用单独的文字的话题略有讨论。这可能是由我在问题中给出的一个不幸的例子引起的。在示例中,文字无论如何都会在编译时转换为正确的类型,因此不会造成任何伤害。但一般情况下会出现需要在表达式中使用字面量的情况,例如:

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

这将强制编译器将 x 转换为双精度,进行计算,然后将结果转换回浮点数。这种行为的利弊:

优点:

  • 精度增益,因为实际计算将以双精度完成。

缺点:

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

总之,目标是使类实例化在正确的类型上工作,而无需任何额外的转换。在任何地方都使用双精度类型文字(例如 0.5)并保留对编译器的正确转换的想法不是一种选择。

关于这个主题的更多信息:我们通常应该对浮点数使用浮点文字而不是更简单的双精度文字吗?

可能的解决方案?

  • 为必须使用文字的每个模板实例化类型专门化方法。这可能是最糟糕的解决方案,因为它会强制编写两次相同的代码,并对文字进行微小的更改。
  • 制作专门getValue<type>()的方法,或者作为Jonathan Wakely 发布的- 专门的成员。这可能会导致类中有一些愚蠢的命名成员或方法,例如getZeroPointFive<float>().
  • Mohammad 和 Tony Delroy 指出,用包裹每个字面 static_cast<T>()量就可以了。转换为正确的类型将在编译时完成。
于 2012-06-19T18:40:42.043 回答
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;
于 2012-06-18T17:53:18.593 回答
0

您不必担心这一点 - 使用 0.5,如果类型是浮点数,编译器仍会将其最佳初始化为与使用 0.5f 相同的值。

这有点冗长,但您可能想在这里通读我的答案的“支持多态性的其他机制”部分:C++ 中的多态性

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

于 2012-06-18T17:51:36.113 回答