終於理解了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));
}