c++ - 用作模板参数以比较 double 值的类型

标签 c++ templates

我得到了这个 n 维点对象:

template <class T, unsigned int dimension> class Obj {
protected:
    T coords[dimension];
    static const unsigned int size = dimension;
public:
    Obj() { };
    Obj(T def) { for (unsigned int i = 0; i < size; ++i) coords[i]=def; };
    Obj(const Obj& o) { for (unsigned int i = 0; i < size; ++i) coords[i] = o.coords[i]; }
    const Obj& operator= (const Obj& rhs) { if (this != &rhs) for (unsigned int i = 0; i < size; ++i) coords[i] = rhs.coords[i]; return *this; }


    virtual ~Obj() {  };
    T get (unsigned int id) { if (id >= size) throw std::out_of_range("out of range"); return coords[id]; }
    void set (unsigned int id, T t) { if (id >= size) throw std::out_of_range("out of range"); coords[id] = t; }

};

和一个使用 Obj 作为基类的 3D 点类:

template <class U> class Point3DBase : public Obj<U,3> {
    typedef U type;

public:
    U &x, &y, &z;
public:
    Point3DBase() : x(Obj<U,3>::coords[0]), y(Obj<U,3>::coords[1]), z(Obj<U,3>::coords[2]) { };
    Point3DBase(U def) : Obj<U,3>(def), x(Obj<U,3>::coords[0]), y(Obj<U,3>::coords[1]), z(Obj<U,3>::coords[2]) { };
    Point3DBase(U x_, U y_, U z_) : x(Obj<U,3>::coords[0]), y(Obj<U,3>::coords[1]), z(Obj<U,3>::coords[2])  { x = x_; y = y_; z= z_; };
    Point3DBase(const Point3DBase& other) : x(Obj<U,3>::coords[0]), y(Obj<U,3>::coords[1]), z(Obj<U,3>::coords[2]) { x = other.x; y = other.y; z = other.z; }
// several operators ...
};

运算符,基本上是用于比较的运算符,使用简单的成员对象比较方法,例如:

friend bool operator== (const Point3DBase<U> &lhs, const Point3DBase<U> rhs) { return (lhs.x ==  rhs.x && lhs.y == rhs.y && lhs.z == rhs.z); }

然后我想到,对于 double 值的比较,简单的相等方法不是很有用,因为 double 值应该与误差范围进行比较。将误差范围引入该点的最佳方法是什么?我考虑过将 epsDouble 类型作为模板参数,但我不知道如何实现。

编辑:

我见过链式输出流运算符调用输出流运算符类型的输出流运算符...有没有办法将比较委托(delegate)给表示浮点类型的自定义类型?

最佳答案

如果你想要一个给定浮点类型的所有实例的一个 epsilon 值,其实很简单:

template <>
bool operator<(const Point3DBase<double>& lhs, const Point3DBase<double>& rhs)
{
}

如果没有,那么我将引导您使用基于策略的设计,正如 Alexandrescu 所展示的:

namespace detail
{
  template <class U>
  struct DefaultComparator: std::binary_function<bool, U, U>
  {
    bool operator()(U lhs, U rhs) const { return lhs < rhs; }
  };
}

template < class U, class Comparator = detail::DefaultComparator<U> >
class Point3DBase;

template < class U, class C>
bool operator<(Point3DBase<U,C> const& lhs, Point3DBase<U,C> const& rhs)
{
  return C()(lhs,rhs);
}

请注意,您仍然可以通过特化 DefaultComparator 来定义安全默认值

namespace detail
{
  template <>
  struct DefaultComparator<float> {};

  template <>
  struct DefaultComparator<double> {};
}

根据这个定义,不可能使用operator==没有通过 Comparator参数自己。另一种解决方案是允许它,但在上面两个特化的定义中提供一个默认的 epsilon。

所有其他操作 ( >, <=, >=, ==, != ) 都可以从 < 中简单地导出(尽管可能效率不高) ,例如从 boost::equality_comparable 派生和/或 boost::less_than_comparable .

关于c++ - 用作模板参数以比较 double 值的类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2731210/

相关文章:

c++ - 什么是 Mixin(作为一个概念)

c++ - 将字符串转换为 double ——失去精度

c++ - 如何访问局部范围内的全局变量?

C++ 模板特化链接器错误

html - 在 Polymer.dart 中使用列表

c++ - 如何判断是否已创建/初始化 MFC 对话框?

c++ - 以下函数的时间复杂度应该是多少?

c++ - 可变参数模板索引包扩展

templates - Go 模板 : How do I access array item (arr[2]) in templates?

c++ - 为什么非模板类要在头文件和源文件中分开?