Range based for loops and pairs of iterators

In C++11, we now have range-based for loops. Given a container c, it is easy to write:

    for ( auto x : c ) { do something with x }

but the STL deals in pairs of iterators.
Given two iterators, f and l, I still have to write:

    for ( auto it=f; it != l; ++it ) { do something with *it }
  • The first time I typed that, I got it wrong – I put a ‘,’ instead of the second ‘;’
  • The second time I wrote that, I got it wrong again! – I used it < l instead of it != l.

Anyway, I would like to be able to write something like:

    for ( auto x : f,l ) { do something with x }

But there is no support for that in C++11.

Enter iterator_pair:

    template <typename Iterator>
    class iterator_pair {
    public:
        iterator_pair ( Iterator first, Iterator last ) : f_ (first), l_ (last) {}
        Iterator begin () const { return f_; }
        Iterator end   () const { return l_; }

    private:
        Iterator f_;
        Iterator l_;
    };

With this I can now write:

    for ( auto x : iterator_pair<type of f and l> ( f,l )) { do something with x }

which works, but is still annoying. Why should I have to put the type of the iterators there in my for loop? Worse than that, if this is in a template, I may not know what the type of f and l are!

But a helper function makes it all better:

    template <typename Iterator>
    iterator_pair<Iterator> make_iterator_pair ( Iterator f, Iterator l ) {
        return iterator_pair<Iterator> ( f, l );
    }

Now my code looks like I want:

    for ( auto x : make_iterator_pair ( f,l )) { do something with x }

and I’m happy (for now).

I’m pretty sure that there’s a better name for this, but I’m going with iterator_pair for the moment.

10 thoughts on “Range based for loops and pairs of iterators

  1. karsten

    I specialized std::begin and std::end for pairs to create a range-based for loop. This also work if a function returns a pair of iterators, which happens quite often.

    Reply
    1. Splinter of Chaos

      std::for_each feels a little messy for me. Comparing…

      for_each( f, l, [](auto x){ … } );

      with…

      for( auto x : make_iterator_pair(f,l) ) …

      Reply
    2. allyourcode

      What if you want to call this:

      template
      void DoStuff(Iterable iterable) {
      for (auto elt : iterable) {
      foo(elt);
      }
      }

      ? Then, you need something that has begin and end methods. iterator_pair FTW. I’m really surprised std lib does not have this already.

      Reply
  2. groovilus

    It is the point to get a range by iterators, so personally I’d call it make_iterator_range(f, l) or make_range_by_iterators(f, l). Anyway, a nice and simple solution.

    Reply

Leave a comment