3

With a random access iterator, you can change the stride length by simply doing iter+=n and then using < container.end() instead of != container.end() as the loop ending condition:

#include <iostream>
#include <vector>

int main(int argc, char *argv[])
{
  typedef std::vector<float> VectorType;
  typedef VectorType::const_iterator IteratorType;

  VectorType v;
  for(unsigned int i = 0; i < 11; ++i)
  {
    v.push_back(i);
  }

  for(IteratorType iter = v.begin(); iter < v.end(); iter += 2)
  {
    std::cout << " " << *iter;
  }

  return 0;
}

However both += 2 and < iter.end() seem to be undefined for something like std::set. It seems reasonable to want traverse a set only visiting every other element (subsampling it), no? Is there another way to do this?

David Doria
  • 9,873
  • 17
  • 85
  • 147
  • I'm on an iPad, so I can't experiment with the code at the minute, but I'm just wondering if you've tried this using a non const iterator? –  Feb 22 '12 at 00:46

2 Answers2

4

With a random access iterator, you can change the stride length by simply doing iter+=n and then using < container.end() instead of != container.end() as the loop ending condition

Actually, you cannot. While the code may compile, it exhibits undefined behavior at runtime if the iterator is actually advanced past the end of the container. You cannot increment an iterator beyond the end of the range into which it points.

In any case, you can write a function template to help:

template <typename TForwardIt, typename TDifference>
bool try_advance(TForwardIt& it,
                 TForwardIt const end,
                 TDifference n)
{
    TDifference i(0);
    while (i < n && it != end)
    {
        ++i;
        ++it;
    }

    return i == n;
}
James McNellis
  • 348,265
  • 75
  • 913
  • 977
  • If you made this call one of two functions, one taking random access and one taking other iterators, that'd be better for vectors and such. – Mooing Duck Feb 22 '12 at 01:15
  • @James McNellis: Cool, thanks. I used it like this: IteratorType iter = v.begin(); while(try_advance(iter, v.end(), 2)) { std::cout << " " << *iter; } What was the idea of TDifference? why not just: template bool try_advance(TForwardIt& it, TForwardIt const end, const unsigned int n) { unsigned int i = 0; while (i < n && it != end) { ++i; ++it; } return i == n; } ? – David Doria Feb 22 '12 at 12:42
2

I'm on an iPad, so I can't test this, but try the following

std::advance(iter, 2);
Mark Wilkins
  • 40,729
  • 5
  • 57
  • 110