自動生成關聯運算符

自動生成關聯運算符

自定義運算符是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>這兩個接口。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章