Thanks for your help, folks. I appreciate it.
Howard wrote:
What's the "end node"? When an iterator is equal to mycontainer.end(), it's
pointing one PAST the last valid item in mycontainer. And without
mycontainer, there's not way to test for equality with mycontainer.end(),
obviously.
Yeah, with "end node" I mean the one that equals the node of
mycontainer.end(). Unfortunately (or fortunately) it's not legal to
dereference the mycontainer.end() iterator.
Iterators are not generic. How would you define a function that took just
any old iterator?
Well, as long as I presume that any iterator has these operators:
operator*
operator->
operator++
operator--
everything should be fine. I don't make use of operatoror operator<,
as not every iterator type supports them.
But in this case (the totally_isolated() function case), I only make
use of the *-operator. I don't even need to know the underlying type
the iterator operates on (see below.)
You can't access what an iterator points to without knowing the iterator
type in the first place. What code do you have that lets you do that?
In fact, the totally_isolated() function is a member of a class to
which the iterator type is actually known. Here is the class I am
talking about
:
http://groups.google.com/group/comp....browse_thread/
thread/d908a39b187d60e6/42558e69440c1da1?lnk=gst&rnum=1#42558e69440c1da1
I'll try to explain the current problem, so you don't have to waste
your time examining the crappy code.
These Abstract Iterator classes wrap iterators. Once an Abstract
Iterator has "swallowed" an iterator, no one but itself knows what the
type of the wrapped iterator is (e.g. vector<...>::iterator,
list<...>::iterator, ...).
When it comes to comparing two Abstract Iterators, I can only pass an
abstract iterator in the shape of a base pointer to another abstract
iterator, which then tests (via dynamic_cast) if the passed base
pointer is pointing to an abstract iterator with the same underlying
iterator type. Then they can be compared. But I don't like the use of
dynamic cast, because once the wrong abstract iterator is passed, an
exception is thrown.
So I have the abstract iterators return addresses of the objects their
wrapped iterators are pointing to so I can compare these addresses. The
functions that return the generic (void*) addresses are called
get_value_address(). It worked, until one of the wrapped iterators
happened to point to an end node. Here's the implementation of that
function that returns the generic address:
void const* get_value_address() const
{
return &*it;
}
That's why I need to dereference the iterator (actually, 'it' is a
member of the class rather than a parameter as shown in the
totally_isolated() function. Still, the whole Abstract Iterator concept
is ignorant about the iterator that is hold as a member. But it would
lose a lot of its elegance if I forced the user of the Abstract
Iterator to pass a reference to the container to an Abstract Iterator
object as well.
Anyway: I need to return the address of the object the 'it' iterator is
pointing to to compare two Abstract Iterators. (I am aware of other
ways to compare two Abstract Iterators, but they make use of
dynamic_cast, which is not so elegant. But I have to, if there's no way
to determine if 'it' is pointing to mycontainer.end().)
by and large, comparison is done this way:
// Instead of comparing two iterators the usual way like:
....
std::vector<int>::iterator i1 = vec.begin(), i2 = vec.begin();
i1 == i2;
// I have the iterators compared like this:
(&(*i1)) == (&(*i2))
But if either of these iterators happens to point to the end node, the
prorgam crashes.
I wished the C++ language stored "real" type information rather than
pseudo type_infos, which only contain lousy strings. So I could write
typeinfo iterator_type = typeid(std::vector<int>::iterator);
std::vector<int>::iterator& iter =
static_cast<iterator_type&>(disguised);
There would be no dynamic_cast whatsoever.