如何实现std::advance来改变迭代器类型上的行为
How is std::advance implemented to change behavior on iterator type?
我们对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
来确定迭代器的类型。
在此基础上,它可以决定如何推进事情。
相关文章:
- 使用std::multimap迭代器创建std::list
- 来自 std::list 的迭代器 .end() 按预期返回"0xcdcdcdcdcdcdcdcd"但 .begin()
- C++中带有List类的迭代器Segfault
- 如何在c++迭代器类型中包装std::chrono
- 集合上的输出迭代器:assign和increment迭代器
- Boost Spirit,获取迭代器内部语义动作
- 对于set上的循环-获取next元素迭代器
- 为什么output_editor Concept不需要output_e迭代器标记
- c++17文件系统::recursive_directory迭代器()在mac上没有给出这样的目录,但在windows上
- 使用迭代器时如何访问对象在向量中的位置?
- std::vector::迭代器是否可以合法地作为指针
- 跟随整数索引列表的自定义类迭代器
- 不明白迭代器,引用和指针失效,一个例子
- 我可以使用反向迭代器作为ForwardIt吗
- ESP8266单片机矢量迭代器的C++问题
- std::list 的 end() 迭代器位置在擦除时会改变吗?
- 如果vector改变,迭代器是否指向相同的元素?或者怎么做
- 包装STL vector并改变其迭代器的行为
- 如何实现std::advance来改变迭代器类型上的行为
- 当我改变矢量时迭代器发生了什么