最近在学习jjhou的《STL源码剖析》,侯大师确实功力深厚,把SGI版本的STL解析的很透彻。让我等凡人能有机会窥见一些C++标准模板库的玄妙。看了第三章的内容,于是打算总结一番,方便后续继续学习。
迭代器模式
提供了一种方法,使之能够依序巡访某个聚合物(容器)所含的各个元素,而又无需暴露该聚合物的内部表达方式。
STL中的迭代器
STL的中心思想在于:将数据容器(containers)和算法(algorithms)分开,彼此独立设计,最后再以一贴胶着剂将它们撮合在一起。容器和算法的泛型化,可以用C++的class template 和 function template 来实现。而迭代器就是两者之间的胶着剂。
find( )方法中循环所满足的条件:
// 要么找到value,返回*first(指向value);要么没找到,最后返回last,终止while循环
while(first != last && *first != value)
++first;
return first;
iterator是一种行为类似指针的对象,指针最重要的便是内容提领(dereference)和成员访问(member access)。因此iterator最重要的是对operator*和operator->进行重载的工作。
迭代器相应型别(associated types)
associated types总共有五种类型: value_type,difference_type,pointer,reference,iterator_cotegory。
其中value_type可以利用function template的argument deducation,但是它只能推导参数的型别,无法推导函数的返回值的型别。
Partial Specialization(偏特化)的意义
在泛化设计中提供了一个特化版本(将泛化版本中的某些template参数赋予明确的指定)。
利用模板的参数推断:
template<typename I, typename T>
void func_impl(I iter, T, t)
{
T tmp; //这里解决了问题。T就是迭代器所指之物的型别,本例为int
// ...这里做原本func()应该做的全部工作
};
template <typename I>
inline
void func(I iter)
{
func_impl(iter, *iter); // func的工作全部移往func_impl
};
int main()
{
int i;
func(&i);
}
万一value_type必须用于函数传回值,模板参数推导机制只能推断参数,而无法推断函数的回返值型别。我们需要其他的方法:声明内嵌。
template <typename T>
struct MyIter
{
typedef T value_type; //内嵌型别声明(nested type)
T* ptr;
MyIter(T* p = 0):ptr(p){}
T& operator*() const{return *ptr;}
// ...
};
template <typename I>
typename I::value_type //这一行是func的回返值型别
func(I ite)
{
return *ite;
}
// ...
MyIter<int> ite(new int (8));
cout<< func(ite); //输出 8
引入萃取:
template <typename T>
struct MyIter
{
typedef T value_type; //内嵌型别声明(nested type)
T* ptr;
MyIter(T* p = 0):ptr(p){}
T& operator*() const{return *ptr;}
// ...
};
template <typename I>
struct iterator_traits
{
typedef typename I::value_type value_type;
};
template <typename I>
typename iterator_traits<I>::value_type //这一行是func的回返值型别
func(I ite)
{
return *ite;
}
// ...
MyIter<int> ite(new int (8));
cout<< func(ite); //输出 8
template <typename T>
struct iterator_traits<T*>
{
typedef T value_type; //偏特化版,迭代器是个原生指针
};
引入萃取之后,不论面对的是迭代器MyIter,或是原生指针int*或是const int*,都可以通过traits取出正确的value_type。
大功告成