Iterator for a subset of a vector

Is it possible to get a constant iterator from a vector that can only iterate a certain range of the vector before it is invalidated?

For example, if I have a vector of 10 elements, I want to return an iterator of elements 4 through 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 } 
+8
c ++ vector c ++ 11 range
source share
5 answers

This is pretty trivial (although I would 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 of now, this follows normal C ++ conventions (counting based on 0, the end you specify is outside the end of the range, not in it), so to get the result you requested, you must specify range 3, 7 , for example:

 for (int num : make_range(vector, 3, 7)) std::cout << num << ", "; // 4, 5, 6, 7, 

Note that in a range-based for loop, we know how to use the begin and end member functions to tell it the range in which it will go, so we don’t need to deal with invalid iterators or something like what we just need indicate the beginning and end of the range we care about.

+10
source share

You can use the range-v3 library, which is the TS range base that will be 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 .

+3
source share

There is nothing explicit in the standard library, but if you want to use Boost, you can use the following approach using the concept of range :

 auto range = boost::make_iterator_range(v.begin()+3, v.begin()+7); BOOST_FOREACH(int i, range) { cout << i << endl; } 

This should output 4567

+1
source share

You can use this

 for( it = v1.begin() + a; it <= v1.begin() + b; it++ ) 

The code below is a small demo

 #include <vector> #include <iostream> using namespace std; int main(){ vector<int> v1; for( int i = 0; i < 50; i++ ){ v1.push_back( 2*(i+1) ); cout<<v1.at(i)<<" "; } cout<<endl; vector<int>::iterator it; int a = 5; int b = 9; for( it = v1.begin() + a; it <= v1.begin() + b; it++ ){ cout<<(*it)<<" "; } cout<<endl; } 

Output signal

 2 4 6 8 10 12 14 16 18 20 22 24 26 28 30 32 34 36 38 40 42 44 46 48 50 52 54 56 58 60 62 64 66 68 70 72 74 76 78 80 82 84 86 88 90 92 94 96 98 100 12 14 16 18 20 
0
source share

You can use span :

 auto first_index = 3; auto last_index = 6; auto count = last_index - first_index + 1; auto interesting_nums = gsl::make_span(std::cbegin(vector) + start_index, count); for(auto& num : interesting_nums) { /* do stuff */ } 

Notes:

  • In your example, you got from the 4th to the 7th element, that is, the indices 3 through 6 that I used here.
  • This piece of code should work for any container, not just a vector.
  • gaps are part of GSL, support the C ++ Fundamentals library . They can officially enter the C ++ standard officially in 2020 and will be highly endorsed by the community.
-one
source share

All Articles