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?
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));
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()}
);
}