Boost logo

Boost :

From: Jeremy Siek (jsiek_at_[hidden])
Date: 2000-11-24 14:56:08


Hi Dave and John,

Upon updating the test code for indirect iterators I realized there's a
problem with the way we are currently getting the inner const iterator
type. (for T**, I'm using "inner" to mean T* and "outer" to mean T**)

Currently we are just trying to add a "const" qualification to the inner
iterator (iterator_traits<T**>::value_type) to get the inner const
iterator (const iterator_traits<T**>::value_type). I think this is wrong
for a couple reasons. First, I think adding the const there gives you a
const iterator instead of an immutable iterator (the const needs to apply
to the thing pointed at). Second, if the inner iterator types in question
are not real pointers like T*, then there is no way to deduce the
const_iterator type from the iterator type.

Given this, I think the interface for indirect iterator needs to change so
that both inner iterator types are explicitly provided by the user.

Also, the interface currently asks the user for both the const and
non-const version of the outer iterator. This is not necessary since
we really don't care whether the outer iterator is mutable or not.

So here's what I think indirect_iterators should look like:

template <class IndirectIterator, // Mutable or Immutable, doesn't matter
          class Iterator, // Mutable
          class ConstIterator, // Immutable
          class IndirectTraits = std::iterator_traits<IndirectIterator>,
          class Traits = std::iterator_traits<Iterator>,
          class ConstTraits = std::iterator_traits<ConstIterator>
>
struct indirect_iterators
{
    typedef typename Traits::value_type ValueType;
    typedef iterator_adaptors<IndirectIterator, IndirectIterator,
        indirect_traits<IndirectIterator, IndirectTraits, Traits>,
        indirect_traits<IndirectIterator, IndirectTraits, ConstTraits>,
        indirect_iterator_policies
> Adaptors;
    typedef typename Adaptors::iterator iterator;
    typedef typename Adaptors::const_iterator const_iterator;
};

Here is John's example again, updated to use the new interface.
If you get rid of the #if 0 you'll see that the const iterator
correctly prevents writing to the immutable value.

#include <vector>
#include <boost/pending/iterator_adaptors.hpp>

int main () {
  typedef std::vector<int*> Ptr_vector;
  typedef Ptr_vector::const_iterator const_outer_iterator;
  typedef int* inner_iterator;
  typedef const int* const_inner_iterator;

  {
    typedef boost::indirect_iterators<const_outer_iterator,
inner_iterator,
      const_inner_iterator> IndirectIters;
    typedef IndirectIters::iterator indirect_iterator;
    typedef IndirectIters::const_iterator const_indirect_iterator;
    
    Ptr_vector v(1);
    v[0] = new int(4);

    indirect_iterator it = v.begin();
    *it = 5;
    const_indirect_iterator cit = v.begin();
#if 0
    // this should fail to compile
    *cit = 5;
#endif
  }
  return 0;
}

----------------------------------------------------------------------
 Jeremy Siek www: http://www.lsc.nd.edu/~jsiek/
 Ph.D. Candidate email: jsiek_at_[hidden]
 Univ. of Notre Dame work phone: (219) 631-3906
----------------------------------------------------------------------


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk