Boost logo

Boost Users :

From: Tim Robertson (timr_at_[hidden])
Date: 2003-07-08 06:26:07


Hi,

I've been trying to get indirect_iterator working in what seems (to me)
to be a straightforward context -- I have a std::vector of
boost::shared_ptr objects, and I need both const and non-const iterators
into the vector (I'm using the vector as the sole data member of a
container class, and I need the iterators to properly handle const and
non-const container types). This looks something like this:

class MyClass
{
   // ...
};

class MyContainer
{
   public:
     typedef MyClass value_type;
     typedef value_type & reference;
     typedef value_type * pointer;
     // and so on, for const_reference, const_pointer, etc...

     // ...

   private:
    std::vector<boost::shared_ptr<MyClass> > _data;
};

Now, the trouble comes when I attempt to define the iterators for
MyContainer using the indirect_iterator generators. If I do the obvious:

Approach #1:
------------

   typedef indirect_iterator_pair_generator<
    vector<shared_ptr<MyClass> >::iterator,
    value_type, reference, const_reference,
    std::random_access_iterator_tag,
    pointer, const_pointer>::itgen;

   typedef typename itgen::iterator my_iterator;
   typedef typename itgen::const_iterator my_const_iterator;

I find that the const_iterator generated is inadequate for use in a
container context. Particularly, it produces a my_const_iterator that
has the following constructor signature:

my_const_iterator(shared_ptr<MyClass> *)

Whereas, a const std::vector<shared_ptr<MyClass> > will produce
const_iterators that look like this:

const shared_ptr<MyClass> * const

This causes compilation problems, because inevitably, in this context,
you'll want to construct a my_const_iterator from a vector::const_iterator.

The problem seems obvious: the indirect_iterator_pair_generator class
is considering only non-const base iterators. This led me to try the
following:

Approach #2:
-----------

   typedef typename indirect_iterator_generator
     <typename vector<shared_ptr<MyClass> >::iterator,
      value_type, reference, pointer,
      std::random_access_iterator_tag>::type my_iterator;

   typedef typename indirect_iterator_generator
     <typename vector<shared_ptr<MyClass> >::const_iterator,
      value_type, const_reference, const_pointer,
      std::random_access_iterator_tag>::type my_const_iterator;

It seemed that this would solve the problem by independently generating
the two types of iterators that are needed (note how I've made the base
iterator type ::iterator in one, and ::const_iterator in the other).
However, with this method I always obtain compilation errors --
whereever there is a use of the operator->(), the following error is
produced (g++ 3.0.3 and 3.2 do the same thing, Linux and Mac OSX):

"result of `operator->()' yields non-pointer result"

I have yet to figure out what is causing this error. This led me to
attempt the following "solution" to the problem:

Approach #3:
-----------

   typedef indirect_iterator_pair_generator
   <typename vector<shared_ptr<MyClass> >::iterator,
    value_type,reference,const_reference,
    std::random_access_iterator_tag,
    pointer,const_pointer> itgen;

   typedef typename itgen::iterator my_iterator;

   typedef indirect_iterator_pair_generator
   <typename vector<shared_ptr<MyClass> >::const_iterator,
    value_type,reference,const_reference,
    std::random_access_iterator_tag,
    pointer,const_pointer> itgen2;

   typedef typename itgen2::const_iterator my_const_iterator;

This actually works! I can't explain why -- it seems like
indirect_iterator_pair_generator and indirect_iterator_generator should
behave identically when their template parameters are identical....

The way I see it, there's a bug in at least one of the indirect_iterator
generator objects. At the very least, indirect_iterator_pair_generator
and indirect_iterator_generator are behaving differently when their
parameter types are the same (compare approaches #2 and #3). But there's
also the issue of why approach #1 didn't work to begin with -- it
*seems* like indirect_iterator_pair_generator should produce a
const_iterator type that can be initialized with an iterator from a
const vector. This isn't the case.

If anyone can explain this to me, and convince me that I'm not going
insane, I'd appreciate it greatly ;-)

(Standard bug-report disclaimers: Current boost distribution, g++
3.0.x/3.2.x, both Mac OSX and Linux exhibit identical behaviour.)

-Tim


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