zoukankan      html  css  js  c++  java
  • 自动生成关联运算符 Anthony

    自动生成关联运算符

    自定义运算符是C++的一个特色。它可以使用很多操作变得直观,符合一般的思维方式:

    例如,在大多数语言中,对于int这样的内建类型(primary type)变量a,b,一个运算过程可以写成:a + b / a – 300,这与数学运算表达式完全一样。但对于非内建类型,比如Complex就不一定了。比如在Java中,它只能写成a.add(b.div(a).sub(300)),这就很难看了。而C++中可以通过自定义运算符实现与int类似的运算表达式。

    运算符的实现有一个重要的原则:不改变运算符的原意。不应该把“+”号重载成减法运算,也不应把“&&”定义为乘方,虽然这些重定义在语法上合法。这一原则的一个引申概念就是有关联的运算符其间的关系不应变化。“+=”和“+”就是一对关联运算,”<”,”>”,”<=””>=”也是一组相关联的运算。其关联关系是这样的:

    a = a + b 等价于 a += b

    a < b,也应有 b > a, b>= a, a<=b

    关联运算符应一起实现,为了保证其相关性不变,在一组关联运算符中只实现一个基本运算符,其它运算符都使用这个基本运算符实现。例如加法运算以+=为基本运算,而+调用+=运算符来实现。

    class A

    {

      A& operator+=(A const& a);

    };

    A operator+(A const& a, A const& b)

    {

       A result = a;

       result += b;

       return result;

    }

    关系运算符更是有一套模式化的实现方法。如果A定义了“<“号,则在STL中为它定义了如下模板。

    template <class _Tp>

    inline bool _STLP_CALL operator>(const _Tp& __x, const _Tp& __y) {

      return __y < __x;

    }

     

    template <class _Tp>

    inline bool _STLP_CALL operator<=(const _Tp& __x, const _Tp& __y) {

      return !(__y < __x);

    }

     

    template <class _Tp>

    inline bool _STLP_CALL  operator>=(const _Tp& __x, const _Tp& __y) {

      return !(__x < __y);

    }

    它们被定义在std::rel_ops命名空间中,要使用它们,需要在类中声明using namespace std::rel_ops

    这可以算是最基本的一个关联运算符生成器了,可惜它太少了一点,也不够灵活。不过在boost库中这个强大的功能被补全了,这就是boost::operators

    operator主要通过继承和友元来为类型提供运算符定义。

    用法1通过继承:

    class A : boost:: less_than_comparable<A>

    {

      friend bool operator<(A const&a, A const& b);

    };

    用法2通过模板友元:

    class A

    {

      friend bool operator<(A const&a, A const& b);

    };

     

    template boost:: less_than_comparable<A>; //显式实例化模板。

    boost:: less_than_comparable模板类提供了以下一组友元:

    friend bool operator>(const T& x, const T& y) { return y < x; }

        friend bool operator<=(const T& x, const T& y) { return !(y < x); }

        friend bool operator>=(const T& x, const T& y) { return !(x < y); }

    它们都依赖于A定义的operator<运算符。

    Boost不只提供只对于当前类型的运算符,还提供类型之间的运算符,如下代码。

    用法1通过继承:

    class A : boost:: less_than_comparable<A,B>

    {

      friend bool operator<(A const&a,  B const& b);

    friend bool operator>(A const&a,  B const& b);

    };

    用法2通过模板友元:

    class A

    {

      friend bool operator<(A const&a,  B const& b);

    friend bool operator>(A const&a,  B const& b);

    };

    template boost:: less_than_comparable<A, B>; //显式实例化模板。

     

    boost:: less_than_comparable<A,B>模板类提供了以下一组友元:

    bool operator<=(const T&, const U&)

    bool operator>=(const T&, const U&)

    bool operator>(const U&, const T&)

    bool operator<(const U&, const T&)

    bool operator<=(const U&, const T&)

    bool operator>=(const U&, const T&)

    以下是一张boost提供的模板,模板提供的运算符和模板所依赖的运算符的对应表。

     

    T: primary operand type U: alternate operand type t, t1: values of type T u: value of type U

    模板

    提供的操作符

    所依赖的运算符

    less_than_comparable<T>

    less_than_comparable1<T>

    bool operator>(const T&, const T&)
    bool operator<=(const T&, const T&)
    bool operator>=(const T&, const T&)

    t < t1.

    less_than_comparable<T, U>
    less_than_comparable2<T, U>

    bool operator<=(const T&, const U&)
    bool operator>=(const T&, const U&)
    bool operator>(const U&, const T&)
    bool operator<(const U&, const T&)
    bool operator<=(const U&, const T&)
    bool operator>=(const U&, const T&)

    t < u. t > u.

    equality_comparable<T>
    equality_comparable1<T>

    bool operator!=(const T&, const T&)

    t == t1.

    equality_comparable<T, U>
    equality_comparable2<T, U>

    bool operator==(const U&, const T&)
    bool operator!=(const U&, const T&)
    bool operator!=(const T&, const U&)

    t == u.

    addable<T>
    addable1<T>

    T operator+(const T&, const T&)

    T temp(t); temp += t1.
    返回值类型为T.

    addable<T, U>
    addable2<T, U>

    T operator+(const T&, const U&)
    T operator+(const U&, const T& )

    T temp(t); temp += u.
    返回值类型为T.

    subtractable<T>
    subtractable1<T>

    T operator-(const T&, const T&)

    T temp(t); temp -= t1.

    subtractable<T, U>
    subtractable2<T, U>

    T operator-(const T&, const U&)

    T temp(t); temp -= u.

    subtractable2_left<T, U>

    T operator-(const U&, const T&)

    T temp(u); temp -= t.

    multipliable<T>
    multipliable1<T>

    T operator*(const T&, const T&)

    T temp(t); temp *= t1.

    multipliable<T, U>
    multipliable2<T, U>

    T operator*(const T&, const U&)
    T operator*(const U&, const T&)

    T temp(t); temp *= u.

    dividable<T>
    dividable1<T>

    T operator/(const T&, const T&)

    T temp(t); temp /= t1.

    dividable<T, U>
    dividable2<T, U>

    T operator/(const T&, const U&)

    T temp(t); temp /= u.

    dividable2_left<T, U>

    T operator/(const U&, const T&)

    T temp(u); temp /= t.

    modable<T>
    modable1<T>

    T operator%(const T&, const T&)

    T temp(t); temp %= t1.

    modable<T, U>
    modable2<T, U>

    T operator%(const T&, const U&)

    T temp(t); temp %= u.

    modable2_left<T, U>

    T operator%(const U&, const T&)

    T temp(u); temp %= t.

    orable<T>
    orable1<T>

    T operator|(const T&, const T&)

    T temp(t); temp |= t1.

    orable<T, U>
    orable2<T, U>

    T operator|(const T&, const U&)
    T operator|(const U&, const T&)

    T temp(t); temp |= u.

    andable<T>
    andable1<T>

    T operator&(const T&, const T&)

    T temp(t); temp &= t1.

    andable<T, U>
    andable2<T, U>

    T operator&(const T&, const U&)
    T operator&(const U&, const T&)

    T temp(t); temp &= u.

    xorable<T>
    xorable1<T>

    T operator^(const T&, const T&)

    T temp(t); temp ^= t1.

    xorable<T, U>
    xorable2<T, U>

    T operator^(const T&, const U&)
    T operator^(const U&, const T&)

    T temp(t); temp ^= u.

    incrementable<T>

    T operator++(T&, int)

    T temp(t); ++t

    decrementable<T>

    T operator--(T&, int)

    T temp(t); --t;

    left_shiftable<T>
    left_shiftable1<T>

    T operator<<(const T&, const T&)

    T temp(t); temp <<= t1.

    left_shiftable<T, U>
    left_shiftable2<T, U>

    T operator<<(const T&, const U&)

    T temp(t); temp <<= u.

    right_shiftable<T>
    right_shiftable1<T>

    T operator>>(const T&, const T&)

    T temp(t); temp >>= t1.

    right_shiftable<T, U>
    right_shiftable2<T, U>

    T operator>>(const T&, const U&)

    T temp(t); temp >>= u.

    equivalent<T>
    equivalent1<T>

    bool operator==(const T&, const T&)

    t < t1.

    equivalent<T, U>
    equivalent2<T, U>

    bool operator==(const T&, const U&)

    t < u. t > u.

    partially_ordered<T>
    partially_ordered1<T>

    bool operator>(const T&, const T&)
    bool operator<=(const T&, const T&)
    bool operator>=(const T&, const T&)

    t < t1. t == t1.

    partially_ordered<T, U>
    partially_ordered2<T, U>

    bool operator<=(const T&, const U&)
    bool operator>=(const T&, const U&)
    bool operator>(const U&, const T&)
    bool operator<(const U&, const T&)
    bool operator<=(const U&, const T&)
    bool operator>=(const U&, const T&)

    t < u. t > u. t == u.

     

    对于同一个类要实现多组运算符,operators采用链式继承的方式,例如如果需要同时定义小于和等于符号。可以这样定义:

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

    {

      friend bool operator<(A const&a, A const& b);

    friend bool operator==(A const&a, A const& b);

    };

    如果是定义类型间的小于和等于,则是这样:

    class A : boost:: less_than_comparable<ABequality_comparable<AB> >

    {

      friend bool operator<(A const&a,  B const& b);

    friend bool operator>(A const&a,  B const& b);

    friend bool operator==(A const&a,  B const& b);

    };

    boost预先定义了一些组合运算模板,也可以直接使用它们,例如上面的类也可以定义为:

    class A : totally_ordered<T>

    {

      friend bool operator<(A const&a, A const& b);

    friend bool operator==(A const&a, A const& b);

    };

    以下是一个称为联合运算的组合运算模板的组成表:

    Template

    Component Operator Templates

    totally_ordered<T>
    totally_ordered1<T>

    · less_than_comparable<T>

    · equality_comparable<T>

    totally_ordered<T, U>
    totally_ordered2<T, U>

    · less_than_comparable<T, U>

    · equality_comparable<T, U>

    additive<T>
    additive1<T>

    · addable<T>

    · subtractable<T>

    additive<T, U>
    additive2<T, U>

    · addable<T, U>

    · subtractable<T, U>

    multiplicative<T>
    multiplicative1<T>

    · multipliable<T>

    · dividable<T>

    multiplicative<T, U>
    multiplicative2<T, U>

    · multipliable<T, U>

    · dividable<T, U>

    integer_multiplicative<T>
    integer_multiplicative1<T>

    · multiplicative<T>

    · modable<T>

    integer_multiplicative<T, U>
    integer_multiplicative2<T, U>

    · multiplicative<T, U>

    · modable<T, U>

    arithmetic<T>
    arithmetic1<T>

    · additive<T>

    · multiplicative<T>

    arithmetic<T, U>
    arithmetic2<T, U>

    · additive<T, U>

    · multiplicative<T, U>

    integer_arithmetic<T>
    integer_arithmetic1<T>

    · additive<T>

    · integer_multiplicative<T>

    integer_arithmetic<T, U>
    integer_arithmetic2<T, U>

    · additive<T, U>

    · integer_multiplicative<T, U>

    bitwise<T>
    bitwise1<T>

    · xorable<T>

    · andable<T>

    · orable<T>

    bitwise<T, U>
    bitwise2<T, U>

    · xorable<T, U>

    · andable<T, U>

    · orable<T, U>

    unit_steppable<T>

    · incrementable<T>

    · decrementable<T>

    shiftable<T>
    shiftable1<T>

    · left_shiftable<T>

    · right_shiftable<T>

    shiftable<T, U>
    shiftable2<T, U>

    · left_shiftable<T, U>

    · right_shiftable<T, U>

    ring_operators<T>
    ring_operators1<T>

    · additive<T>

    · multipliable<T>

    ring_operators<T, U>
    ring_operators2<T, U>

    · additive<T, U>

    · subtractable2_left<T, U>

    · multipliable<T, U>

    ordered_ring_operators<T>
    ordered_ring_operators1<T>

    · ring_operators<T>

    · totally_ordered<T>

    ordered_ring_operators<T, U>
    ordered_ring_operators2<T, U>

    · ring_operators<T, U>

    · totally_ordered<T, U>

    field_operators<T>
    field_operators1<T>

    · ring_operators<T>

    · dividable<T>

    field_operators<T, U>
    field_operators2<T, U>

    · ring_operators<T, U>

    · dividable<T, U>

    · dividable2_left<T, U>

    ordered_field_operators<T>
    ordered_field_operators1<T>

    · field_operators<T>

    · totally_ordered<T>

    ordered_field_operators<T, U>
    ordered_field_operators2<T, U>

    · field_operators<T, U>

    · totally_ordered<T, U>

    euclidian_ring_operators<T>
    euclidian_ring_operators1<T>

    · ring_operators<T>

    · dividable<T>

    · modable<T>

    euclidian_ring_operators<T, U>
    euclidian_ring_operators2<T, U>

    · ring_operators<T, U>

    · dividable<T, U>

    · dividable2_left<T, U>

    · modable<T, U>

    · modable2_left<T, U>

    ordered_euclidian_ring_operators<T>
    ordered_euclidian_ring_operators1<T>

    · euclidian_ring_operators<T>

    · totally_ordered<T>

    ordered_euclidian_ring_operators<T, U>
    ordered_euclidian_ring_operators2<T, U>

    · euclidian_ring_operators<T, U>

    · totally_ordered<T, U>

    与其它boost库一样,operators要求支持C++98标准的编译器,现在完全支持的编译器有VC7.1GCC3.3EGD 2.5以上。通过一定的方式支持GCC2.95VC6 sp3以上。

      对于完全支持的编译器,推荐使用operatorable<T>operatorable<T, U>模板。对于不完全支持的编译器,可以使用operatorable1<T>operatorable2<T,U>这两个接口。

     

  • 相关阅读:
    蓝桥题库基础练习1-10
    HTML5(八)Web Workers
    对自动化测试工具的实战运用
    对自动化测试工具的简要认识
    HTML5(七)Web 存储
    蓝桥杯javaB组入坑
    Google Play内购测试
    【python】python中的json、字典dict
    【python】python之tuple元组
    性能测试基础知识
  • 原文地址:https://www.cnblogs.com/ahuangliang/p/5309272.html
Copyright © 2011-2022 走看看