如何推导std :: advance迭代器类型?

时间:2018-06-22 13:31:53

标签: c++ stl iterator time-complexity

请查看std::advance函数。 根据cppreference,复杂度为:

  

线性。   但是,如果InputIt额外满足RandomAccessIterator的要求,则复杂性是恒定的。

因此,如果我传递一个迭代器和一个整数,程序如何推断出它是什么迭代器以及如何实现呢?那么该函数有2个重载吗?

2 个答案:

答案 0 :(得分:6)

  

程序如何推导它的迭代器以及如何实现?

它使用std::iterator_traits<T>::iterator_category确定迭代器类别,然后进行标签分派

std::iterator_traits专用于原始指针。原始指针是随机访问迭代器。

例如:

template<class I>
void doadvance(I& i, size_t n, std::random_access_iterator_tag) {
    i += n;
}

template<class I, class Tag>
void doadvance(I& i, size_t n, Tag) {
    while(n--)
        ++i;
}

template<class I>
void advance(I& i, size_t n) {
    using Tag = typename std::iterator_traits<I>::iterator_category;
    doadvance(i, n, Tag{});
}

在C ++ 17中,它可以使用if constexpr而不是 tag dispatch ,但这会使标准库不向后兼容。这就是为什么它必须继续使用标签分发

IMO,std::nextstd::advance具有更好的接口,因为它返回迭代器,因此调用不必占用其自己的代码行。

答案 1 :(得分:6)

  

程序如何推断出它是什么迭代器

std::iterator_traits被使用,即将检查std::iterator_traits<It>::iterator_category,如果它是std::random_access_iterator_tag,则表示它是RandomAccessIterator。

BTW:std::iterator_traits专用于原始指针;它们始终是RandomAccessIterator。

  

该函数有2个重载吗?

std::advance不再有重载,该实现通常实现几个辅助函数重载,这些重载根据std::advance中的iterator_category进行调用。