Loading

《STL源码剖析》traits技法分析

在完成一个迭代器的时候,我们可能会暴露太多的细节在外面,为了将这些细节给隐藏,我们需要封装,这也是为什么每一种STL容器都提供了一种专属的迭代器。
为了解决以“迭代器所指对象的型别”为型别
解决办法是:利用template的参数推导(argument deducation)

template<class I,class T>
void func_impl(T iter,T t)
{
    T temp;//这里解决了问题,T就是所指的对象的型别
};

template<class I>
void func(I iter)
{
 func_impl(iter,*iter);//传入的一个是迭代器,一个是迭代器所指的对象的类型
}

这里编译器会自动进行template类型推导,于是可以推导出型别T,顺利解决问题。
(迭代器相应型别不止是迭代器所指对象的型别一种,最常用的有5种:value_type,difference_type,reference_type,pointer_type,iterator_category)


为了解决以迭代器所指对象型别为返回值的问题
在这里我们使用声明内嵌型类型来解决问题:

template<class T>
struct MyIter{
typedef T value_type;//声明内嵌型型别(nested type)
T*ptr;
MyIter(T*p=0):ptr(p){}
T&operator*(){return *ptr}
};

template<class I>
typename I::type_value
func(I ite){
return *ite;
}

int main()
{
MyIter<int> ite(new int(8));
cout<<func(ite);//输出结果为8
}

但是这种方法有一个隐藏的缺点:无法为原生指针类型制作迭代器,因为内建类型无法定义内部的value_type,所以我们还需要针对特定情况做特定的处理,这时候我们需要特偏化处理(template partial specialization)


特偏化(template partial specialization)
(1) 类模板的偏特化
例如c++标准库中的类vector的定义
template

template<class T>
struct iterator_traits{
typedef typename T::value_type value_type;
//这里多加了一层封装,好处是traits可以拥有特化的版本(这里我还是不清楚,为什么说加了封装才能有特化的版本?)
};

//特化的版本1,为了解决原生指针,比如:int*
template<class T>
struct iterator_traits<T*>{
    typename T value_type;//如果是个Int*,可以萃取出int类型
};

//特化版本2,为了解决原生的const指针,比如:const int*
template<class T>
struct iterator_traits<const T*>{
    typename T value_type;//如果是个const int*,可以从中萃取出int类型
}

这里写图片描述
最后的效果就像图中这样。

posted @ 2017-03-11 18:53  李正浩  阅读(143)  评论(0编辑  收藏  举报