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

Edu*_*yan 2 c++ iterator stl time-complexity

请看一下这个std::advance功能.根据cppreference,复杂性是:

线性.但是,如果InputIt另外满足RandomAccessIterator的要求,则复杂性是不变的.

因此,如果我传递一个迭代器和一个整数,程序如何推导它是什么迭代器以及它是如何实现的?那么这个功能有2个重载或者是什么?

Max*_*kin 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{});
}
Run Code Online (Sandbox Code Playgroud)

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

IMO,std::next有一个更好的接口,std::advance因为它返回迭代器,因此调用不必占用自己的代码行.

  • @EduardRostomyan`std :: iterator_traits`专门用于原始指针.原始指针是随机访问迭代器. (4认同)

son*_*yao 6

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

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

BTW:std::iterator_traits专门用于原始指针; 他们总是RandomAccessIterator.

那么这个功能有2个重载或者是什么?

没有更多的重载std::advance,实现通常会实现几个辅助函数重载,这些重载根据iterator_category调用std::advance.