自动生成关联运算符
自定义运算符是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&) | t < t1. |
less_than_comparable<T, U> | bool operator<=(const T&, const U&) | t < u. t > u. |
equality_comparable<T> | bool operator!=(const T&, const T&) | t == t1. |
equality_comparable<T, U> | bool operator==(const U&, const T&) | t == u. |
addable<T> | T operator+(const T&, const T&) | T temp(t); temp += t1. |
addable<T, U> | T operator+(const T&, const U&) | T temp(t); temp += u. |
subtractable<T> | T operator-(const T&, const T&) | T temp(t); temp -= t1. |
subtractable<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> | T operator*(const T&, const T&) | T temp(t); temp *= t1. |
multipliable<T, U> | T operator*(const T&, const U&) | T temp(t); temp *= u. |
dividable<T> | T operator/(const T&, const T&) | T temp(t); temp /= t1. |
dividable<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> | T operator%(const T&, const T&) | T temp(t); temp %= t1. |
modable<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> | T operator|(const T&, const T&) | T temp(t); temp |= t1. |
orable<T, U> | T operator|(const T&, const U&) | T temp(t); temp |= u. |
andable<T> | T operator&(const T&, const T&) | T temp(t); temp &= t1. |
andable<T, U> | T operator&(const T&, const U&) | T temp(t); temp &= u. |
xorable<T> | T operator^(const T&, const T&) | T temp(t); temp ^= t1. |
xorable<T, U> | T operator^(const T&, const U&) | 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> | T operator<<(const T&, const T&) | T temp(t); temp <<= t1. |
left_shiftable<T, U> | T operator<<(const T&, const U&) | T temp(t); temp <<= u. |
right_shiftable<T> | T operator>>(const T&, const T&) | T temp(t); temp >>= t1. |
right_shiftable<T, U> | T operator>>(const T&, const U&) | T temp(t); temp >>= u. |
equivalent<T> | bool operator==(const T&, const T&) | t < t1. |
equivalent<T, U> | bool operator==(const T&, const U&) | t < u. t > u. |
partially_ordered<T> | bool operator>(const T&, const T&) | t < t1. t == t1. |
partially_ordered<T, U> | bool operator<=(const T&, const U&) | 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<A,B,equality_comparable<A,B> >
{
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> | · less_than_comparable<T> · equality_comparable<T> |
totally_ordered<T, U> | · less_than_comparable<T, U> · equality_comparable<T, U> |
additive<T> | · addable<T> · subtractable<T> |
additive<T, U> | · addable<T, U> · subtractable<T, U> |
multiplicative<T> | · multipliable<T> · dividable<T> |
multiplicative<T, U> | · multipliable<T, U> · dividable<T, U> |
integer_multiplicative<T> | · multiplicative<T> · modable<T> |
integer_multiplicative<T, U> | · multiplicative<T, U> · modable<T, U> |
arithmetic<T> | · additive<T> · multiplicative<T> |
arithmetic<T, U> | · additive<T, U> · multiplicative<T, U> |
integer_arithmetic<T> | · additive<T> · integer_multiplicative<T> |
integer_arithmetic<T, U> | · additive<T, U> · integer_multiplicative<T, U> |
bitwise<T> | · xorable<T> · andable<T> · orable<T> |
bitwise<T, U> | · xorable<T, U> · andable<T, U> · orable<T, U> |
unit_steppable<T> | · incrementable<T> · decrementable<T> |
shiftable<T> | · left_shiftable<T> · right_shiftable<T> |
shiftable<T, U> | · left_shiftable<T, U> · right_shiftable<T, U> |
ring_operators<T> | · additive<T> · multipliable<T> |
ring_operators<T, U> | · additive<T, U> · subtractable2_left<T, U> · multipliable<T, U> |
ordered_ring_operators<T> | · ring_operators<T> · totally_ordered<T> |
ordered_ring_operators<T, U> | · ring_operators<T, U> · totally_ordered<T, U> |
field_operators<T> | · ring_operators<T> · dividable<T> |
field_operators<T, U> | · ring_operators<T, U> · dividable<T, U> · dividable2_left<T, U> |
ordered_field_operators<T> | · field_operators<T> · totally_ordered<T> |
ordered_field_operators<T, U> | · field_operators<T, U> · totally_ordered<T, U> |
euclidian_ring_operators<T> | · ring_operators<T> · dividable<T> · modable<T> |
euclidian_ring_operators<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> | · euclidian_ring_operators<T> · totally_ordered<T> |
ordered_euclidian_ring_operators<T, U> | · euclidian_ring_operators<T, U> · totally_ordered<T, U> |
与其它boost库一样,operators要求支持C++98标准的编译器,现在完全支持的编译器有VC7.1,GCC3.3,EGD 2.5以上。通过一定的方式支持GCC2.95和VC6 sp3以上。
对于完全支持的编译器,推荐使用operatorable<T>和operatorable<T, U>模板。对于不完全支持的编译器,可以使用operatorable1<T>和operatorable2<T,U>这两个接口。