如何检查传递的Iterator是一个随机访问迭代器?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何检查传递的Iterator是一个随机访问迭代器?相关的知识,希望对你有一定的参考价值。

我有以下代码,它执行一些迭代器算术:

template<class Iterator>
void Foo(Iterator first, Iterator last) {
  typedef typename Iterator::value_type Value;
  std::vector<Value> vec;
  vec.resize(last - first);
  // ...
}

(last - first)表达式(AFAIK)仅适用于随机访问迭代器(如vectordeque中的那些)。如何检查传递的迭代器满足此要求的代码?

答案

如果Iterator是一个随机访问迭代器,那么

std::iterator_traits<Iterator>::iterator_category

将是std::random_access_iterator_tag。实现这个的最简洁方法可能是创建第二个函数模板并让Foo调用它:

template <typename Iterator>
void FooImpl(Iterator first, Iterator last, std::random_access_iterator_tag) { 
    // ...
}

template <typename Iterator>
void Foo(Iterator first, Iterator last) {
    typedef typename std::iterator_traits<Iterator>::iterator_category category;
    return FooImpl(first, last, category());
}

这样做的好处是,如果您愿意,可以为不同类别的迭代器重载FooImpl

Scott Meyers在一本有效的C ++书籍中讨论了这种技术(我不记得哪一本)。

另一答案

除了标签发送,您还可以使用std::random_access_iterator_tag直接将该类别与std::is_same_v进行比较:

using category = typename std::iterator_traits<Iterator>::iterator_category;
if constexpr (std::is_same_v<category, std::random_access_iterator_tag>) {
  vec.resize(last - first);
}

这有时会导致更清晰简洁的代码,特别是如果实现的一小部分(如保留向量大小)取决于迭代器类别。

以上是关于如何检查传递的Iterator是一个随机访问迭代器?的主要内容,如果未能解决你的问题,请参考以下文章

迭代器

STL源码分析-iterator(迭代器)

java 中 iterator 为啥翻译成迭代器呢

迭代器模式(Iterator.hasNaxt())

迭代器模式(Iterator Pattern)

Python迭代器(Iterator)