Boost logo

Boost Users :

From: David Abrahams (dave_at_[hidden])
Date: 2006-07-15 10:16:07


"Seb Martel" <smartel_at_[hidden]> writes:

> Hello,
>
> given something like:
>
> class ProxyIterator
> : public boost::iterator_facade<ProxyIterator, Costly, boost::random_access_traversal_tag>
> {
> public:
> ProxyIterator(FactoryOfCostly* pF, int i ) : m_pFactory( pF ), m_index( i )
> {}
> private:
> friend class boost::iterator_core_access;
> void decrement() {--m_index;}
> // ... and others
>
> Costly& dereference() const
> {
> m_value = m_pFactory->MakeCostlyAtIndex( m_index );
> return m_value;
> }
> private:
> FactoryOfCostly* m_pFactory;
> int m_index;
> mutable Costly m_value;
> };

You might need to do something to prevent this from being reported as
a valid random access (or even forward) iterator. 24.1.3:

  --- If a and b are both dereferenceable, then a == b if and only if *a
      and *b are the same object.

> I cannot use this ProxyIterator with a boost::reverse_iterator adaptor because the implementation of reverse_iterator's dereference dereferences a temporary:
>
> // from reverse_iterator.hpp
> typename super_t::reference dereference() const { return *boost::prior(this->base()); }

> and in ProxyIterator, this dereference returns a reference to an
> internal member, m_value, that will immediately vanish out of
> existence. Bummer.

Yeah, bummer!

reverse_iterator is designed to be a better version of
std::reverse_iterator, but it does not solve this problem.

> What if reverse_iterator carried as member the decremented iterator
> instead of decrementing to a temporary on a dereference?

The problem then is that it either becomes less efficient, or
impossible to represent an end reverse iterator, because you can't
necessarily decrement the underly iterator you're passed:

         vector<int> v;
         make_reverse_iterator( v.begin() ); // undefined behavior

> In the current reverse_iterator implementation, decrement must
> behave properly on an end iterator, but not on a begin iterator. Can
> a begin iterator be decremented and still used for comparison
> purposes?

No.

You could build a reverse_iterator like the one you propose by storing
the inner iterator within a boost::optional wrapper, and only
initializing it upon dereference.

HTH,

-- 
Dave Abrahams
Boost Consulting
www.boost-consulting.com

Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net