tags:

views:

171

answers:

5

Hi,

I have a vector of IntRect: vector.

How can I iterate from both ends of the list and stop the iterator when the iterator intersects?

vector<IntRect>::iterator itr = myVector.begin();
  vector<IntRect>::reverse_iterator revItr.rbegin();

  for (; /*check itr and revItr does not intersect, and itr and revItr do not end */ ; ++itr, ++revItr) {
    IntRect r1 = *itr;
    IntRect r2 = *revItr;

    // do something with r1 and r2

  }

Thank you.

A: 

Your iterators point to the same thing if &(*itr) == &(*revItr)

Assuming nobody has done something stupid and overloaded operator& on IntRect.

rlbond
But take care of the special case where there are no elements in the sequence :)
Johannes Schaub - litb
Tom
You can't compare a reverse iterator to a "normal" iterator...
rlbond
@rlbond: that doesn't compare iterators; it compares addresses (actual raw pointers).
MSalters
No, I mean there's no `operator==` defined for those two types AFAIK.
rlbond
+1  A: 

You can use base function on the reverse iterator and compare the result with your forward iterator.

Remember that if you're moving both iterators, they will never be equal if the sequence has odd number of elements. You have to check the equality twice in each iteration.

avakar
Be careful with `base` -- it doesn't quite do what a lot of people think it does!(Namely, `base` does not point to the same element as the reverse iterator.)
rlbond
Indeed, there would be no base for `rend()` otherwise.
avakar
@avakar, agreed with your comments on my answer: I was over-generalizing. We should only care about random access iterators here, and provide a more optimized version for lists if we really need. Or we should really go a bit more lowlevel and do the two checks like you mention.
Johannes Schaub - litb
A: 

I would replace the second (reverse) iterator with a regular one and have that initialised to --myVector.end(). Instead of incrementing it, decrement it and compare the iterator values.

Timo Geusch
You can't initialize to `--myVector.end()` since `myVector.end()` is immutable.
rlbond
rlbond is correct. You can use `boost::prev` though.
avakar
You can however initialise to `myVector.end()` and then decrement it. Should've been clearer.
Timo Geusch
+4  A: 
if(!myVector.empty()) {
    for(vector<IntRect>::iterator forwards = myVector.begin(), 
                                  backwards = myVector.end()-1;
        forwards < backwards;
        ++forwards, --backwards) {

            // do stuff
    }
}

I think you need to check empty() with that implementation - suspect that end()-1 isn't defined if the vector is empty. I haven't used it before, but Dinkumware STL at least has operator < defined for vector iterators and it appears to do something sensible.

Also note that you need to check <, not just equality - that takes care of the (common) case where your vector has an even number of entries and the two iterators would step past one another.

Peter
Of course, `<` only works with Random Access Iterators...
rlbond
Yep, so does end()-1. Fortunately we know it's a vector :)
Peter
`begin()-1` is undefined, and therefore `end()-1` isn't defined for an empty vector either.
MSalters
+1  A: 

None of the answers that I've seen account for the two iterators "passing in the night."

vector<IntRect>::iterator forward = myVector.begin(), backward = myVector.end();

while (forward != backward)
{
    ++forward;

    // at this point they could be equal
    if (forward == backward)
        break;

    --backward;
}
keraba