Reputation: 2459
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?
Upvotes: 1
Views: 458
Reputation: 238461
What's the easiest way to create two iterators, where iterating from the first one to the second takes you from 0 to N?
It seems that you're describing std::ranges::iota_view
. Use begin
and end
to get the pair of iterators that you're looking for.
in C++11
Unfortunately, std::ranges::iota_view
was introduced in C++20 and the original library ranges_v3 requires C++14.
But, there are other implementations of the same idea such boost::counting_iterator
that work in C++11.
Or if you want to write the iterator from scratch, you can look at how the mentioned pre-existing implementations have been implemented. Writing custom iterators involves a ton of boilerplate, but this is among the simplest iterators that can be written.
Upvotes: 2
Reputation: 30694
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()}
);
}
Upvotes: 3