|
Boost : |
From: David Abrahams (david.abrahams_at_[hidden])
Date: 2001-10-02 16:35:13
----- Original Message -----
From: <michel.andre_at_[hidden]>
> > template <class Difference, class BaseType1, class BaseType2>
> > Difference distance(type<Difference>, const BaseType1& x, const
> > BaseType2& y) const {}
> >
> > As I understand it, the "BaseType1/2" is misleading, because the
> > parameter is not the base iterator, it's the adapted iterator. Do I
> > understand correctly? I hope so, because it would be impossible to
> > make this work for adaptors that have internal state otherwise.
>
> It seems from the source code that it is the Base or underlying
> iterator thats sent into to the policy class.
>
> I'm wrestling with a similar problem and the iterator_adaptors i want
> to keep all state in the "begin()" iterator and have the "end()" with
> just a flag saying endIterator and this means to be able to determine
> equality i need the policy objects for both rhs and lhs in the equal
> method of the policy class.
>
> template <class Iterator1, class Iterator2>
> bool equal(const Iterator1& x, const Iterator2& y) const
This is a problem which occurred to me long after Jeremy started storing a
policies object in the iterator adaptor so he could keep extra state. Hey,
Jeremy!
> The reason for my design is that the iterator generated by begin
> contains both the start and the end of the iteration and in some
> cases even a pointer to the container of the elements to iterate over.
>
> Is there some solution to this problem? Or do i have to "adapt" the
> base iterator with my state (using eg inheritance) and then use the
> iterator_adapter to adapt my "adaption" to get it to work?
If inheritance works for you (remember, you can't inherit from a pointer),
then go for it. That seems like the easiest approach. Otherwise, consider
std::pair<IteratorType,StateData> or the equivalent.
We should probably think about changing the design. I think a
backwards-compatible change is possible, but I don't think the extra cruft
implied is desirable:
struct default_iterator_policies
{
// Some of these members were defined static, but Borland got confused
// and thought they were non-const. Also, Sun C++ does not like static
// function templates.
template <class Base>
void initialize(Base&)
{ }
// The "type<Reference>" parameter is a portable mechanism for
// the iterator_adaptor class to tell this member function what
// the Reference type is, which is needed for the return type.
template <class Reference, class Base>
Reference dereference(type<Reference>, const Base& x) const
{ return *x; }
template <class Iterator>
void increment2(Iterator& x)
{ x.policies().increment(x.iter()); }
template <class Base>
void increment(Base& x)
{ ++x; }
template <class Iterator>
void decrement2(Iterator& x)
{ x.policies().decrement(x.iter()); }
template <class Base>
void decrement(Base& x)
{ --x; }
template <class Iterator, class DifferenceType>
void advance2(Iterator& x, DifferenceType n)
{ x.policies().advance(x.iter(), n); }
template <class Base, class DifferenceType>
void advance(Base& x, DifferenceType n)
{ x += n; }
.
.
.
You get the idea. Now you can redefine difference2 instead of difference to
get the behavior you want. Hmm, have I just invented a new kind of
compile-time virtual function here? ;-)
Anyway, I'd like to discuss with the group whether backwards-compatibility
is paramount. Should we maintain the status quo, crufty-up the design and
the documentation to maintain backward-compatibility, provide a transition
path using #ifdefs, or something else?
===================================================
David Abrahams, C++ library designer for hire
resume: http://users.rcn.com/abrahams/resume.html
C++ Booster (http://www.boost.org)
email: david.abrahams_at_[hidden]
===================================================
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk