C ++ 11: loop vector with second element?

I have std::vector<std::string> v; (initialized). How can I use the range-for loop to access all elements except the first (by zero index). For all elements:

 for (const string & s: v) process(s); 

Instead of v , a range expression can be used. How can I write a range expression to skip the first element (or skip the first n elements) ?

I know how to get the effect using v.begin() + 1 and using the classic loop. I am looking for a new, more readable, recommended alternative for this. Perhaps something similar to slicing Python? ... like:

 for s in v[1:]: process(s) 
+5
source share
2 answers

Create a wrapper for which begin () and end () return the correct iterators, and then you can use this as the second argument.

 #include <iostream> #include <vector> template< typename Collection > class FromNth { Collection& coll_; size_t offset_; public: FromNth( Collection& coll, size_t offset ) : coll_( coll ), offset_( offset ) { } // will nicely resolve to const_iterator if necessary auto begin() const -> decltype( coll_.begin() ) { return coll_.begin() + offset_; } auto end() const -> decltype( coll_.end() ) { return coll_.end(); } }; template< typename Collection > FromNth<Collection> makeFromNth( Collection& collection, size_t offset ) { return FromNth<Collection>( collection, offset ); } template< typename Collection > auto begin( const FromNth<Collection> & wrapper ) -> decltype( wrapper.begin() ) { return wrapper.begin(); } template< typename Collection > auto end( const FromNth<Collection> & wrapper ) -> decltype( wrapper.end() ) { return wrapper.end(); } int main() { std::vector< int > coll { 2, 3, 5, 7, 11, 13, 17, 19, 23 }; for( auto x : makeFromNth( coll, 1 ) ) { std::cout << x << '\n'; } return 0; } 

Note that my fromNth "begin" is undefined behavior if the input size is less than the offset. (If it is equal, then it is clearly defined and starts == end). Therefore, first check the size.

Note. If you are using an updated version of boost, then iterator_range may already provide you with a “collection” that looks like my “FromNth”.

 for( auto const& s : boost::make_iterator_range( v.begin() + 1, v.end() ) ) { process( s ); } 

Note: the code above worked on CodingGround using C ++ 11 GNU 4.8.3. (This site is very slow, though). From C ++ 14 you will not need the operators → decltype (which are required in C ++ 11 for templates).

Output:

 sh-4.3$ g++ -std=c++11 -o main *.cpp sh-4.3$ main 3 5 7 11 13 17 19 23 
+5
source

Until the ranges fall into the standard library, you will get nothing better than vanilla for a loop in plain C ++:

 for(auto i = begin(v) + 1, e = end(v); i !=e; ++i) // Do something with *i 
+5
source

All Articles