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

How is std::advance implemented to change behavior on iterator type?

本文关键字:迭代器 改变 类型 advance 何实现 实现 std      更新时间:2023-10-16

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

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

将迭代器i向前推进n元素

如果i是随机访问迭代器,则函数使用一次operator+operator-,否则,函数重复使用增减运算符(operator++operator--),直到n元素被进进。


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

通过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());
}

注意iterator_category是一个类型(std::input_iterator_tag等之一),所以iterator_category()不是一个函数调用;它是一个构造该类型的临时右值的表达式。然后通过正常的过载解析选择适当的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的重载正在接收一个未命名参数作为它们的第三个参数,该参数是它们选择的标记类型的一个实例。

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

在此基础上,它可以决定如何推进事情。