traits编程技巧

template<class T>
class iterator//表示迭代器针对泛型iterator_traits时的底层代码
{
    typedef T value_type;
}; 

template<class Iterator>
struct iterator_traits//泛化iterator_traits,作用多层间接性
{
    typedef typname Iterator::value_type value_type;
};


template<class T>
struct iterator_traits<T*>//特化iterator_traits,直接提取类型
{
    typedef T value_type;
};
template<class T>
struct iterator_traits<const T*>//特化iterator_traits,直接提取类型
{
    typedef T value_type;
};

//typename iterator_traits<Iterator>调用的是泛化的或者特化的
template<class Iterator>
typename iterator_traits<Iterator>::value_type fun(Iterator ite)
{
    return *ite;//迭代器基本类型,以及有解引用功能
}
//直接使用底层型别,如果是T*,则出问题,相当于value_type被解读为T*
//同样用list<int>::iterator,则被解读为list<int>::iterator,而不会深度挖掘。
//显然只是适合于传递T,才能达到目的
template<class Iterator>
typename Iterator::value_type fun(Iterator ite)
{
    return *ite;
}
fun(list<int>::iterator ite);//显然是调用了iterator_traits模板
//typename iterator_traits<list<int>::iterator>::value_type
//typedef typname list<int>::iterator::value_type value_type;
//这就调用了list相应的迭代器中value_type,则为int。
//typedef typname list<int>::iterator::int value_type;
//-------------------------------------------------------------上述是T类型,榨取---------------------------
//stl-iterator头文件
//具体的模板,可能需要的具体的5种型别不一样,有的模板直接可以确定下来。所以定义一个最高的母版为下
template <class Category, class T, class Distance = ptrdiff_t,
          class Pointer = T*, class Reference = T&>
struct iterator {
  typedef Category  iterator_category;
  typedef T         value_type;
  typedef Distance  difference_type;
  typedef Pointer   pointer;
  typedef Reference reference;
};
//例如<假象的>vector特化迭代器
template<class T>
struct vector_iterator:public iterator<random_access_iterator_tag,T>{
  typedef random_access_iterator_tag  iterator_category;//vector模板可以确定
  typedef T         value_type;
  typedef size_type  difference_type;//可以确定下来了
  typedef Pointer   pointer;
  typedef Reference reference;
};



//基础榨取机模板类----泛化
template<class I>
struct iterator_traits
{
    typedef I::value_type value_type;//迭代器所指的类型
    typedef I::difference_type difference_type;//迭代器距离
    typedef I::pointer pointer;
    typedef I::reference reference;
    typedef I::iteratro_category iterator_category;//迭代器类型。
};
//特化版1
template<class T>
struct iterator_traits<T*>
{
    typedef T value_type;//迭代器所指的类型
    typedef ptrdiff_t difference_type;//迭代器距离
    typedef T* pointer;
    typedef T& reference;
    typedef random_access_iterator_tag iterator_category;
    
};
//特化版2
template<class T>
struct iterator_traits<const T*>
{
    typedef T value_type;//迭代器所指的类型
    typedef ptrdiff_t difference_type;//迭代器距离
    typedef T* pointer;
    typedef T& reference;
    typedef random_access_iterator_tag iterator_category;
};

//应用部分
template<class I>
typename iterator_traits<I>::difference_type f(I);//榨取其中的ptrdiff_t
//如果I传入的是类型为list<vector<int>>则,会先看list迭代器,取出其中元素为vector<int>,细调用
//vector的difference_type,此时就会调用int的difference_type,那此处就会有difference_type的类别名
template<class I>
typename iterator_traits<I>::value_type f();//榨取其中的T
template<class I>
typename iterator_traits<I>::pointer f();//榨取其中的T*
template<class I>
typename iterator_traits<I>::reference f();//榨取其中的T&
template<class I>
typename iterator_traits<I>::iterator_category f();//榨取其中的random_access_iterator_tag




//------------------------------下述,产生iterator_category的型别因素---------------------------------
//将5种类型迭代器,构造一个空类,其这样做目的是区分种类类型,而不需要任何数据成员。
struct input_iterator_tag {};
struct output_iterator_tag {};
struct forward_iterator_tag : public input_iterator_tag {};
struct bidirectional_iterator_tag : public forward_iterator_tag {};
struct random_access_iterator_tag : public bidirectional_iterator_tag {};


//输入迭代器---只读,单向
template <class InputIterator, class Distance>
inline void __advance(InputIterator& i, Distance n, input_iterator_tag) {
  while (n--) ++i;
}
//双向迭代器---可读写,双向
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;
}
//随机迭代器---可读写,随机访问
template <class RandomAccessIterator, class Distance>
inline void __advance(RandomAccessIterator& i, Distance n, 
                      random_access_iterator_tag) {
  i += n;
}
//外口函数--客户端使用的,是2个参数的advance函数,是根据传入时的迭代器类型不同而定下采用哪个函数
template <class InputIterator, class Distance>
inline void advance(InputIterator& i, Distance n) {
  __advance(i, n, iterator_category(i));
}
//获取迭代器的 距离。----放回距离的指针,其值为0
template <class Iterator>
inline typename iterator_traits<Iterator>::difference_type*
distance_type(const Iterator&) {
  return static_cast<typename iterator_traits<Iterator>::difference_type*>(0);
}
//获取迭代器所指元素类型---放回元素类型指针,其值为0
template <class Iterator>
inline typename iterator_traits<Iterator>::value_type*
value_type(const Iterator&) {
  return static_cast<typename iterator_traits<Iterator>::value_type*>(0);
}
//函数获取,迭代器种类型别,放回种类型别对象,初始化后的
template <class Iterator>
inline typename iterator_traits<Iterator>::iterator_category
iterator_category(const Iterator&) {
  typedef typename iterator_traits<Iterator>::iterator_category category;//此处出来的最后是某个_tag类型
  return category();
}



//例如:
advance(vector<int>::iterator,2);//通过传入的vector迭代器,则可以通过榨取机获得此类型为随机访问迭代器模型
//因为它会调用vector模板中的iterator_category,而它则某个_bag,则显然会被定义为随机访问迭代器。而不会是
//迭代器的I::iterator_category,故而和vector<list<int>>的迭代器类型应该是一致的。
//---------------------------------------------------//
原文地址:https://www.cnblogs.com/miner007/p/4162647.html