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 _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::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 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
::iterator,
value_type, reference, pointer,
std::random_access_iterator_tag>::type my_iterator;
typedef typename indirect_iterator_generator
::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
::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
::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