Boost logo

Geometry :

Subject: [ggl] pre-/post-increment op on iterators
From: Mateusz Loskot (mateusz)
Date: 2009-04-29 16:52:50


Barend Gehrels wrote:
> Mateusz Loskot wrote:
>> I think it can be solved with a thin iterator adapter that
>> dereferences to segment, instead of to point.
>> The adapter, or a view as called in some situations, should do the job.
>>
>>
> It will probably be something like that. However, it'll need a local
> variable "segment" which is then dereferenced. What if the iterator goes
> next? Is the local variable copied? Didn't do such a thing before.

We definitely don't want to dereference by-value (make a copy of segment
object) but by reference, so we need to cache segment object
created/filled with coordinates read from the adapted vector..
The cache is simply a member variable of adaptor iterator.

Roughly drawing the idea, it could be something like this:

struct segment; // our segment type

template <typename Iterator>
struct segment_iterator
{
   typedef Iterator iterator_type;
   typedef std::input_iterator_tag iterator_category;
   typedef typename std::iterator_traits <Iterator>::difference_type
difference_type;
   typedef segment value_type;
   typedef segment* pointer;
   typedef segment const& reference;

   explicit segment_iterator(iterator_type it)
        : m_it(it), m_prev(m_it)
    {
       // move to 2nd point
       ++m_it;

      // TODO: check, somehow, if m_it is not pass the end
      // Possibly container which iterator is being
      // adapted store only 1 point
    }

   reference operator*() const
   {
      // Lazy, so make segment when needed, on dereference not
      // on incrementation

      // TODO
      // 1. make segment from 2 points
      m_cache.first = *m_prev;
      m_cache.second = *m_it;

      // 2. Cache segment as m_segment
      return m_cache;
   }

   pointer operator->() const
   {
       return &(operator*());
   }

   segment_iterator& operator++()
   {
      // TODO: advance position
      ++m_prev;
      ++m_it;

      return *this;
    }

   segment_iterator operator++(int)
   {
      segment_iterator it(*this);
      ++(*this);
      return it;
   }

   // access iterator being adapted
   iterator_type base() { return m_it; }
   iterator_type base() const { return m_it; }

private:

   segment m_cache;

   iterator_type m_it;
   iterator_type m_prev;
};

template <typename Iterator>
bool operator==(segment_iterator<Iterator> const& lhs,
                segment_iterator<Iterator> const& rhs)
{
    return (lhs.base() == rhs.base());
}

template <typename Iterator>
bool operator==(segment_iterator<Iterator> const& lhs,
                segment_iterator<Iterator> const& rhs)
{
    return (lhs.base() != rhs.base());
}

It seems to make sense to have object generator like make_segment_iterator.

What you think about this idea?

> I'm currently busy in core, multi_core and probably some
> (multi)algorithms...

OK, great!

-- 
Mateusz Loskot, http://mateusz.loskot.net
Charter Member of OSGeo, http://osgeo.org

Geometry list run by mateusz at loskot.net