c++ - 如何实现 std::advance 以更改迭代器类型的行为?

标签 c++ implementation std stdadvance

我们对 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_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() 不是函数调用;它是构造该类型的临时纯右值 的表达式。然后通过正常的重载决策选择适当的 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 的重载正在接收一个未命名的参数作为它们的第三个参数,该参数是它们选择的标记类型的一个实例。

关于c++ - 如何实现 std::advance 以更改迭代器类型的行为?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15368673/

相关文章:

c++ - 静态变量和全局变量什么时候初始化?

c++ - C++ "type deduction"和 Haskell "type inference"有什么区别?

c++ - eclipse c++ 中的 "control reaches end of non-void function"警告但没有编译或运行时错误

c++ - 为什么我的字符串没有被打印出来?

c++ - 如何使用 Win32 Imaging API (Windows Mobile 6+) 将 HBITMAP 保存为 JPG?

c++ - 归并排序的实现

c++ - 基类的更改需要重新编译派生类

git - 为什么 `git update-ref -d`不删除空的父目录?

c++ - 使用仿函数的自动类型推断不起作用

c++ - std::list 中最小元素的索引