我得到了这个 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/