终于理解了c++ traits技法,不得不说它对c++的作用可以说是很大,让编程效率可以提升很多,为什么这多说,就是当我们在写了一个模板后,traits技法可以让这个模板的通用性更强,模板偏特化就会在模板泛化中再设计一个特别的版本,看下面这个列子,对于模板参数是一个一个普通类型时,它会匹配第一个模板,当为指针时匹配第二个模板,这就区分开了两种,可以有不同的处理方式
template<typename T>
struct A {
};
template<typename T> //偏特化版本
struct A<T*> {
};
再看下面例子, 是traits在迭代器里简单应用的抽象例子,我们就可以根据模板里的参数类型来赋值,使其能调用相应的函数
template<class IterT>
struct my_iterator_traits {
typedef typename IterT::value_type value_type;
};
template<class IterT>
struct my_iterator_traits<IterT*> {
typedef IterT value_type;
};
void fun(int a) {
cout << "fun(int) is called" << endl;
}
void fun(double a) {
cout << "fun(double) is called" << endl;
}
void fun(char a) {
cout << "fun(char) is called" << endl;
}
int main()
{
my_iterator_traits<vector<int>::iterator>::value_type p; //vector迭代器内部有一个typedef T value_type;有迭代器的value_type就可知类型
fun(p);
my_iterator_traits<int*>::value_type q;
fun(q);
}
来看一看iterator_traits的源码,对于iterator_traits类,通过调用它的iterator_category获得它的参数类型,即相应的迭代器类型,这样一来,我们就可以获取到任何类型的相应型别
template <class Iterator>
struct iterator_traits {
typedef typename Iterator::iterator_category iterator_category;
typedef typename Iterator::value_type value_type;
typedef typename Iterator::difference_type difference_type;
typedef typename Iterator::pointer pointer;
typedef typename Iterator::reference reference;
};
/* 特化版本,迭代器是个原生指针
*/
template <class T>
struct iterator_traits<T*> {
typedef random_access_iterator_tag iterator_category;
typedef T value_type;
typedef ptrdiff_t difference_type;
typedef T* pointer;
typedef T& reference;
};
/* 这里还要针对const T*特化
* 否则还是依照上一个特化版本,value_type是const int而不是int
*/
template <class T>
struct iterator_traits<const T*> {
typedef random_access_iterator_tag iterator_category;
typedef T value_type;
typedef ptrdiff_t difference_type;
typedef const T* pointer;
typedef const T& reference;
};
当用advance函数来计算两个迭代器间的距离时,可以获得其迭代器类型进行相应的操作,提高效率
template <class InputIterator, class Distance>
inline void __advance(InputIterator& i, Distance n, input_iterator_tag) {
while (n--) ++i;
}
#if defined(__sgi) && !defined(__GNUC__) && (_MIPS_SIM != _MIPS_SIM_ABI32)
#pragma set woff 1183
#endif
template <class BidirectionalIterator, class Distance>
inline void __advance(BidirectionalIterator& i, Distance n,
bidirectional_iterator_tag) {
if (n >= 0)
while (n--) ++i;
else
while (n++) --i;
}
#if defined(__sgi) && !defined(__GNUC__) && (_MIPS_SIM != _MIPS_SIM_ABI32)
#pragma reset woff 1183
#endif
template <class RandomAccessIterator, class Distance>
inline void __advance(RandomAccessIterator& i, Distance n,
random_access_iterator_tag) {
i += n;
}
template <class InputIterator, class Distance>
inline void advance(InputIterator& i, Distance n) {
__advance(i, n, iterator_category(i));
}