YAKOVM
YAKOVM

Reputation: 10153

traverse std::list , holding 2 last values

I need to traverse the std::list holding 2 last values,i.e if my list is [1,2,3,4,5,6]

iteration1 : v1 = 1, v2 = 2
iteration2 : v1 = 2, v2 = 3
iteration3 : v1 = 3, v2 = 4
iteration4 : v1 = 4, v2 = 5
iteration5 : v1 = 5, v2 = 6

I tried to

auto next = _contour.begin();
auto prev = next;

while( next != _contour.end())
{
    prev = next;
    next++;
}

But it doesn't work good - there is a problem at the end of traverse. In the last iteration next is pointing outside the list.

How can I do this correctly with good performance I don't want at each iteration check next?

Upvotes: 0

Views: 71

Answers (2)

cdhowie
cdhowie

Reputation: 169018

The problem, as you've hinted at, is that you check if next != _contour.end() before incrementing it, and after incrementing it you cannot be certain that it's not equal to the end iterator.

To solve this problem, switch around the logic in your loop such that you test the new value of next before each iteration.

For example:

auto current = _contour.begin();
// Make sure the list isn't empty before we go charging ahead.
if (current != _contour.end()) {
    decltype(current) prev;

    while ((prev = current), (++current != _contour.end())) {
        std::cout << "v1:" << *prev << " v2:" << *current << std::endl;
    }
}

(Demo)

Upvotes: 2

Swift - Friday Pie
Swift - Friday Pie

Reputation: 14589

Your loop should have increment and check condition swapped around to not go out of bounds. It can be done in several ways, using various loops, e.g.

   auto  next = _contour.begin();
   auto prev = next;

   if( !_contour.empty())
     while( ++next != _contour.end())
     {
        //std::cout << *prev << ":" << *next << std::endl;
        prev = next;
     }

Or one-liner for:

  if( !_contour.empty())
     for(auto next = _contour.begin(), prev = next; ++next != _contour.end(); prev = next )
     {    
         //std::cout << *prev << ":" << *next << std::endl;
     }

Upvotes: 0

Related Questions