traits编程技法
看了《stl源码剖析》中关于traits的部分,由于对模板还不是很熟悉,就看了一下还未完工的C++ Template 进阶指南 ,感觉收获很大,推荐一下。
在使用迭代器时,为了知道它的相应类型,可以使用模板的参数推导,代码如下
template <class T> struct MyIter typedef T value_type; T* ptr; MyIter(T* p=0) : ptr(p) { } T& operator*() const { return *ptr; } // ... }; template <class I> typename I::value_type // 返回类型 func(I ite) { return *ite; } // ... MyIter<int> ite(new int(8)); cout << func(ite); // 输出:8
用typename是因为I::value_type要在模板实例化的时候才能知道是不是一个类型,所以用typename声明为类型。具体可见我前面提到的那篇文章,说得很详细。
但是这样有一个问题,有些迭代器(比如指针)并不是一个类,也就用不了这个办法了。这时就要用traits思想把相应的类型萃取出来。
原始的类模板如下:
template <class I> struct iterator_traits { typedef typename I::value_type value_type; };
偏特化:
template <class T> struct iterator_traits<T*> { typedef T value_type; };
这样就得到了相应的类型,同理,对于const T*有
template <class T> struct iterator_traits<const T*> { typedef T value_type; };
有了这个技巧,stl就可以根据需要制定提取迭代器相应类型的办法,比如对于下面五种有不同的方式提取类型
value_type
difference_type
pointerpointer
referencereference
iteratoriterator_category
具体方式书中有说,就不赘述了。