STL itertor概念和traits编程技法(一)

来源:互联网 发布:苹果ipad越狱软件 编辑:程序博客网 时间:2024/05/18 00:57

  自从C++中引入了template后,以泛型技术为中心的设计得到了长足的进步。STL就是这个阶段杰出的产物。STL的目标就是要把数据和算法分开,分别对其进行设计,之后通过一种名为iterator的东西,把这二者再粘接到一起。设计模式中,关于iterator的描述为:一种能够顺序访问容器中每个元素的方法,使用该方法不能暴露容器内部的表达方式。可以说,类型萃取技术就是为了要解决和iterator有关的问题的,下面,我们就来看看整个故事。

应该说,迭代器就是一种智能指针,因此,它也就拥有了一般指针的所有特点——能够对其进行*和->操作。但是在遍历容器的时候,不可避免的要对遍历的容器内部有所了解,所以,设计一个迭代器也就自然而然的变成了数据结构开发者的一个义务,而这些iterators的表现都是一样的,这种内外的差异,对用户来说,是完全透明的,

一、 为什么要有萃取技术

既然是一种智能指针,iterator也要对一个原生指针进行封装,而问题就源于此,当我们需要这个原生指针所指对象的类型的时候(例如声明变量),怎么办呢?

case1:类型推导

#include<iostream>using namespace std;template<class I,class T>void func_imp(I iter,T t){    T item;    item=t;    cout<<item<<endl;}template<class I>inline void func(I iter){    func_imp(iter,*iter);}int main(){    int i=9;    func(&i);    return 0;}

在这个程序里,T是某个指向某个特定对象的指针,在func中需要指针所指向对象类型的变量的时候,利用模板的参数推导机制可以得到T的类型。但是这有一个问题,迭代器类型不只是是所指对象的类别,还包括其他常用型别,而且模板的参数推导也不能推导出返回值类型。

case2:声明内嵌型别

template<class T>struct MyIter{    typedef T value_type;    T* ptr;    MyItem(T* p=0):ptr(p){}    T& operator*() const{ return *ptr;}};template<class I>typename I::value_type func(I iter){    return *iter;}int main(){    MyIter<int> ite(new int(8));    cout<<func(ite)<<endl;    return 0;}

typedef T value_type是为所指向的对象的类型添加一个别名,这样在func()函数里面就可以通过typename I::value_type func(I iter)返回value_type对象,typename I::value_type func(I iter)这句不好理解,如果觉得这一段代码难理解的话,不妨改成这样:

template <class T>typename myIter<T>::value_typefunc (myIter<I>){ return *iter;}

 不同的只是红色部分;这跟X是一个变量,可以用Y表示;5*X还是一个变量,也可以用Y表示,是一个道理但是这样的函数不能使用原生指针,比如我们这样使用int *p=new int(6);cout<<func(p)<<endl;编译器就会客气的告诉你出错了Failed to specialize function template 'generic-type-257 __cdecl func(I)。因为编译器不知道I和T的类型,这当然不行。

case3:类型萃取

/*1.当T为内嵌型别时,通过类型推导获取型别 *2.当T为原生指针的或者pointer-to-const的时候,通过iterator_traits偏特化获取型别*/#include <iostream>using namespace std;template <class I>struct myiterator_traits{    typedef typename I::value_type value_type;};//特化版本1,T为原生指针template<class T> struct myiterator_traits<T*> {    typedef T value_type;};//特化版本2,T为const-to-pointertemplate<class T> struct myiterator_traits<const T*> {    typedef T value_type;};//自定义类型MyItertemplate<class T>struct MyIter{    typedef T value_type;    T* ptr;    MyIter(T* p=0):ptr(p){}    T& operator*() const{ return *ptr;}};template<class I>typename myiterator_traits<I>::value_typefunc(I iter){                    return *iter;}int main(){    MyIter<char> ite(new char('f'));//当T为自定义类型    cout<<func(ite)<<endl;    int *p=new int(6);    //当T为原生指针时    cout<<func(p)<<endl;    const int *t=new int(9);    //当T为pointer-to-const时    cout<<func(t)<<endl;    return 0;}

这样就可以了。不仅可以接受各种类或基本类型作为迭代对象,而且接受原生指针作为迭代器。

原创粉丝点击