Reverse Iteration with Range-Based For Loops in C++

Recently I faced a problem where I needed to make two passes over a vector, one iterating in a forwards direction and one in reverse. This is a simple task if you use the traditional loop style, but whenever I can I prefer to use C++11's range-based for loop for the primary reason that it is much easier to read, especially when a value is used many times within the loop body.

const std::vector<int> values { 5, 6, 7, 8, 9 };

// traditional for loop using an index
for (int i = 0; i < values.size(); ++i)
{
    std::cout << values[i];
}

// ... and in reverse
for (int i = values.size() - 1; i >= 0; --i)
{
    std::cout << values[i];
}

Expected output: 5678998765

Not too bad, but having to index into the container using the subscript operator every time a value is read isn't so easy on the eye and adds some extra typing too. Writing a reverse loop can also be error-prone, if you're not concentrating, due to unfamiliar indexing.

// traditional for loop with iterators
for (auto i = values.begin(); i < values.end(); ++i)
{
    std::cout << *i;
}

// ... and in reverse with iterators
for (auto i = values.rbegin(); i < values.rend(); ++i)
{
    std::cout << *i;
}
std::cout << std::endl;

When the auto keyword's meaning was changed in C++11 to become a placeholder type specifier, using iterators became much easier and clearer than before.

This is better, but we still have the initialisation, condition and iteration expressions to write, plus we still can't access the value without dereferencing the iterator. Having * dotted around definitely doesn't help to make things easier to read.

// range-based for loop
for (auto& i : values)
{
    std::cout << i;
}

Finally, the range-based version. Isn't that better? If you interpret the : as 'in' then it reads very well. This syntax is very concise, too. No more subscript operators or dereferencing. Great, but what about in reverse?

The range-based for loop works by using a range expression. If the range expression is an array, then the beginning of the range is determined to be the pointer to the first element of the array and the end is the beginning plus the array bounds. For class types, the compiler looks for begin() and end() methods. If those methods aren't found, then argument-dependent lookup is used to find non-member functions that are suitable. Once the range is determined, the declared variable (i in this case) is set to the dereferenced version of each element in the sequence, resulting in less work for us!

Amazing, but no syntax exists to specify iteration from the end to the beginning of a range. So how can we take advantage of this syntactic sugar if we want to iterate through a range in reverse? We know we have reverse iterators, so how can we get the compiler to use these instead?

Luckily, a few class and function templates can come to our rescue.

// a type that simply holds a reference to the object
// we want to iterate through in reverse
template<typename IterableType>
struct Reversed
{
    IterableType& iterable;
};

// non-member begin() function that returns the iterable's reverse equivalent
// we use a trailing return type for C++11 compatibility, C++14 doesn't require it
template<typename IterableType>
auto begin (Reversed<IterableType>& R) -> decltype (R.iterable.rbegin())
{
    return R.iterable.rbegin();
}

// non-member end() function, opposite to begin()
template<typename IterableType>
auto end (Reversed<IterableType>& R) -> decltype (R.iterable.rend())
{
    return R.iterable.rend();
}

// finally, a function that returns a new instance of the Reversed holder
template<typename IterableType>
Reversed<IterableType> reversed (IterableType& I)
{
    return { I };
}

A fairly minimal example, but for most cases this works beautifully! With the above code, iterating in reverse is as simple as it is forwards:

// range-based for loop in reverse
for (auto& i : reversed (values))
{
    std::cout << i;
}

View the full code on Compiler Explorer.

Original solution from Stack Overflow, adapted to work with C++11.

Focused on C++ software development and turning ideas into great products. Most of my experience comes from working in the music industry developing audio plug-ins with the JUCE framework. I've spent a lot of time building optimised, responsive user interfaces with JUCE and OpenGL.
Posts created 1

2 thoughts on “Reverse Iteration with Range-Based For Loops in C++

    1. Yep! As of C++20 this is now the preferred way. Thanks for pointing it out! I should probably update the article to mention this.

Leave a Reply

Your email address will not be published. Required fields are marked *

Begin typing your search term above and press enter to search. Press ESC to cancel.

Back To Top