简体   繁体   English

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

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

What we know about std::advance is the following: 我们对std::advance的了解如下:

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

Purpose 目的

Advances the iterator i by n elements. 通过n元素推进迭代器i

If i is a Random Access Iterator, the function uses once operator+ or operator- , otherwise, the function uses repeatedly the increase or decrease operator ( operator++ or operator-- ) until n elements have been advanced. 如果i是随机访问迭代器,则该函数使用一次operator+operator- ,否则,该函数重复使用增加或减少运算符( operator++operator-- ),直到n元素被提前。


My question is the following: How is std::advance implemented such that it recognizes if it is a Random Access Iterator or not? 我的问题如下:如何实现std::advance ,以便识别it是否是随机访问迭代器? How does it know it can use operator+ instead of operator++ ? 它是如何知道它可以使用operator+而不是operator++

Through iterator_traits and tag dispatch : 通过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());
}

Note that iterator_category is a type (one of std::input_iterator_tag etc.), so iterator_category() is not a function call; 请注意, iterator_category是一个类型( std::input_iterator_tag等之一),因此iterator_category()不是函数调用; it's an expression that constructs a temporary prvalue of that type. 它是一个构造该类型的临时prvalue的表达式。 The appropriate overload of advance_impl is then selected by normal overload resolution. 然后通过正常的重载分辨率选择advance_impl的适当重载。 This is called tag dispatch . 这称为标签调度 Equivalently one could write: 同样可以写:

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);
}

The overloads of advance_impl are receiving as their third argument an unnamed argument that is an instance of their chosen tag type. advance_impl的重载作为第三个参数接收一个未命名的参数,该参数是其所选标记类型的一个实例。

I would imagine it may use std::iterator_traits::iterator_category to figure out what the type of the iterator is. 我想可能会使用std::iterator_traits::iterator_category来确定std::iterator_traits::iterator_category的类型。

Based on that, it can decide how to advance things. 基于此,它可以决定如何推进事物。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM