C++11: Range-based for loop

In C++03, if I have a vector and want to show its elements, I could do something like this:

template <typename T>
void show(const T& x)
{
	for (typename T::const_iterator i = x.begin(); i != x.end(); i++)
		cout << *i << endl;
}

That method will be useful to show any collection that has a begin() and an end() and an iterator with an operator++(int), an operator!=() and an operator*() properly implemented.

C++0x provides us a very useful range-based for loop that makes iterations easier to write and read. This new for loop works also with plain-old arrays.

So, my code above can be rewritten like this in C++0x:

template <typename T>
void show(const T& x)
{
	for (auto& i : x)
		cout << i << endl;
}

As you see, the syntax is very similar to the Java “improved-for” loop and the resulting code is far easier to write and to understand than the old one.

In the next example you will see how this new for can be used with several containers and arrays in C++0x:

#include <vector>
#include <array>
#include <iostream>

using namespace std;

template <typename T>
void show(const T& t)
{
	for (auto& i : t)
		cout << i << endl;
}

int main()
{
	int ints[] = { 10, 20, 30, 40, 50 };
	show(ints);

	cout << "*****" << endl;

	vector<string> s = { "Monday", "Tuesday",
						 "Wednesday", "Thursday",
						 "Friday", "Saturday", "Sunday" };

	show(s);
	
	cout << "*****" << endl;
	
	array<string, 12> m = { "January", "February",
							"March", "April", "May",
						    "June", "July", "August",
						    "September", "October",
						    "November", "December" };

	show(m);						    
	cout << "*****" << endl;


	return 0;	
}

Your own classes could be iterated using the new for if you implement the needed methods:

#include <vector>
#include <array>
#include <iostream>

using namespace std;

template <typename T>
void show(const T& t)
{
	for (auto& i : t)
		cout << i << endl;
}


class RangeIterator
{
	private:
		int _index;
		
	public:
		RangeIterator(int index) : _index(index) { }
		
		bool operator!=(const RangeIterator& x) const
		{
			return _index != x._index;
		}
		
		const int& operator*() const
		{
			return _index;
		}
		
		int& operator++()
		{
			return ++_index;
		}
};

template <int N, int M>
class Range
{
	public:
		typedef const RangeIterator const_iterator;
		
	    const_iterator begin() const
	    {
	    	return const_iterator(N);
	    }
	    
		const_iterator end() const
		{
			return const_iterator(M);
		}
};

int main()
{
	Range<10, 20> r;
	show(r);

	return 0;	
}

The class to be iterated needs to have a begin() and an end() method that should return an iterator. An iterator is basically a class that implements an operator++(), an operator!=() and an operator*() to access to the next element, to verify if there are more available elements and to return the current element respectively.

Advertisements

8 thoughts on “C++11: Range-based for loop

  1. Are `begin()` and `end()` member functions sufficient to make user-defined classes usable as ranges? The standard specifies that these are called as free functions. I expect there’s a template in the `std` namespace to forward these calls to members (although I don’t see where in the C++0x draft this is specified, nor in which header such a template resides), but if your class doesn’t live in `std` wouldn’t you have to write these free functions yourself?

  2. Hi Rob, you are completely right. What I suppose is that if you do not provide your own begin() and end() free functions, the compiler generates a forwarder that invokes the begin() and end() methods of the object you passed as parameter; and it should work… but I’m just speculating.

    Anyway, I modified my example of my post as shown below, and it also works. As you can see in the example, I provide begin() and end() as free functions that just forward the message to xbegin() and xend() implemented as methods of my RangeIterator class.

    
    #include <vector>
    #include <array>
    #include <iostream>
    
    using namespace std;
    
    template <typename T>
    void show(const T& t)
    {
    	for (auto& i : t)
    		cout << i << endl;
    }
    
    class RangeIterator
    {
    	private:
    		int _index;
    
    	public:
    		RangeIterator(int index) : _index(index) { }
    
    		bool operator!=(const RangeIterator& x) const
    		{
    			return _index != x._index;
    		}
    
    		const int& operator*() const
    		{
    			return _index;
    		}
    
    		int& operator++()
    		{
    			return ++_index;
    		}
    };
    
    template <int N, int M>
    class Range
    {
    	public:
    		typedef const RangeIterator const_iterator;
    
    	    const_iterator xbegin() const
    	    {
    	    	return const_iterator(N);
    	    }
    
    		const_iterator xend() const
    		{
    			return const_iterator(M);
    		}
    };
    
    template <typename T>
    auto begin(const T& r) -> decltype(r.xbegin())
    {
    	return r.xbegin();
    }
    
    template <typename T>
    auto end(const T& r) -> decltype(r.xend())
    {
    	return r.xend();
    }
    
    int main()
    {
    	Range<10, 20> r;
    	show(r);
    
    	return 0;
    }
    
    1. std::begin and std::end functions are templates in header. Most general versions are specified to return result of calling argument’s begin/end function. There are also overloads for array types.

      1. Ahh, angle brackets have eaten “<iterator >” part from “in header <iterator >”

  3. is there any performance benefits of using range-based for loops? it certainly is less verbose and hence attractive, to me at least but what is going on under the hood?
    i used for loops all the time but then heard many gurus suggest that i should instead use standard library calls like for_each(), transform(), accumulate() etc … i got in to the habbit of avoiding for loops but now after discovering the range based for loops i could not hold back :(
    so r the c++ gurus in favour of using range based for loops over standard library calls?

    1. Actually do not know; but under the hood, I think the range-based for loop transforms your:

      for (auto& x : container)
         do_something(x);
      

      to:

      for (auto i = container.begin(); i != container.end(); ++i)
      {
        auto& x = *i;
        do_something(x);
      }
      

      so its performance depends heavily on the iterator’s performance.

      if you convert this to a for_each() based thing, it could be written in this way:

      for_each(container.begin(), container.end(), [](decltype(*container.cbegin())& x) { do_something(x); });
      

      that under the hood:

      1. creates an anonymous class with a functor inside.
      2. Instances such class
      3. and invokes the functor for every iteration in the loop; so, with no optimizations, I think the for_each()-like methods should behave poorer than the range-based for loop. What do you think?
      1. thanks for the reply and another thanks for teaching the for_each+decltype trick :)

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s