Can range-based C++11 for do/check extra operations/conditions?

Unfortunately, you can't put the increment into the range based for loop. However, in your specific case - as std::vector stores its elements contigously in memory - you can simulate option 2 by falling back to pointers (thanks to @M.M and @Jarod42 for corrections and improvements):

for ( const int& val : v )  {
    std::cout << "v at index " << &val-v.data() << " is " << val; 
}

more generic:

for ( const auto& val : v )  {
    std::cout << "v at index " << std::addressof(val)-v.data() << " is " << val; 
}

The other thing you can do is to write a index_range class, that represents a collections of indexes over which you can iterate in your range based for loop:

struct index_range_it {
    size_t idx;
    size_t operator*(){
        return idx;
    }
    index_range_it& operator++() {
        idx++;
        return (*this);
    }
};

bool operator!=(index_range_it l,index_range_it r) {
    return l.idx != r.idx;
}

struct index_range {
    size_t size;
    index_range_it end(){return index_range_it{size};}
    index_range_it begin(){return index_range_it{0};}
};

int main()
{
    for (auto i: index_range{v.size()}){
        std::cout << "v at index " << i << " is " << v[i]; 
    }        
}

A full fledged implementation of this idea can be found e.g. here

Such a range can then also be composed to something, where the iterator returns a proxy object containing the index as well as a reference to the current object and with c++17's structured binding that would be even more convenient to use.


Take a look at range-v3 and cppitertools.

cppitertools provides a very convenient enumerate:

std::vector<int> v = { 1, 2, 3, 4, 5 };
for (auto&& e : enumerate(v))
{
    std::cout << "v at index " << e.index << " is " << e.element;
}

Range-v3 unfortunately has no enumerate, which makes me very sad, but you can compose your own using view::ints and view::zip*. Range-v3 has the big advantage that it is the basis for the proposed ranges in for standard library. The range composition allows to build clean abstractions.

Regarding your last example, I would argue that you should avoid a loop altogether if you need to reduce the complexity. Instead use an appropriate algorithm such as std::find_if, std::any_of that matches your task without you having to express control flow.


For a general container, you cannot get the index nor the iterator from a range-based loop. Instead you either have to keep a separate variable, or go back to the iterator loop.

The iterator look can be written a bit more simply since C++11:

for( auto iter = begin(v); iter != end(v); ++iter )

For the specific case of a vector you can do:

for ( auto& val : v )
{
    cout << "Index is " << (&val - &v[0]) << '\n';
}

which works because vectors use contiguous storage.