针对不同类型迭代器实现各自的高效函数重载

来源:互联网 发布:手机能淘宝开店吗 编辑:程序博客网 时间:2024/05/18 06:05

1.不同的迭代器类型对相同功能的函数需进行不同的处理

1.Input Iterator :只读迭代器,不允许外界改变所指对象

2.Output Iterator:只写迭代器

3.Forward Iterator:单向迭代器,只允许单向移动

4.Bidirectional Iterator:双向迭代器

5.Random Access Iterator:随机访问迭代器(p+n,p-n)


对不同类型的迭代器,处于效率考虑,将采用不同的实现方式。例如对于一个实现迭代器移动的函数,将产生以下几种不同的函数:


①对Input Iterator,Output Iterator,Forward Iterator 类型的迭代器,函数定义如下:

template<class InputIterator,class Distance>void advance_II(InputIterator &iter, Distance n){while (n--) ++iter;}


②对Bidirectional Iterator 类型的迭代器,函数定义如下:

template<class BidirectionIterator,class Distance>void advance_BI(BidirectionIterator & iter, Distance n){if (n > 0)while (n--) ++iter;elsewhile (n++) --iter;}

③对Random_Access Iterator 类型的迭代器,函数定义如下:

template<class RandomAcessIterator ,class Distance>void advance_RAI(RandomAcessIterator &iter, Distance n){iter += n;}

观察上述函数定义,发现对不同类型的函数不能通过重载来进行区分,因为上述函数的参数类型完全相同,所以对其调用提供一个通用接口,根据判断迭代器的类型来决定调用不同的函数:

template<class InputIterator,class Distance>void advance(InputIterator & iter, Distance n){if (is_random_access_iterator(iter))      //is_random_access_iterator 待设计advance_RAT(iter, n);else if (is_bidirection_iterator(iter))advance_BI(iter, n);elseadvance_II(iter, n);}


但是此时也存在缺陷,即对调用哪一个函数,需要到执行期才能决定,会影响程序的效率,我们希望在编译期就能选择正确的版本

前面的三个 advance_xx() 都只有两个函数参数,型别都是未定,为了令这些函数同名,以实现函数重载,我们必须加上一个类型已确定的函数参数。设计思路:如果 traits 有能力萃取出迭代器的种类,则可以用迭代器的类型来作为 advance() 的第三个参数。为了实现在编译期确定正确的函数,则第三个参数必须是类类型,而不能是值。因此,定义以下五个类,代表五种类型迭代器,用来作为迭代器类型的标记

struct input_iterator_tag{};struct output_iterator_tag{};struct forward_iterator_tag : public input_iterator_tag{};struct bidirectional_iterator_tag : public forward_iterator_tag{};struct random_access_iterator_tag : public bidirectional_iterator_tag{};


此处使用继承的原因,是为了实现传递调用,即,假设仅定义了 Input_iterator_tag 可调用的函数 advance,则由于Forward_iterator_tag 是 Input_iterator_tag 的派生类,则Forward_iterator_tag可以通过传递调用 前者的 advance函数。

通过上述迭代器的标记类型引入作为第三个确定参数的方式,我们可以将上述三个函数进行重载,代码如下:

template<class InputIterator, class Distance>void __advance(InputIterator & iter, Distance n,input_iterator_tag){while (n--) ++iter;}template<class BidirectionIterator, class Distance>void __advance(BidirectionIterator & iter, Distance n,bidirectional_iterator_tag){if (n > 0)while (n--) ++iter;elsewhile (n++) --iter;}template<class RandomAcessIterator, class Distance>void __advance(RandomAcessIterator & iter, Distance n,random_access_iterator_tag){iter += n;}



则该函数的公共接口如下,将通过 iterator_traits 对迭代器类型的萃取功能来实现合适的函数调用:

template<class InputIterator, class Distance>void advance(InputIterator& iter, Distance n){__advance(iter, n, iterator_traits<iter>::iterator_category());  //iterator_category()创建一个临时对象,类似:int()}

*注:STL算法的一个命名规则:以算法所能接受的最低阶的迭代器的类型来为其迭代器类别参数命名(如上面的InputIterator)



0 0
原创粉丝点击