之前用C++实现一个不限长度的整型,为了让这个整型在行为上尽量与int类似,我重载了‘<’、‘>’、‘==’和‘!=’四个符号。记得当时的一个困扰就是这几个函数的代码几乎是重复的,而且微小的区别很容易一不小心就出错。感觉当时是急于实现一个“真”类型,想都没想就“选择”重复了:-(
刚才阅读go语言的nat类型(无符号不限长度的整型)实现,因为go语言不提供操作符重载,所以他们很自然地定义了cmp函数来实现比较操作。
一拍脑门儿,在我的C++实现里用cmp会不会更好?
定义cmp函数的通常做法就是通过返回一个int值来表述比较结果(比如:返回负数,表示小于;正数,大于;零,等于)。这样一来,不再需要为多个操作符函数写那些重复的代码,一个函数就把比较的任务都完成了。除了看起来比‘<’、‘>’、‘==’和‘!=’丑一点(要看个人喜好了),cmp会有什么缺点吗?
‘<’、‘>’、‘==’和‘!=’的重载函数是会直接返回true或false的,而cmp函数的返回结果一般需要进一步和零比较(又得使用到‘<’、‘>’、‘==’和‘!=’了:-))才能用。
另外一个可能情况是,也许对于某些特殊的类型,小于比较和大于比较的逻辑很不同,不太具有对称性,那么cmp减少重复代码的优点就被削弱;而且在这种情况下,对于只需要知道小于比较的结果(或是大于比较的结果)的使用场景,cmp会包含更多的额外计算成本。
不对称的小于、大于比较逻辑好像较少,在一般情况下(有硬性要求的除外),cmp V.S. 重载?
又或者:
bool operator<(x, y) { return cmp(x, y)<0? true:false; } bool operator>(x, y) { return cmp(x, y)>0? true:false; } bool operator==(x, y) { return cmp(x, y)==0? true:false; } bool operator!=(x, y) { return cmp(x, y)!=0? true:false; }
?
:-)