最近写算法,习惯上了泛型编程,一敲键盘,就会不由自主的打出一个template出来。比如前一阵子的通配符搜索库的模块,以及刚刚完成的通用集合运算。
通用集合运算的主要功能是:
输入: 集合列表, 集合列表索引的并、交、差运算信息串
输出: 集合列表在该信息串的运算下所得结果集合
比如:
SetList = <Set0, Set1, …, Set4>
SetOpList = “(0+2)*((1-3)+4)”
则可以计算出一个Set出来,为(Set0∪Set2)∩((Set1-Set3)∪Set4)的结果。
用函数对象来做的话,就成了
template<typename TSet, typename TOpElem>
class CSetLogicop
{
public:
//…
int operator ()(…); //TSet’s list and TOpElem’s string info,also result
}
这样任意的集合以及信息串的形式都可以利用该算法了,但因为是参数形式,TSet的并、交、差等集合运算怎么办呢?信息串表位置的子串如何向整数索引转化呢?
一个念头一闪而过,加上两个接口来定义这些所需要的操作,不就一切ok了?比如:
template<typename TSet>
class ISetOp
{
public:
// pResult[out] = pSet1[in] 并 pSet2[in]
virtual int Union (TSet* pSet1, TSet* pSet2, TSet* pResult) = 0;
// pResult[out] = pSet1[in] 交 pSet2[in]
virtual int Intersection(TSet* pSet1, TSet* pSet2, TSet* pResult) = 0;
// pResult[out] = pMinuendSet[in] 减 pSet[in]
virtual int Minus(TSet* pMinuendSet, TSet* pSet, TSet* pResult) = 0;
// …
}
这样就成了真正的通用算法了,想做什么样的集合运算,只要把这个元操作的接口实现,然后初始化到CSetLogicop中,就可以使用这个模版函数对象了。