Search code examples
c++c++11for-loopauto

Using range based for loop to replace traditional nested loops in C++11


I am trying to apply the range based for loop from C++11 std in some of my existing code which has a lot of nested loops like the one below:

vector<MyClass const*> myClassVec ; 
for(vector<MyClass const*>::const_iterator itr_m(myClassVec.begin()); itr_m != myClassVec.end(); ++itr_m) {
        const MyClass* star_m(*itr_m) ;
        <<<<Do something with star_m>>>>>
        for(vector<MyClass const*>::const_iterator itr_n(itr_m +1); itr_n != myClassVec.end(); ++itr_n) {
            const MyClass* star_n(*itr_n) ;
            if (star_m->GetIndex() == star_n->GetIndex()) {
                    <<Do something>>
            }
        }
}   

I want to use auto variable and range based for loop here to make my code simpler. I was easily able to apply these to the outer loop but I am stuck at how to do this for the inner loop. Are range based loops not meant for situations like the inner for loop where you need to loop through a limited range of the container ?

The code I wrote to replace the above nested loop code and which obvious throws compile errors for the inner for loop:

vector<MyClass const*> myClassVec ; 
for(const auto& itr_m : myClassVec) {
    const MyClass* star_m(itr_m) ;
    <<<<Do something with star_m>>>>>   
    for(const auto& itr_n(itr_m +1);itr_n != myClassVec.end();++itr_n) {                
        const MyClass* star_n(*itr_n) ;
        if (star_m->GetIndex() == star_n->GetIndex()) {
            <<Do something>>
        }
    }
}

Compile error is as follows: error C2679: binary '!=' : no operator found which takes a right-hand operand of type 'std::_Vector_iterator<_Myvec>' (or there is no acceptable conversion)

Could somebody pls shed some light on how to replace the inner for loop and what are typical scenarios where the range based for loops are NOT meant to be used. Thanks in Advance!


Solution

  • Your case actually is a typical case where range-based iteration can't be used. You can use it whenever you don't care about the position of the element/iterator in the container. Conversely, if you need the index of the current element (or an iterator pointing to it), classical loops are needed.*

    See your example:

    for(const auto& itr_m : myClassVec)
    

    Here, itr_m is not an iterator, but a reference to a MyClass const*, which means that you lost all information about the position of the element.

    *You could of course keep track of the current element in a range-for loop, but that would defeat its purpose and make the code harder to read.