1

结论: std::iterator_traits 用于Iterator类型

比如有这么一个需求,给随意的一个迭代器移动距离 , 伪代码:

template <typename Iter, typename Distance>
void move_iter(Iter& iter, Distance d)
{
    if( iter is std::random_access_iterator_tag)   //随机迭代器随意加减
        iter +=d;
    else                                           //别的迭代器
        ....
}

问题是如何判断一个迭代器类型 ,使用 iterator_traits;

前提 , 5种迭代器是继承关系 ,随意看一眼即可:

struct input_iterator_tag
    {    // identifying tag for input iterators
    };

struct _Mutable_iterator_tag
    {    // identifying tag for mutable iterators
    };
struct forward_iterator_tag
    : input_iterator_tag, _Mutable_iterator_tag
    {    // identifying tag for forward iterators
    };
....

看一下iterator_traits:

template<class _Iter>
    struct iterator_traits
    {    // get traits from iterator _Iter
    typedef typename _Iter::iterator_category iterator_category;
    ...
    还有一堆typedef的东西, 省略
    }

iterator_traits 和 remove_reference 内部实现差不多, 只是一堆typedef ,主要用于获取类型;
先简单看一下iterator_traits 怎么用:

    //太长了? 
    // iterator_traits<迭代器类型>::iterator_category 
    //iterator_category 就是一个被typedef 的 5个结构体中的其中一个
    
    cout << typeid(std::iterator_traits<list<int>::iterator>::iterator_category).name() << endl;
    cout << typeid(std::iterator_traits<deque<int>::iterator>::iterator_category).name() << endl;
    
    
/*
    输出:
    struct std::bidirectional_iterator_tag
    struct std::random_access_iterator_tag
*/

用于判断迭代器类型的就是iterator_category ,而他本身就是5种迭代器的其中一个;

接下来就可以修改第一份伪代码了 . 大致是这样:

template <typename Iter, typename Distance>
void move_iter(Iter& iter, Distance d)
{
    if(typeid(std::random_access_iterator_tag) == typeid(std::iterator_traits<Iter>::iterator_category))
        iter += d;
    else if ...
    ...
}

用RTTI这类东西总是觉得,本来就可以在编译的时候完成的,干嘛非等到运行时;

在修改一下 , 下面代码用了哑元 , 3个重载的template function:

template <typename Iter , typename Dist>
void do_move_iter(Iter & iter, Dist d , std::random_access_iterator_tag) //随机迭代
{
    iter += d;
}
template <typename Iter , typename Dist>
void do_move_iter(Iter & iter, Dist d , std::bidirectional_iterator_tag) //双向
{
    if( d>= 0){
        while(d--)
            ++iter;
    }
    else {
        while(d++)
            --iter;
    }
}
template <typename Iter , typename Dist>
void do_move_iter(Iter & iter, Dist d , std::input_iterator_tag) // forward继承了input;
{
    if( d < 0)
        throw std::out_of_range("d < 0");
    while(d--)
        ++iter;
}

template <typename Iter, typename Distance>
void move_iter(Iter& iter, Distance d)
{
    do_move_iter(iter,d,  std::iterator_traits<Iter>::iterator_category());
}

int main()
{
    vector<int> vi{1,2,3,4}; 
    vector<int>::iterator iter = vi.begin();  //随机迭代器
    move_iter(iter,2); //移动2个距离
    cout << *iter << endl; //3. ok的
}

dashoumeixi
15 声望1 粉丝