自动生成关联运算符

原创 2004年08月19日 14:09:00

自动生成关联运算符

自定义运算符是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>这两个接口。

 

关于C++成员函数和运算符的重载

1.为啥要重载操作符: 通过重载操作符,程序员可以针对“类”类型的操作数定义不同的操作符版本。良好的操作符定义可以使class类型的使用想内置类型一样直观简洁,使用重定义的操作符而不是命名函数使得...
  • lurendetiankong
  • lurendetiankong
  • 2016年11月10日 19:36
  • 1465

Java进行三目运算时的自动类型转换

今天看到两个面试题,居然都做错了。通过这两个面试题,也加深对三目运算是的自动类型转换的理解。 题目1.以下代码输出结果是()。 public class Test { public st...
  • wyqihsj
  • wyqihsj
  • 2015年11月03日 21:29
  • 1553

loadrunner--终于关联成功了

学习手动关联 使用自带的扫描关联
  • jianglai3289
  • jianglai3289
  • 2016年11月21日 10:30
  • 3240

Thinkphp3.2.3 解决关联模型的自动生成问题($_auto)

Thinkphp 关联模型 自动生成
  • u011832039
  • u011832039
  • 2016年03月23日 17:19
  • 330

C++中拒绝编译器自动生成copy构造函数和copy赋值运算符操作(6)---《Effective C++》

C++是一片荆棘遍布的雷区,等待用于挑战的你去探索,在《Effective C++》系列的第5篇中我们已经看到当用户进行赋值或者拷贝操作的时候,即使我们没有定义拷贝构造函数或者拷贝赋值运算符操作,编译...
  • u014038273
  • u014038273
  • 2017年07月18日 16:57
  • 148

关联规则挖掘算法 Apriori算法的Matlab实现 可以自动生成关联规则,计算支持度、置信度

  • 2016年09月22日 22:19
  • 6KB
  • 下载

【iOS】CoreData对象关联时,自动生成的关联属性类型不对

2014.07.17 CoreData
  • arctan90
  • arctan90
  • 2014年07月17日 09:33
  • 729

asp.net上传图片并自动生成缩略图和给图片水印

无标题页 upfile.aspx.cs文件 using System; u...
  • youngshao1025
  • youngshao1025
  • 2012年09月26日 17:43
  • 350

基于注解和反射的Java ORM框架(4)-数据库自动生成Java实体类

Panda ORM作为最懒ORM框架之一(低调!),提供了直接从数据库表自动生成java实体类的功能。本篇介绍使用方法,十分之简单舒畅,后续在测试完毕后将提供Panda ORM的全部源代码(包括数据库...
  • woshisangsang
  • woshisangsang
  • 2017年03月20日 16:11
  • 1146

[Webservice] Eclipse根据wsdl文件自动生成webservice的调用客户端

公共接口:可供测试的在线webservice 生成客户端: 1. 带有webservice插件的Eclipse工具; 2. 首先用浏览器访问webservice的站点,接着保存打开的页面后缀为wsd...
  • qq_14852397
  • qq_14852397
  • 2016年10月08日 23:05
  • 12139
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:自动生成关联运算符
举报原因:
原因补充:

(最多只允许输入30个字)