boost工具 operators系列操作、基类链技术使用

boost中operators库提供了一系列的操作符重载自动生成工具类,只需要提供少量操作即可自动重载其他操作符。

我们先来看两段源码:

template <class T, class U, class B = ::boost::detail::empty_base<T> >
struct less_than_comparable2 : B
{
     friend bool operator<=(const T& x, const U& y) { return !static_cast<bool>(x > y); }
     friend bool operator>=(const T& x, const U& y) { return !static_cast<bool>(x < y); }
     friend bool operator>(const U& x, const T& y)  { return y < x; }
     friend bool operator<(const U& x, const T& y)  { return y > x; }
     friend bool operator<=(const U& x, const T& y) { return !static_cast<bool>(y < x); }
     friend bool operator>=(const U& x, const T& y) { return !static_cast<bool>(y > x); }
};

template <class T, class B = ::boost::detail::empty_base<T> >
struct less_than_comparable1 : B
{
     friend bool operator>(const T& x, const T& y)  { return y < x; }
     friend bool operator<=(const T& x, const T& y) { return !static_cast<bool>(y < x); }
     friend bool operator>=(const T& x, const T& y) { return !static_cast<bool>(x < y); }
};

template <class T, class U, class B = ::boost::detail::empty_base<T> >
struct equality_comparable2 : B
{
     friend bool operator==(const U& y, const T& x) { return x == y; }
     friend bool operator!=(const U& y, const T& x) { return !static_cast<bool>(x == y); }
     friend bool operator!=(const T& y, const U& x) { return !static_cast<bool>(y == x); }
};

template <class T, class B = ::boost::detail::empty_base<T> >
struct equality_comparable1 : B
{
     friend bool operator!=(const T& x, const T& y) { return !static_cast<bool>(x == y); }
};

less_than_comparable2 与 less_than_comparable1提供比较操作重载,由源码可知两个工具类的重载主要借助operator<操作符实现。

与此类似,quality_comparable2与equality_comparable1提供相等操作的重载,其借助operator==操作符实现。

typename##2系列与typename##1系列不同在于前者提供相异类型的操作符重载。算是一种扩充。

缺省模板参数 empty_base确实是空类,其作用随后再讲。

我们如何使用operator库呢?下面是示例

#include <boost/operators.hpp>
class point : boost::equality_comparable<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; }

    friend bool operator<(const point& l, const point& r)//支持less_than_comparable
    {
        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);
    }
}

operator<必须声明为友元,因为在重载工具类中要使用该操作符。
当类继承自boost::equality_comparable并且定义了operator< 其”>”,”<=”,”>==”操作符都已经被自动重载。

编译器如何通过equality_comparable来自动匹配less_than_comparable2 或less_than_comparable1?

源码中有如下系列声明:

BOOST_OPERATOR_TEMPLATE(less_than_comparable)
BOOST_OPERATOR_TEMPLATE(equality_comparable)
...

宏展开如下:

# define BOOST_OPERATOR_TEMPLATE(template_name)                    \
template <class T                                                  \
         ,class U = T                                              \
         ,class B = ::boost::detail::empty_base<T>                 \
         ,class O = typename is_chained_base<U>::value             \
         >                                                         \
struct template_name : template_name##2<T, U, B> {};               \
                                                                   \
template<class T, class U, class B>                                \
struct template_name<T, U, B, ::boost::detail::true_t>             \
  : template_name##1<T, U> {};                                     \
                                                                   \
template <class T, class B>                                        \
struct template_name<T, T, B, ::boost::detail::false_t>            \
  : template_name##1<T, B> {};                                     \
                                                                   \
template<class T, class U, class B, class O>                       \
struct is_chained_base< ::boost::template_name<T, U, B, O> > {     \
  typedef ::boost::detail::true_t value;                           \
};                                                                 \

该宏操作声明了多组操作符重载模板,编译时自动匹配对应模板。
接下来我们扩充class point功能:

class point :boost::less_than_comparable<point>,
    boost::equality_comparable<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; }

    friend bool operator<(const point& l, const point& r)//支持less_than_comparable
    {
        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);
    }
    friend bool operator==(const point& l, const point& r)//支持equality_comparable
    {
        return l.x == r.x && l.y == r.y && l.z == r.z;
    }
}

此时class point已经支持 “<”,”>”,”>=”,”<=”,”==”,”!=”这些操作符。

C++支持多重继承,但是多重继承本身有可能导致钻石继承、优化困难等问题,为此泛型编程有种技术叫做”基类链”来解决多重继承的问题。相当于从一对多的聚集状继承模型转换为了单链式继承模型。子类本身只有一个父类,却拥有上层父类所有特性。
前面我们提到重载模板有个模板参数class B ,通常设置为empty class。他主要用于基类链技术。
如上例中:

class point :boost::less_than_comparable<point>,
    boost::equality_comparable<point>

其等价于如下写法:

class point :boost::less_than_comparable<point, boost::equality_comparable<point>>//基类链

boost::equality_comparable取代了 empty_base的位置,避免了多重继承。

//基类链技术使用示例
class empty_class {};

template<typename T = empty_class>
class function_class1:  public T
{
public:
    void do_something(){}
};

template<typename T = empty_class>
class function_class2: public T
{
public:
    void do_anotherthing(){}
};

class your_class : public function_class2<function_class1<>>
{
public:
    void your_work_func(){}
};

void test_func()
{
    your_class you;
    you.do_something();
    you.do_anotherthing();
    you.your_work_func();
}

其他操作如totally_ordered( 全序概念(比较操作))、additive(可加减操作)等读者可查阅相关资料学习。

部分代码示例来自《Boost程序库完全开发指南:深入C++_准备标准库 第3版》

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值