joeButler
joeButler

Reputation: 1711

Whats the best way to conditionally control the direction of a for loop

I've got a block in my code in which the for loop should run forwards or backwards depending on a condition.

if (forwards) {
    for (unsigned x = 0; x < something.size(); x++ ) {
        // Lots of code
    }

} else {
    for (unsigned x = something.size()-1 ; x >= 0 ; x-- ) {
        // Lots of code
    }
} 

Is there a nice way to set this up, so I don't repeat all the code within the for loop twice?

The 'something' in question is a std::vector<>, so maybe its possible with an iterator? (I'm not using C++11 )

Upvotes: 10

Views: 3692

Answers (4)

Alexandru Barbarosie
Alexandru Barbarosie

Reputation: 3002

Or you can do something like this:

for (unsigned x = (forward ? 0: something.size()); x != (forward ? something.size() :0); forward? x++: x-- ) {
    // Lots of code
}

The compiler will most likely optimize it and evaluate forward only once since it's value doesn't change in the for loop I assume.

Upvotes: 5

mattnewport
mattnewport

Reputation: 14077

template<typename Cont, typename Func>
Func directional_for_each(Cont c, bool forwards, Func f) {
    return forwards ? for_each(begin(c), end(c), f) : for_each(rbegin(c), rend(c), f);
}

Used like this:

vector<int> v;
// put stuff in v...
bool forwards = false;
directional_for_each(v, forwards, [](decltype(v[0]) x) {
    // Lots of code using x
});

As you're not using C++11 the lambda containing 'Lots of code using x' would have to be replaced with a function defined elsewhere.

Upvotes: 2

Drew Hall
Drew Hall

Reputation: 29065

Probably the easiest way is to convert Lots of code to a function with argument x and replace both loop bodies with a call to that function:

void do_lots_of_stuff(unsigned x) {
  // Lots of code
}

////////

if (forwards) {
  for (unsigned x = 0; x < something.size(); x++ ) {
    do_lots_of_stuff(x);
  }
} else {
  for (unsigned x = something.size()-1 ; x >= 0 ; x-- ) {
    do_lots_of_stuff(x);
  }
}

Upvotes: 6

Daniel Frey
Daniel Frey

Reputation: 56921

Separate the loop value from the value you use inside the loop:

for (unsigned x2 = 0; x2 < something.size(); x2++ ) {
    const int x = forward ? x2 : (something.size()-1) - x2;
    // Lots of code using x
}

Upvotes: 17

Related Questions