Search code examples
c++c++11iterator

How can I create an iterator of a range of indexes in C++11?


I'm working with an API that takes a start and end iterator, and runs async work on the objects in that range. However, in one case I want to iterate over indexes of objects, not objects (from 0 to myVector.size() - 1). I could create a simple vector of those indexes and use its .begin() and .end() iterators, but that has unacceptable performance overhead.

What's the easiest way to create two iterators, where iterating from the first one to the second takes you from 0 to N?


Solution

  • If you have access to C++20, then you can use std::views::iota/std::ranges::iota_view to get a sequence of integers:

    std::vector<SomeType> vec = ...
    auto index_sequence = std::views::iota(std::size_t{0}, vec.size());
    some_function_needing_iterators(std::begin(index_sequence), std::end(index_sequence));
    

    Live Demo


    Under previous standards, you can write your own numeric range iterator pretty easily; it just requires a bit of boilerplate:

    template <typename T>
    class NumericRangeIterator
    {
    public:
        using difference_type = std::ptrdiff_t;
        using value_type = T;
        using pointer = T const*;
        using reference = T const&;
        using iterator_category = std::bidirectional_iterator_tag;
    
        explicit NumericRangeIterator(T n) : n_{n} {}
    
        reference operator*() const
        {
            return n_;
        }
    
        pointer operator->() const
        {
            return &n_;
        }
    
        NumericRangeIterator& operator++()
        {
            ++n_;
            return *this;
        }
    
        NumericRangeIterator operator++(int)
        {
            return NumericRangeIterator{n_++};
        }
    
        NumericRangeIterator operator--()
        {
            --n_;
            return *this;
        }
    
        NumericRangeIterator operator--(int)
        {
            return NumericRangeIterator{n_--};
        }
    
        bool operator==(const NumericRangeIterator& other) const
        {
            return n_ == other.n_;
        }
    
        bool operator!=(const NumericRangeIterator& other) const
        {
            return !(*this == other);
        }
    
    private:
        T n_;
    };
    
    int main() {
        std::vector<int> vec = ...;
        some_function_needing_iterators(
            NumericRangeIterator{size_t{0}},
            NumericRangeIterator{vec.size()}
        );
    }
    

    Live Demo