boost gemotry
2.设计原理假设你需要一个C++程序计算两点间的距离,你可能会定义一个结构体:
struct mypoint { double x, y; };
和一个函数,包含这个算法:
double distance(mypoint const& a, mypoint const& b) { double dx = a.x - b.x; double dy = a.y - b.y; return sqrt(dx * dx + dy * dy); }
非常简单,它是可用的,但不是通用的。对于库来说,它必须进一步设计。上述设计只能用于笛卡尔坐标系中的二维点、结构mypoint(而不是其他结构)。通用库应能够计算距离:
对于任何point类或结构,而不仅仅是此mypoint类型
在两个以上的维度上
对于其他坐标系,例如地球上方或球体上
点与线之间或其他几何图形组合之间
以比双精度更高的精度
避免平方根:我们通常不想这样做,因为这是一个相对昂贵的函数,而比较距离则没有必要
在本节和后续章节中,我们将逐步使设计更通用。
2.1使用模板距离函数可以变成一个模板函数。这很简单,可以计算除mypoint之外的其他点类型之间的距离。我们添加了两个模板参数,允许输入两种不同的点类型。
templatedouble distance(P1 const& a, P2 const& b) { double dx = a.x - b.x; double dy = a.y - b.y; return std::sqrt(dx * dx + dy * dy); }
这个模板版本稍微好一点,但不多。
考虑一个C++类,其中成员变量受到保护…这样的类不允许直接访问x和y成员。所以,这一段很短,我们继续。
2.2使用Traits我们需要采用一种通用方法,允许任何点类型作为距离函数的输入。我们将使用traits系统添加几个级别的间接寻址,而不是访问x和y成员。然后,该函数变为:
templatedouble distance(P1 const& a, P2 const& b) { double dx = get<0>(a) - get<0>(b); double dy = get<1>(a) - get<1>(b); return std::sqrt(dx * dx + dy * dy); }
此调整后的距离函数使用一个通用get函数,用维度作为模板参数,以访问点的坐标。这将转到traits系统,定义如下:
namespace traits { templatestruct access {}; }
然后专门用于mypoint类型,实现一个名为get的静态方法:
namespace traits { template <> struct access{ static double get(mypoint const& p) { return p.x; } }; // same for 1: p.y ... }
调用traits::access
templateinline double get(P const& p) { return traits::access ::get(p); }
这使我们能够为任何具有traits::access专门化的点调用get<0>(a),如本段开头的距离算法所示。因此,我们希望使用x()之类的方法来启用类,只要access结构有专门化,并且有一个静态get函数为维度0返回x(),为维度1和y()返回类似的x(),就可以支持这些类。
2.3维度不可知论Traits?
C++ traits技术浅谈
现在我们可以计算2D中点之间的距离,任何结构或类的点。然而,我们也想要3D。因此,我们必须使其维度不可知。这使我们的距离函数变得复杂。我们可以使用for循环遍历维度,但是for循环有另一种性能,而不是最初直接添加坐标。但是,我们可以更多地使用模板,并使距离算法如下,更复杂,但对模板迷有吸引力:
templatestruct pythagoras { static double apply(P1 const& a, P2 const& b) { double d = get (a) - get (b); return d * d + pythagoras ::apply(a, b); } }; template struct pythagoras { static double apply(P1 const&, P2 const&) { return 0; } };
距离函数正在调用pythagoras结构,指定维度数:
templatedouble distance(P1 const& a, P2 const& b) { BOOST_STATIC_ASSERT(( dimension ::value == dimension ::value )); return sqrt(pythagoras ::value>::apply(a, b)); }
上面提到的dimension,使用traits类定义:
namespace traits { templatestruct dimension {}; }
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)