Is it possible to get a const iterator from a vector that can only iterate a certain range of the vector before being invalidated?
For example if I have a vector of 10 elements, I want to return an iterator of elements 4 to 7.
pseudo-code:
int main()
{
std::vector<int> vector = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
auto iterator = GetRangedIterator(vector, 4, 7)
for (const int& num : iterator)
print num; // 4, 5, 6, 7
}
Use a for loop and reference pointer In C++ , vectors can be indexed with []operator , similar to arrays. To iterate through the vector, run a for loop from i = 0 to i = vec. size() .
Vector's iterators are random access iterators which means they look and feel like plain pointers. You can access the nth element by adding n to the iterator returned from the container's begin() method, or you can use operator [] . std::vector<int> vec(10); std::vector<int>::iterator it = vec.
In general: If you pass a non- const reference, the caller doesn't know if the iterator is being modified. You could pass a const reference, but usually iterators are small enough that it gives no advantage over passing by value.
This is pretty trivial to do (though I'd call the result a range, not an iterator).
A simple implementation would look something like this:
template <class Iter>
class range {
Iter b;
Iter e;
public:
range(Iter b, Iter e) : b(b), e(e) {}
Iter begin() { return b; }
Iter end() { return e; }
};
template <class Container>
range<typename Container::iterator>
make_range(Container& c, size_t b, size_t e) {
return range<typename Container::iterator> (c.begin()+b, c.begin()+e);
}
As it stands right now, this follows normal C++ conventions (0-based counting, the end you specify is past the end of the range, not in it) so to get the output you asked for, you'd specify a range of 3, 7
, like:
for (int num : make_range(vector, 3, 7))
std::cout << num << ", "; // 4, 5, 6, 7,
Note that the range-based for
loop knows how to use begin
and end
member functions to tell it the range it's going to iterate, so we don't have to deal with invalidating iterators or anything like that, we just have to specify the beginning and end of the range we care about.
You could use the range-v3 library that is the bases of a Ranges TS which will been part of C++20, but the library already works with C++11 compilers. Here's how:
#include <range/v3/all.hpp>
#include <iostream>
#include <vector>
int main()
{
using namespace ranges;
auto v = view::iota(1, 11) | to_<std::vector<int>>();
std::cout << view::all(v) << '\n';
auto rng = v | view::slice(3, 7);
std::cout << rng << '\n';
}
Live Example.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With