【问题标题】:How can I define floating point constants depending on template type?如何根据模板类型定义浮点常量?
【发布时间】:2019-11-25 12:51:10
【问题描述】:

在我的代码中,我有很多模板算法,其中模板类型必须是浮点数(floatdoublelong double)。其中一些算法需要默认的 epsilon 值。示例:

template <typename FloatType>
bool approx(FloatType x1, FloatType x2)
{
  const FloatType epsilon; // How can I set it ?
  return abs(x2 - x1) < epsilon;
}

我该如何定义它?我尝试了以下方法,它被 gcc 接受,但它不是标准的(并且在 C++11 中无效)。我知道在 C++11 中是可能的,但我必须与 c++03 兼容。

template <typename FloatType>
struct default_epsilon
{};

template <>
struct default_epsilon<float>
{
  static const float value = 1.0e-05f;
};

template <>
struct default_epsilon<double>
{
  static const double value = 1.0e-10;
};

template <>
struct default_epsilon<long double>
{
  static const long double value = 1.0e-12l;
};

// Then, I use it like that :
template <typename FloatType>
bool approx(FloatType x1, FloatType x2)
{
  return abs(x2 - x1) < default_epsilon<FloatType>::value;
}
// or that
bool approx(FloatType x1, FloatType x2, FloatType epsilon = default_epsilon<FloatType>::value)
{
  return abs(x2 - x1) < epsilon;
}

【问题讨论】:

  • 像 numeric_limits 一样,使用(内联)函数。
  • 但这不是标准的 为什么? 我必须与 c++03 兼容。 自 C++11 以来,C++ 中没有模板特化,它也在 C++03 中。
  • @AProgrammer,这不是我喜欢的解决方案,因为我不能将它用作函数声明中的默认参数值。
  • @Caduchon 所以在类定义之外初始化那些静态常量。
  • @Caduchon,为什么你认为你不能使用函数调用作为默认参数? AFAIK,这从来都不是真的。

标签: c++ templates constants c++03


【解决方案1】:

如果你不想使用std::numeric_limits&lt;FloatType&gt;::epsilon(),我认为你可以按照cmets中的建议:在类定义之外初始化static成员。

你可以写:

#include <cmath>

template <typename FloatType>
struct default_epsilon
{};

template <>
struct default_epsilon<float>
{
    static const float value;
};
template <>
struct default_epsilon<double>
{
    static const double value;
};
template <>
struct default_epsilon<long double>
{
    static const long double value;
};

template <typename FloatType>
bool approx(FloatType x1, FloatType x2)
{
    return std::abs(x2 - x1) < default_epsilon<FloatType>::value;
}

在您的 .cpp 文件中的某处:

const float default_epsilon<float>::value = 1.0e-05f;
const double default_epsilon<double>::value = 1.0e-10;
const long double default_epsilon<long double>::value = 1.0e-12l;

它应该可以解决问题。

【讨论】:

    【解决方案2】:

    使用传统的 c++ 强制转换运算符重载

    class MyEpsilon
    {
    public:
        operator float() {return 1.0e-05f;};
        operator double() { return 1.0e-10; };
        operator long double() { return 1.0e-12l; };
    };
    
    template<class T>
    class MyTest {
    public:
        T DoSome() {
            MyEpsilon e;
            return T(e);
        }
    };
    

    【讨论】:

      猜你喜欢
      • 2012-08-05
      • 1970-01-01
      • 2013-05-22
      • 2019-04-23
      • 2020-09-11
      • 1970-01-01
      • 2016-03-05
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多