我们对std::advance
的了解如下:
template <class InputIterator, class Distance>
void advance (InputIterator& i, Distance n);
目的
通过i
元素推进迭代器n
。
如果i
是随机访问迭代器,则该函数使用一次operator+
或operator-
,否则,该函数会重复使用增加或减少运算符({{1} }或operator++
),直到operator--
个元素被提前。
我的问题如下:
n
如何实现,以便它识别std::advance
是否是随机访问迭代器?它如何知道它可以使用it
代替operator+
?
答案 0 :(得分:18)
通过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()
不是函数调用;它是一个构造该类型的临时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);
}
advance_impl
的重载作为第三个参数接收一个未命名的参数,该参数是其所选标记类型的一个实例。
答案 1 :(得分:1)
我想可能会使用std::iterator_traits::iterator_category
来确定迭代器的类型。
基于此,它可以决定如何推进事物。