C++ Looping through a container

Example

In C++, looping through a sequence container c can be done using indexes as follows:

for(size_t i = 0; i < c.size(); ++i) c[i] = 0;

While simple, such writings are subject to common semantic errors, like wrong comparison operator, or wrong indexing variable:

for(size_t i = 0; i <= c.size(); ++j) c[i] = 0;
                     ^~~~~~~~~~~~~~^

Looping can also be achieved for all containers using iterators, with similar drawbacks:

for(iterator it = c.begin(); it != c.end(); ++it) (*it) = 0;

C++11 introduced range-based for loops and auto keyword, allowing the code to become:

for(auto& x : c) x = 0;

Here the only parameters are the container c, and a variable x to hold the current value. This prevents the semantics errors previously pointed.

According to the C++11 standard, the underlying implementation is equivalent to:

for(auto begin = c.begin(), end = c.end(); begin != end; ++begin)
{
    // ...
}

In such implementation, the expression auto begin = c.begin(), end = c.end(); forces begin and end to be of the same type, while end is never incremented, nor dereferenced. So the range-based for loop only works for containers defined by a pair iterator/iterator. The C++17 standard relaxes this constraint by changing the implementation to:

auto begin = c.begin();
auto end = c.end();
for(; begin != end; ++begin)
{
    // ...
}

Here begin and end are allowed to be of different types, as long as they can be compared for inequality. This allows to loop through more containers, e.g. a container defined by a pair iterator/sentinel.