现在的位置: 首页 > 综合 > 正文

STL itertor类型萃取技术

2014年01月04日 ⁄ 综合 ⁄ 共 2030字 ⁄ 字号 评论关闭

  自从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_type
func (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类型萃取

template<class T> 
struct iterator_traits<const T*> {
    typedef T value_type;
};
template<class T>
struct MyIter{
    typedef I::value_type value::type;
    T* ptr;
    MyIter(T* p=0):ptr(p){}
    T& operator*() const{ return *ptr;}
};

template <class I>
struct iterator_traits
{
    typedef I::value_type value_type;
};

template<class I>
typename itertor_traits<I>::value_type func(I iter)
{                
    return *iter;
}
int main()
{
    int *p=new int(6);
    MyIter<char> ite(new char('f'));
    cout<<func(ite)<<endl;
    cout<<func(p)<<endl;
    return 0;
}

这样就可以了。不仅可以接受各种类或基本类型作为迭代对象,而且接受原生指针作为迭代器。可以这样理解:C++ traits就是为了萃取迭代器(或指针)的特性而写的一个通用的模板和它的偏特化版本。

 

 

 

抱歉!评论已关闭.