我们对 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
和 tag 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/