Reset a range based for loop

Apr 23, 2014 at 12:47am
In the traditional for loop, you could make the loop start again by resetting the int value

1
2
3
4
for (int i = 0; i < 10: ++i){
  //Do something
   i =0;
}


Then it would start the loop again. However I can not seem to find a way to do this with the range based for loop.

Is there anyway to force a range based for loop to start from, i = 0 ?

1
2
3
4
for(const auto &i : vec){
  //Do something
  //Restart for loop
}
Last edited on Apr 23, 2014 at 12:49am
Apr 23, 2014 at 1:56am
As far as I know there is no easy way to do this (without building some wrapper on top of everything etc). If you need this kind of behavior you might as well just stay with the "traditional" style.

I know a lot of people dislike ranged based for loops for limitations like this.
Technically you could put a label before the for loop and use goto under certain conditions to reset it, but then everyone will complain you used goto and it will rain fire and all that stuff.

Personally I would stay with your first example.
Apr 23, 2014 at 3:19am
You would have to play compiler to do that. The range-based for loop is syntactic sugar for something like this*:

1
2
3
4
5
for (type_of_xs::const_iterator xi = xs.begin(); xi != xs.end(); ++xi)
{
  const type_of_x& x = *xi;
  ...
}
1
2
3
4
for (const auto& x : xs)
{
  ...
}

* It's actually a bit more complicated than this, but it ultimately compiles to about the same thing.

What this means is that you do not have direct access to the range iterator itself.

Boost provides range adaptors for the most useful things. For example, if you want to iterate over only part of a range:
http://www.boost.org/doc/libs/release/libs/range/doc/html/range/reference/adaptors/reference/sliced.html

What you are asking to do sounds a little unkosher anyway. You might want to rethink your algorithm.

So, uh, what are you trying to do? Anything interesting?

Hope this helps.
Apr 23, 2014 at 3:31am
> Is there anyway to force a range based for loop to start from, i = 0 ?

1
2
3
4
restart: for(const auto &i : vec){
  //Do something
  goto restart ; //Restart for loop
}

http://coliru.stacked-crooked.com/a/0fda49e64f2e3633
Apr 23, 2014 at 9:50am
So, uh, what are you trying to do? Anything interesting?


Im part of a SAT solver, the clause propagation.

I'm looping through the vector removing certain elements, but I have found that when i remove one element from the vector, everything moves up one place to fill the gap, as it should.

However the for loop is moving onto the next element, which effectively means it is skipping the element which took the removed elements place

If this makes sense?
Apr 23, 2014 at 10:16am
You don't want a range-based for in the vicinity of iterator-invalidating operations.
Apr 23, 2014 at 10:20am
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <iostream>
#include <vector>

int main()
{
    std::vector<int> seq { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 } ;
        
    // remove odd elements as we are iterating
    for( auto iter = std::begin(seq) ; iter != std::end(seq) ;  )
    {
        if( *iter % 2 ) 
        {
            std::cout << "removing " << *iter << '\n' ;
            iter = seq.erase(iter) ; // returns an iterator to the elment immediately after 
                                     // the element that was removed (or end if there is none).
        }
        else ++iter ; // not erased; so increment iter
    }
        
    for( int v : seq ) std::cout << v << ' ' ;
    std::cout << '\n' ;
}

http://coliru.stacked-crooked.com/a/f6b298afaa84d72c
Apr 23, 2014 at 10:42am
JLBorges this makes sense, and I think would work, is there a way to adapt it for a vector of sets?

To clarify, I'm using a vector of sets. So this was my range based loop which would go through every set,

for(const auto &mySet : clauseVector){

This would return mySet, which was a set from the array

Im thinking this is trivial, but something is not quite clicking with me to translate it to code
Apr 23, 2014 at 11:05am
> is there a way to adapt it for a vector of sets?
> Im thinking this is trivial

It is trivial; and it works with any sequence container.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#include <iostream>
#include <list>
#include <set>
#include <numeric>

int main()
{
    std::list< std::set<int> > seq { { 0, 25, 7 }, { 1, 6, 12 }, { 20, 21, 22 }, { 1, 3, 7, 8 }, { 5, 6, 7, 8, 9 } } ;
    
    const auto print = [] ( const std::set<int>& set ) 
                          { std::cout << "[ " ; for( int v : set ) std::cout << v << ' ' ; std::cout << "]\n" ; } ;
        
    // as we iterate, remove sets which sum up to 19
    for( auto iter = std::begin(seq) ; iter != std::end(seq) ;  )
    {
        const auto& set = *iter ;
        if( std::accumulate( set.begin(), set.end(), 0 ) == 19 ) 
        {
            std::cout << "removing set " ;
            print(set) ;
            
            iter = seq.erase(iter) ; // returns an iterator to the elment immediately after 
                                     // the element that was removed (or end if there is none).
        }
        else ++iter ; // not erased; so increment iter
    }
     
    std::cout << "\nthe sequence now contains:\n" ;
    for( const auto& set : seq ) print(set) ;
}

http://coliru.stacked-crooked.com/a/3049368879dea914

The erase-remove idiom may be more appropriate.
http://www.cplusplus.com/forum/general/129501/#msg699368
Apr 23, 2014 at 12:30pm
Snnnider wrote:
I'm part of a SAT solver, the clause propagation.

I'm looping through the vector removing certain elements, but I have found that when i remove one element from the vector, everything moves up one place to fill the gap, as it should.

However the for loop is moving onto the next element, which effectively means it is skipping the element which took the removed elements place

If this makes sense?


Using the traditional for loop, you could decrease the value of the index variable by one, after deleting an element, so it checks that same position again.

Aceix.
Topic archived. No new replies allowed.