STL中有五种迭代器:
input_iterator,
output_iterator,
forward_iterator,
bidirectional_iterator,
random_access_iterator,
迭代器最主要的好处时,不会暴露你放在在容器中的对象的具体细节。也就是说,当你有一个迭代器,返回了你想要的对象。但是在使用过程中有没有疑问,就是由于容器都是模板,迭代器隐藏了放置在容器中的对象的具体细节。那迭代器又是怎么知道我想要的那个对象恰好是对的那个类型呢?还有就是,STL中大量使用了模板,某些工具性的函数返回的都是未知的类型(出于隐藏内部对象的细节的考虑),那我怎么知道这个函数会返回什么类型呢?在C++模板中,模板参数推导机制能有效的推导出参数的类型,但是问题是,我如何推导出函数返回类型呢?出于隐藏客户对象的细节的考虑,肯定是不能直接返回对象的类型的,这种情况下,迭代器如何做到的?
答案就在于萃取。萃取:就是萃取出迭代器的类型。例如:
std::vector<int>::iterator iter;
通过萃取就可以得到iter的返回类型int(当然,这里有点牵强,因为vector中的迭代器实际上就是 value_type*)。在STL中,自行定义内嵌类型的方式自定义出相应类型,通过自定义的类型进行类型推导,这样以达到得到返回对象的类型。
关于迭代器的实现可以翻阅STL的源码,这里不作赘述,这里主要用一个傻逼的模拟说明萃取的实现过程。STL中类型特性一般有:对象,引用,指针,const引用,const指针等。用一个结构体描述萃取:
template<typename T> // T -- People<int>
struct my_iterator_traits
{
typedef typename T::value_type value_type; // People<int> data member value_type
typedef typename T::point point;
typedef typename T::reference reference;
};
然后是一个模板类(此类没有太多的意义):
template<typename T> // int----------2
class People
{
public:
typedef T value_type;
typedef T* point;
typedef T& reference;
public:
T* ptr; // T -- int
People(T* p = 0):ptr(p) // T -- int
{
std::cout << "construct People!" << endl;
}
T& operator*()
{
return *ptr;
}
T* operator&()
{
return ptr;
}
private:
int p;
};
使用者:
template<typename T> // T -- People<int>
inline typename my_iterator_traits<T>::value_type // People<int> data member
myFun(T i) //使用者 T -- People<int>
{
return *i; // invoke operator*,return *ptr
}
main函数:
int _tmain(int argc, _TCHAR* argv[])
{
People<int>me(new int(8)); //------------------ 1
std::cout << myFun(me) << endl;
return 0;
}
运行打印出:8
下面解析一下程序。my_iterator_traits
结构体,使用typedef将模板参数T中的型别别名化了。1定义了一个对象me(模板参数类型int),其成员变量p被初始化成指向8的一个整形变量。接下来调用myFun调用者,myFun中,T为People<int>
,myFun的返回值是:typename my_iterator_traits<T>::value_type
,这里的T是People<int>
,转而进去People内部看看有typedef T value_type
,这是一个People的内嵌类型,由于此例中People的模板参数类型是int,那么typedef替换之后实际上就是 typedef int value
。
那么在 my_iterator_traits结构中,访问了People的内嵌类型,也做了别名化,但是实际程序在编译阶段已经将 typedef typename T::value_type value_type
替换成typedef typename People<int>::value_type value_type
,也就说myFun函数实际上返回的是int类型,People
这里可能有人说,何必这么麻烦,要返回的int类型不就可以了?但是有必要说明的是,这里我们只是以最简单的C++内建数据类型测试了,如果myFun是STL中内置函数,而People的模板参数不是内建类型而是自定义类类型,那这样的myFun应该返回哪种类型呢?
这个例程里面还少了一个比较重要的地方,就是模板特化,当传回的是原生指针呢,所有应该有一个萃取器对原生指针的特化这里就不用多说了,每一本将泛型或者STL的书中都会讲这个的,自己也可以去翻阅STL的源码。