如何实现std :: advance来改变迭代器类型的行为?

时间:2013-03-12 18:00:04

标签: c++ implementation std stdadvance

我们对std::advance的了解如下:

template <class InputIterator, class Distance>
void advance (InputIterator& i, Distance n);

目的

通过i元素推进迭代器n

如果i是随机访问迭代器,则该函数使用一次operator+operator-,否则,该函数会重复使用增加或减少运算符({{1} }或operator++),直到operator--个元素被提前。


我的问题如下: n如何实现,以便它识别std::advance是否是随机访问迭代器?它如何知道它可以使用it代替operator+

2 个答案:

答案 0 :(得分:18)

通过iterator_traitstag dispatch

template<class InputIterator, class Distance>
void advance_impl(InputIterator& i, Distance n, std::random_access_iterator_tag) {
  i += n;
}

template<class InputIterator, class Distance>
void advance_impl(InputIterator& i, Distance n, std::bidirectional_iterator_tag) {
  if (n < 0) {
    while (n++) --i;
  } else {
    while (n--) ++i;
  }
}

template<class InputIterator, class Distance>
void advance_impl(InputIterator& i, Distance n, std::input_iterator_tag) {
  assert(n >= 0);
  while (n--) ++i;
}

template<class InputIterator, class Distance>
void advance (InputIterator& i, Distance n) {
  advance_impl(i, n,
    typename std::iterator_traits<InputIterator>::iterator_category());
}

请注意,iterator_category是一种类型(std::input_iterator_tag之一等),因此iterator_category()不是函数调用;它是一个构造该类型的临时prvalue 的表达式。然后通过正常的重载分辨率选择advance_impl的适当重载。这称为标签调度。同样可以写:

template<class InputIterator, class Distance>
void advance (InputIterator& i, Distance n) {
  typename std::iterator_traits<InputIterator>::iterator_category the_tag;
  advance_impl(i, n, the_tag);
}

advance_impl的重载作为第三个参数接收一个未命名的参数,该参数是其所选标记类型的一个实例。

答案 1 :(得分:1)

我想可能会使用std::iterator_traits::iterator_category来确定迭代器的类型。

基于此,它可以决定如何推进事物。