STL源码利用Traits类来萃取,模板参数一些型别,我觉得蛮不错,做个笔记。
1.利用function template的参数推导机制
template<class I,class T> Void func_impl(I iter,T t) { T tmp;// }; template<class I> Void func_impl(I iter) { func_impl(iter,*iter); } int main() { int I; func(&i);//编译器会自动进行template参数推导 }
迭代器所指对象的型别,称为迭代器的value_type。上面技巧可以用于value_type,但是不是全面可用。万一value_type必须用于函数的传回值,毕竟template的参数推导机制导出的只是输入参数,无法推导函数的返回值型别。
2.内嵌型别
内嵌型别似乎能解决这个问题:
template<class T> struct MyIter{ typedef T value_type; T* ptr; }; template<class I> typename I::value_type func(I ite){ return*ite; } MyIter<int>ite(new int(4)); Cout<<func(ite);
Func()的返回类型必须加上关键字typename,因为T是一个template参数,它在编译之前,编译器对T一无所知,并不知道MyIter<T>::value_type是一个型别还是一个function还是一个data
member。关键字typename告诉编译器这是一个型别。
3.偏特化
这种方案看起来是可行,但是有个陷阱,并不是所有的迭代器都是class Type,原生指针就不是。如果不是class Type,就无法定义内部型别,但是我们可以针对这种特殊情况定义特化版本,也就是将泛化版本中某些参数template参数明确固定。我们针对template参数更进一步的条件限制所设计出来的特化版本:
template<class I> calss C{…….}; //允许I为任何型别 template<class I> calss C<T*>{…….}; //这个特化版本仅适用于“T原生指针”的情况。
4.STL中的Traits技术
template<class T> struct iterator_traits{ typedef typename I::value_type value_type; typedef typename I::iterator_category iterator_category; typedef typename I::difference_type difference_type; typedef typename I::pointer pointer typedef typename I::reference reference }; //两个特化版本 template<class T> struct iterator_traits<const T*>{ typedef T value_type; … }; template<class T> struct iterator_traits<const T*>{ typedef T value_type; … }; //应用 template<class T> typename iterator_traits<I>::value_type func(I ite) { return*ite; }
注:若要使用这个“特性萃取机”,每个迭代器必须遵守约定,自行定义内嵌型别定义。
注:我可以学到的两点:型别提取技术,template的特化
5.迭代器(iterator)中的型别
迭代器中包含有五种型别:value_type、difference_type、reference_type、pointer_type和iterator_category