Boost logo

Boost :

From: troy d. straszheim (troy_at_[hidden])
Date: 2004-11-25 13:09:53


I'm wondering if there is any interest in a "type_iterator", built on
top of the iterator_adaptor. If so I'll send it out.

It is a kind of combination of transform_iterator and filter_iterator,
where the transform is a cast, and the filter predicate is whether or
not each entry in the container passes the cast. This you would want
to do when iterating over heterogenous containers (where you are
forced to reconstruct type information by downcasting) or containers
of boost::any. I was going to call it downcast_iterator but the
boost::any stuff isn't a downcast, so I came up with type_iterator.
Maybe cast_iterator is better?

Generally it looks like this

type_iterator<TypeThatIWant, UnderlyingIterator>

Here's an example:

struct Base {
  virtual ~Base() {}
};
struct Derived : public Base {
  virtual ~Derived(){};
  virtual void OnlyDerivedHasThis(){}
};

vector<Base*> v;
// love boost::assign
v += new Base, new Derived, new Base, ... etc.

type_iterator<Derived,vector<Base*>::iterator> iter =
  make_type_iterator<Derived>(v.begin(), v.end());

while (iter.base() != iter.end())
{
  (*iter)->OnlyDerivedHasThis();
  ++iter;
}

In order to cooperate with associative containers, containers of
shared_ptr's and so forth, the type_iterator maps the type of the
underlying iterator (and the cast used) like this:

underlying iterator's type_iterator's cast
reference_type reference_type
-----------------------------------------------------------------------------
Base*& Derived*& dynamic_cast<>
shared_ptr<Base>& shared_ptr<Derived>& dynamic_pointer_cast<>
any& Derived*& any_cast<>
pair<T,Base*>& pair<T,Derived*>& dynamic_cast<>
pair<T,shared_ptr<Base> >& pair<T,shared_ptr<Derived> >& dynamic_pointer_cast<>
pair<T,any>& pair<T,Derived*>& any_cast<>

For instance:

type_iterator< Derived, std::map<string,shared_ptr<Base> > > iter;

*iter <= returns type pair<string,shared_ptr<Derived> >&

I'm sure there are things that need changing, (for instance, should
the "any" map to Derived* or just Derived? Should it incorporate the
behavior of indirect_iterator and do an extra dereference? Dunno.)
I'm just wondering if there is interest before I generalize too far
beyond what my client needs.

DISCLAIMER: it's widely believed that the need to iterate like this
(or the need to downcast at all) indicates a lousy inheritance
hierarchy and that in these cases the desire to downcast should be
removed via improving the base classes. I hope I don't provoke any
lectures on the evils of downcasting: this iterator is not intended to
substitute for good class design...

cheers,

troy d. straszheim


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