4.8.2 算术操作符的用法
我们使用之前4.5.3节定义的三维空间的点point作为opreators库的示范类,在此把它重新定义如下(去掉了swap函数):
- class point
- {
- int x, y, z;
- public:
- explicit point(int a=0, int b=0, int c=0):x(a),y(b),z(c){}
- void print()const
- { cout << x <<","<< y <<","<< z << endl; }
- };
我们先来实现less_than_comparable,它要求point类提供<操作符,并由它继承。假定point的小于关系是三个坐标值的平方和决定的,下面的代码示范了less_than_comparable的用法,只需要为point增加父类,并定义less_than_comparable概念所要求的operator<: - #include <boost/operators.hpp>
- class point:
- boost::less_than_comparable<point> //小于关系,私有继承
- {
- public:
- friend bool operator<(const point& l, const point& r)
- {
- return (l.x*l.x + l.y*l.y +l.z*l.z <
- r.x*r.x + r.y*r.y +r.z*r.z);
- }
- ... //其他成员函数
- };
less_than_comparable作为基类的用法可能稍微有点奇怪,它把子类point作为了父类的模板参数:less_than_comparable,看起来好像是个"循环继承"。实际上,point类作为less_than_comparable的模板类型参数,只是用来实现内部的比较操作符,用作操作符函数的类型,没有任何继承关系。less_than_comparable生成的代码可以理解成这样 :- //template<TT = point>
- struct less_than_comparable
- {
- friend bool operator>=(const point& x, const point& y)
- { return !(x < y); }
- }
明白了less_than_comparable的继承用法,剩下的就很简单了:point类定义了一个友元operator<操作符,然后其余的>、<=、>=就由less_than_comparable自动生成。几乎不费什么力气,在没有污染名字空间的情况下我们就获得了四个操作符的能力:- int main()
- {
- point p0, p1(1,2,3), p2(3,0,5), p3(3,2,1);
-
- assert(p0 < p1 && p1 < p2);
- assert(p2 > p0);
- assert(p1 <= p3);
- assert(!(p1<p3)&&!(p1>p3) );
- }
同样我们可以定义相等关系,使用equality_comparable,规则是point的三个坐标值完全相等,需要自行实现operator==: - class point:boost::less_than_comparable<point> //使用多重继承
- ,boost::equality_comparable<point> //新增相等关系
- {
- public:
- friend bool operator<(const point& l, const point& r)
- { /*同前*/ }
- friend bool operator==(const point& l, const point& r)
- { return r.x == l.x && r.y == l.y && r.z == l.z; }
- };
然后我们就自动获得了operator!=的定义:- point p0, p1(1,2,3), p2(p1), p3(3,2,1);
- assert(p1 == p2);
- assert(p1 != p3);
在使用operators库时要注意一点,模板类型参数必须是子类自身,特别是当子类本身也是个模板类的时候,不要错写成子类的模板参数或者子类不带模板参数的名称,否则会造成编译错误。假如我们改写point类为一个模板类:- template<typename T> class point {...}
那么如下的形式都是错误的:- template<typename T> class point:boost::less_than_comparable<T>
- template<typename T> class point:boost::less_than_comparable<point>
正确的写法应该是:- template<typename T> class point:boost::less_than_comparable< point<T> >
因为只有point才是模板类point的全名。