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

Nar*_*rek 9 c++ implementation std stdadvance

我们所知道的std::advance是以下内容:

template <class InputIterator, class Distance>
void advance (InputIterator& i, Distance n);
Run Code Online (Sandbox Code Playgroud)

目的

in元素推进迭代器.

如果i是随机访问迭代器,函数使用一次operator+operator-,否则,该函数使用重复的增加或减少经营者(operator++operator--),直到n元件已经前进.


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

eca*_*mur 18

通过iterator_traits标签发送:

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());
}
Run Code Online (Sandbox Code Playgroud)

注意,这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);
}
Run Code Online (Sandbox Code Playgroud)

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

  • @Narek [C++中的迭代器类如何工作?](http://stackoverflow.com/q/4688177/478288) (3认同)
  • @Narek`theerator_category`是一个类型(`std :: input_iterator_tag`之一等),所以`iterator_category()`正在构造该类型的临时prvalue.然后通过正常的重载分辨率选择`advance_impl`的适当重载.这称为*tag dispatch*. (2认同)