4.8.4 复合运算概念
基类链技术解决了多重继承的效率问题,但它也带来了新的问题,为了使用操作符概念需要写出很长的基类链代码。因此operators库使用基类链把一些简单的运算概念组合成了复杂的概念,即复合运算。这是个很自然的要求,如果有<,当然会需要==,如果有了+,可能还需要-、*和/。复合运算不仅进一步简化了代码的编写,给出了更明确的语义,它也可以避免用户代码中基类链过长的问题。
operators库提供的常用复合运算概念如下:
totally_ordered:全序概念,组合了equality_comparable和less_than_comparable;
additive:可加减概念,组合了addable和subtractable;
multiplicative:可乘除概念,组合了multipliable和dividable;
arithmetic:算术运算概念,组合了additive和multiplicative;
unit_stoppable:可步进概念,组合了incrementable和decrementable。
使用复合运算概念,point类只需要很少的代码就可以很容易地获得完全的算术运算能力:
- class point:
- totally_ordered<point, //全序比较运算
- additive<point> > //可加减运算
- {
- public:
- friend bool operator<(const point& l, const point& r)
- {...}
- friend bool operator==(const point& l, const point& r)
- {...}
- point& operator+=(const point& r) //支持addable概念
- {
- x += r.x;
- y += r.y;
- z += r.z;
- return *this;
- }
- point& operator-=(const point& r) //支持subtractable概念
- {
- x -= r.x;
- y -= r.y;
- z -= r.z;
- return *this;
- }
- };
point的操作符重载验证代码如下: - point p0, p1(1,2,3), p2(5,6,7), p3(3,2,1);
-
- using namespace boost::assign;
- vector<point> v = (list_of(p0), p1, p2, p3);
-
- BOOST_AUTO(pos, std::find(v.begin(), v.end(), point(1,2,3))); //find算法使用operator==
- pos->print();
-
- (p1 + p2).print(); //operator+
- (p3 - p1).print(); //operator-
-
- assert((p2 - p2) == p0); //operator-和operator==
point类很好地示范了复合运算操作符的用法:一般情况下,类型T继承boost:: totally_ordered<T>,再定义<、==操作符即可获得完全的比较运算功能,能够用于标准容器和算法。
operators库另一个例子是将在9.2节(第344页)介绍的rational类,它实现了有理数,支持全序和算术运算,不过很可惜的是它虽然使用了operators库,但没有用到复合运算概念,从而导致基类声明有16个">"!