this is the end()

N

NKOBAYE027

my friends, the end()...

hehehe no...nothing so dire...

I'm at an impasse I think. I've created the MathematicalSet class as
follows - it has 4 lists. An ObjectPool of the actual objects, a static
Universe of countable pointers, a static Null set (unpopulated) and a Set of
countable pointers. Each time I add an object I check the pool to see if it
exists already, if not, I add it to the pool, then I push countable pointers
to the object in the pool onto the Universe and the Set. Now I want users to
be able to access and iterate over the Mathematical set as though it were a
regular STL container. This means that dereferencing a
MathematicalSet::iterator will return a reference to an object of whatever
type the set contains - those stored in the pool. This has all been done to
a point. The next issue comes with iterating over the Set.

MathematicalSet::const_iterator it = begin();
MathematicalSet::const_iterator ick = end();

while(it++ != ick);

Now since I want the iterators to behave as though they're actually pointing
to objects instead of countable pointers to unique objects I've had to
overload a couple of functions for the Set::iterator. Namely the *, ->, ==
and != - these operators return a refererence to a pooled object, a pointer
to a pooled object and booleans. The MathematicalSet::begin() and end()
functions simply return iterators initialised to Set::begin() and end(). So,
the problem comes in when I use != (or any other time, actually) and have to
dereference MathematicalSet::end(). The iterator def'ns are nested within
the MathematicalSet class and I can't access the Set member (compiler says
it must be static, enumeration or type name) for it's 'end' to write code
within the iterator def's so that I can avoid this problem (and, I'm not
sure I can avoid the problem that way even if I could access the Set
member). I'll post the complete code below, but it's fairly extensive. I
need some good suggestions or advice on how to get through this 'end()'
dereferencing issue with the embedded iterator def's. I can't seem to
determine how the compiler does it with it's own code, though I suspect it's
just a pointer comparison. My problem is I want to keep only one copy of
each object in the pool, so I have to do a member comparison using the
object's == rather than just compare addresses. Speak, oh ye gurus, sages,
pundits and code wizards...tell me it can be done using the regular STL
list, or am I going to have to write my list from scratch. I really want to
use STL for the memory management, I'm too much of a beginner to think of
writing a list that manages it's own resources....this is bugging the heck
out me, the wife, the cat (if I kick him once more I think she'll disown
me).... :eek:)

regards,
L.

PS: The code below compiles without error on my MSVC 6.0

// MathSetDriver.cpp
#include "MathematicalSet.hpp"
#include <iostream>

using namespace mathematical_set;

class bob
{
public:

int a;
char b;

bob():a(0),b(0){}

bob(const bob& d)
{
a = d.a;
b = d.b;
}

bob& operator=(const bob& d)
{
if(this != &d)
{
a = d.a;
b = d.b;
}
return *this;
}
bool operator==(const bob& d) const
{
return (a == d.a) ? ( b == d.b) : false;
}
bool operator!=(const bob& d)
{
return !(*this == d);
}
~bob(){}
};


int main()
{

bob b, b1, b2;
b1.a = 1;
b2.a = 2;
b1.b = 1;
b2.b = 2;
MathematicalSet<bob> aSet;

aSet.add(b);
aSet.add(b);
aSet.add(b2);
aSet.add(b1);

MathematicalSet< bob >::iterator ia = aSet.begin();
MathematicalSet< bob >::iterator ib = aSet.begin();
ib++;
ib->a=0;
ib->b=0;

if( ia == ib)
cout << "wheeee\n";

const MathematicalSet< bob > bSet = aSet;

MathematicalSet< bob >::const_iterator ita = aSet.begin();
MathematicalSet< bob >::const_iterator itb = bSet.begin();

bob a = *itb;

if(ita == itb)
cout << "wheeeeeeeeee\n";

// this code crashes...
// MathematicalSet< bob >::iterator i = begin();
// MathematicalSet< bob >::iterator e = end();
// while(i != e) i++;

return 0;
}

// Element.hpp
// File: Element.hpp
// Countable element template for use with the Mathematical set class and
counted pointers.

#pragma once // include this file once
#pragma warning( disable : 4786 ) // disable the "name too long" warning

// hide this creature in its own namespace
namespace mathematical_element
{
// reference counted wrapper for objects
template< typename object >
class Element
{
public:

// all the pointers (must be initialised to 0 in each ctor)
unsigned m_NumberOfPointers;

// the object
object m_TheObject;

// default ctor.
Element< object >():m_NumberOfPointers(0), m_TheObject()
{ /* nothing to do here */ }

// copy ctor
Element< object >(const Element< object >& s) : m_NumberOfPointers(0),
m_TheObject(s.m_TheObject)
{ /* nothing to do here */ }

// elemental ctor
Element< object >(const object& anObject) : m_NumberOfPointers(0),
m_TheObject(anObject)
{ /* nothing to do here */ }

// assignment operator
const Element< object >& operator=(const Element< object >& anElement)
const
{
// avoid self-assignment
if(this != &anElement)
{
// set member values
m_NumberOfPointers = anElement.m_NumberOfPointers;
m_TheObject = anElement.m_TheObject;
}

return *this;
}

// comparison operator
const bool operator==(const Element< object >& anElement) const
{
return m_TheObject == anElement.m_TheObject;
}

// dtor
~Element(){ /* nothing to do here */ }
};
};

// CountedPointer.hpp
// File: CountedPointer.hpp
// A counted pointer template to be used with the countable element
// described in element.hpp.

#pragma once // include this file once

#pragma warning( disable : 4786 ) // disable the "name too long" warning

// hide this creature in its own namespace
namespace counted_pointer
{

template< typename element >
class CountedPointer
{
public:
// private constructor to limit user access
CountedPointer< element >(){}

// can make the pointer public since author is only one using it
element* m_ThePointer;

// overload operator ->
element* operator->()
{
return m_ThePointer;
}

// overload operator ->
const element* operator->() const
{
return m_ThePointer;
}

// operator *
element& operator*()
{ return *m_ThePointer; }

// operator *
const element& operator*() const
{ return *m_ThePointer; }

// explicit ctor
CountedPointer< element >(element* aPointer):m_ThePointer(aPointer)
{ ++m_ThePointer->m_NumberOfPointers; }

// explicit ctor
CountedPointer< element >(element& anElement):m_ThePointer(&anElement)
{ ++m_ThePointer->m_NumberOfPointers; }

// dtor
~CountedPointer< element >()
{ --m_ThePointer->m_NumberOfPointers; }

// copy ctor
CountedPointer< element >(const CountedPointer< element >&
aCountedPointer) : m_ThePointer(aCountedPointer.m_ThePointer)
{ ++m_ThePointer->m_NumberOfPointers; }

// assignment operator
CountedPointer< element >& operator=(const CountedPointer< element >&
aCountedPointer)
{
++aCountedPointer.m_ThePointer->m_NumberOfPointers;

--m_ThePointer->m_NumberOfPointers;

m_ThePointer = aCountedPointer.m_ThePointer;

return *this;
}

// comparison operator
const bool operator==(const CountedPointer< element >& aCountedPointer)
{
if( aCountedPointer.m_ThePointer == m_ThePointer )return true;

return *m_ThePointer == *(aCountedPointer.m_ThePointer);
}

// contrapositive comparison
const bool operator!=(const CountedPointer< element >& aCountedPointer)
{
return !(*this == aCountedPointer);
}

};
};

// MathematicalSet.hpp
#pragma once
#pragma warning( disable : 4786 )

#include <list> // basic list structure
#include <algorithm> // for the find function template, et. al.

#include "Element.hpp" // a countable element wrapper for objects
#include "CountedPointer.hpp" // a counted pointer friend for element

// hide this creature in it's own namespace
namespace mathematical_set
{

// the namespaces the set needs
using namespace std;
using namespace mathematical_element;
using namespace counted_pointer;

// the parameterised def'n of the MathematicalSet
template< typename object >
class MathematicalSet
{
public:

// standard typedefs
typedef MathematicalSet< object > MathSet;
typedef Element< object > MathElement;
typedef CountedPointer< MathElement > ElementPointer;
typedef object value_type;
typedef object& reference;
typedef const object& const_reference;
typedef object* pointer;
typedef const object* const_pointer;

typedef list< MathElement > ObjectPool;
typedef list< ElementPointer > Set;

class iterator;
class const_iterator;

class const_iterator : public Set::const_iterator
{
public:
typedef Set::const_iterator base_iterator;

const_iterator(){}

const_iterator(base_iterator aSetIterator) :
base_iterator(aSetIterator){}

const_reference operator*() const
{
return (*(static_cast<base_iterator>(*this)))->m_TheObject;
}

const_pointer operator->() const
{
return &**this;
}

bool operator==(const const_iterator& aConstIterator) const
{
return (*(static_cast<base_iterator>(*this)))->m_TheObject ==
*aConstIterator;
}

bool operator!=(const const_iterator& aConstIterator) const
{
return !(*this == aConstIterator);
}
};

class iterator : public Set::iterator
{
public:
typedef Set::iterator base_iterator;

iterator(){}

iterator(base_iterator aSetIterator) : base_iterator(aSetIterator){}

reference operator*() const
{
return (*(static_cast<base_iterator>(*this)))->m_TheObject;
}

pointer operator->() const
{
return &**this;
}

bool operator==(const iterator& anIterator) const
{
return (*(static_cast<base_iterator>(*this)))->m_TheObject ==
*anIterator;
}

bool operator!=(const iterator& anIterator) const
{
return !(*this == anIterator);
}
};

iterator begin()
{
return iterator(m_TheSet.begin());
}

const_iterator begin() const
{
return const_iterator(m_TheSet.begin());
}

iterator end()
{
return iterator(m_TheSet.end());
}

const_iterator end() const
{
return const_iterator(m_TheSet.end());
}
private:

friend class iterator;
friend class const_iterator;
static ObjectPool m_ObjectPool;
static MathematicalSet m_TheUniverse;
static MathematicalSet m_TheNullSet;
// the user's set
Set m_TheSet;


protected:
/* no protected members or functions yet */

public:
MathSet() : m_TheSet( list< ElementPointer >() )
{ /* nothing to do here */ }

MathSet(const MathSet& aSet):m_TheSet( aSet.m_TheSet )
{ /* nothing to do here */ }

~MathematicalSet()
{ /* nothing to do here */ }

const MathSet& operator=(const MathSet& aSet)
{
if(*this != aSet)
{
m_TheSet = aSet.m_TheSet;
}
return *this;
}

const bool operator==(const MathSet& aSet)
{ return m_TheSet == aSet.m_TheSet; }


const bool operator<(const MathSet& aSet)
{ return m_TheSet < aSet.m_TheSet; }


void add(object& anObject);
void remove(object& anObject);
};

// externalise the typedefs
template< typename object >
typedef MathematicalSet< object >::MathSet MathSet;

template< typename object >
typedef MathematicalSet< object >::MathElement MathElement;

template< typename object >
typedef MathematicalSet< object >::ElementPointer ElementPointer;

template< typename object >
typedef MathematicalSet< object >::ObjectPool ObjectPool;

template< typename object >
typedef MathematicalSet< object >::Set Set;


// initialise the globals
template< typename object >
MathematicalSet< object > MathematicalSet< object >::m_TheNullSet;

template< typename object >
MathematicalSet< object > MathematicalSet< object >::m_TheUniverse;

template said:
::m_ObjectPool;

template< typename object >
inline void MathematicalSet< object >::add(object& anObject)
{
// create an element and a reference pointing to it
MathElement& anElement = MathElement(anObject);

// find the object in the object pool
ObjectPool::iterator& foundObject = find(m_ObjectPool.begin(),
m_ObjectPool.end(), anObject);

// if the object doesn't already exist in the pool then create one
if( foundObject == m_ObjectPool.end())
{
// add it to the global pool
m_ObjectPool.push_back(anElement);
foundObject = --m_ObjectPool.end();
}

ElementPointer& anElementPointer = ElementPointer(*foundObject);

// update the universal set
m_TheUniverse.m_TheSet.push_back(anElementPointer);

// add the element pointer to the local set
m_TheSet.push_back(anElementPointer);

}
};
 
B

Buster

NKOBAYE027 said:
PS: The code below compiles without error on my MSVC 6.0
[...]

template< typename object >
typedef MathematicalSet< object >::MathSet MathSet;

I don't have MSVC 6.0 to check this out, but I was under the
impression it was a C++ compiler ...

Here's a selective quote from Herb Sutter by way of backup.

Visual Studio .NET (Visual C++ version 7.0) doesn't yet [...]
have typedef templates which are not in the C++98 standard. (As
I'll point out in a second, nobody else has [...], either.)

In context at this address:
http://www.codeproject.com/interview/herbsutter3032002.asp
 
N

NKOBAYE027

I'm not certain I'm following whatever it is you're trying to say, buster.
All I know is that the code compiles and runs without error on my machine
using MS Visual C++ 6.0 - forgive me for leaving the ++ off of the original
compiler desc. I'm not certain if the compiler has any issues or even
touches the typedef you've alluded to - though I expect it must since
several functions are defined to return MathSet references. That being said,
its not my real issue - my issue is that I can't determine how best to
redefine/define the end of the set so that when I use a comparison operator
or any other creature that perchance dereference the thing it doesn't hack
(give up the ghost, throw an exception or otherwise fail to perform in the
desired manner) on me - or to come up with some other scheme to overcome
this difficulty.

If you're being toungue-in-cheek then forgive my lack of humour this
morning - I need more coffee. :eek:) Perhaps if you could put another word or
two in your advice post I'd understand better what you're trying to say.

regards,
L.

Buster said:
NKOBAYE027 said:
PS: The code below compiles without error on my MSVC 6.0
[...]

template< typename object >
typedef MathematicalSet< object >::MathSet MathSet;

I don't have MSVC 6.0 to check this out, but I was under the
impression it was a C++ compiler ...

Here's a selective quote from Herb Sutter by way of backup.

Visual Studio .NET (Visual C++ version 7.0) doesn't yet [...]
have typedef templates which are not in the C++98 standard. (As
I'll point out in a second, nobody else has [...], either.)

In context at this address:
http://www.codeproject.com/interview/herbsutter3032002.asp
 
B

Buster

NKOBAYE027 said:
If you're being toungue-in-cheek then forgive my lack of humour this
morning - I need more coffee. :eek:) Perhaps if you could put another word or
two in your advice post I'd understand better what you're trying to say.

They say discretion is the better part of valour, so I won't be too
explicit. It just seems very strange to me that any C++ compiler should
accept the code you posted, which contains quite a few syntax errors.
Here's a selection.

(1) Implicit typenames, all over the place.
Inside the definition of a template, some names are dependent (on the
template parameters). The compiler doesn't know whether such a name is
a typename (a name for a type) or not, and cannot make sense of the code
without knowing. The rule is that unless a name is marked with the
'typename' keyword the compiler must assume it is a non-typename (a name
for a non-type).

For example, the following is wrong: you have to say "typename
A<T>::type" instead of "A<T>::type".

template <typename T> struct A { typedef T type; }
template <typename T> struct B { A<T>::type member; }

(2) In the class definition for mathematical_set::MathematicalSet you
use the typedef name "MathSet" as the 'name' of the constructors. This
is not allowed. You should use "MathematicalSet" (it is not necessary to
give the template parameters, since there's only one specialization
whose constructor you can declare there).

(3) In several places you ask to convert a MathematicalSet::iterator
into a MathematicalSet::const_iterator, but these are unrelated classes
and no user-defined conversions are in evidence.

(4) The whole template typedef thing. The compiler certainly should be
trying to parse those declarations, since they're not removed by the
preprocessor. They ought to be legal C++ but they're not, yet, and
never have been.

I realise how unhelpful this post has probably been to you. My advice
is, firstly to forget about most of this stuff and come up with a new
design based on shared_ptr (or, if you insist, intrusive_ptr) from
boost, and secondly, [censored for the sake of international relations].
 
N

NKOBAYE027

Buster said:
They say discretion is the better part of valour, so I won't be too
explicit. It just seems very strange to me that any C++ compiler should
accept the code you posted, which contains quite a few syntax errors.

Well why didn't you say that to begin with? Then I would have understood
you weren't trying to be helpful, just glib. I'm not lying, Buster. The code
compiles without error - who am I to argue with my betters? I'm certain that
even the lowliest programmer on the design team of the MS compiler
is better at C++ programming than I am currently.
Here's a selection.

(1) Implicit typenames, all over the place.
Inside the definition of a template, some names are dependent (on the
template parameters). The compiler doesn't know whether such a name is
a typename (a name for a type) or not, and cannot make sense of the code
without knowing. The rule is that unless a name is marked with the
'typename' keyword the compiler must assume it is a non-typename (a name
for a non-type).

For example, the following is wrong: you have to say "typename
A<T>::type" instead of "A<T>::type".

template <typename T> struct A { typedef T type; }
template <typename T> struct B { A<T>::type member; }
I don't really understand this typename deal. Thank you for bringing it
to my attention. I'll check Stroustrup et. al. later for enlightenment.
(2) In the class definition for mathematical_set::MathematicalSet you
use the typedef name "MathSet" as the 'name' of the constructors.
This is not allowed....

By whom? Or how is it in error? I don't doubt your veracity, just would
appreciate further clarification.
You should use "MathematicalSet" (it is not necessary to
give the template parameters, since there's only one specialization
whose constructor you can declare there

Ok. Thanks for the heads up on this. Another trip through Stroustrup
is in order.
(3) In several places you ask to convert a MathematicalSet::iterator
into a MathematicalSet::const_iterator, but these are unrelated classes
and no user-defined conversions are in evidence.
I'd could benefit further from you picking an example of the above since I
seem to be blind to them.
(4) The whole template typedef thing. The compiler certainly should be
trying to parse those declarations, since they're not removed by the
preprocessor. They ought to be legal C++ but they're not, yet, and
never have been.

So the template typedef thing is something I did which you feel
should be allowed but has yet to be (or may never be) implemented
as part of the standard...ok. Thank you for acknowledging my intent
was doomed as paving to hades.
I realise how unhelpful this post has probably been to you. My advice
is, firstly to forget about most of this stuff and come up with a new
design based on shared_ptr (or, if you insist, intrusive_ptr) from
boost, and secondly, [censored for the sake of international relations].

Now, now, Buster - it wasn't at all unhelpful. Just underscores to me
that I still have a lot to learn. I appreciate your candor as much as a
polite man can. I'm truly sorry if I inadvertantly offended your expert
sensibilities - you're clearly a well-read, rounded and experienced
person. I'm not a programmer by university training, so kindly forgive
me my presumptive foray into your realm.

I'll have to look into the shared_ptr (or intrusive_ptr?) you mentioned
and rethink the design based upon whatever the heck they are. I appreciate
your recommendations.

Now, in the future, if you find my efforts put you off so much just don't
read
or reply to them. I'm not certain, but I imagine you're newsreader may
even have a setting to ignore posts from any addresses you would
rather not see.

Clearly you did spend a little time going over the code, so I do owe you
thanks for the consideration, if not the tone of your replies.

best regards,
L.
 
B

Buster

NKOBAYE027 said:
Well why didn't you say that to begin with? Then I would have understood
you weren't trying to be helpful, just glib. I'm not lying, Buster.

Point out where I said you were lying. I'm still not convinced you're
not mistaken, but you seem pretty sure and I have no way to check. I do
know that no compiler I use will touch it.
The code
compiles without error - who am I to argue with my betters? I'm certain that
even the lowliest programmer on the design team of the MS compiler
is better at C++ programming than I am currently.

Which is why they ought to be embarassed about MSVC6. By all accounts,
versions from 7.1 onward are much closer to the mark.
By whom? Or how is it in error? I don't doubt your veracity, just would
appreciate further clarification.

ISO/IEC 14882:1998(E), 12.1.3.
"A /typedef-name/ that names a class is a /class-name/ (7.1.3);
however, a /typedef-name/ that names a class shall not be used as
the /identifier/ in the declarator for a constructor declaration."
Ok. Thanks for the heads up on this. Another trip through Stroustrup
is in order.


I'd could benefit further from you picking an example of the above since I
seem to be blind to them.

It seems there's just one, I think, about 16 lines down from
"int main()", with the line
"MathematicalSet< bob >::const_iterator ita = aSet.begin();".
Possibly a typo. (Did you mean bSet?)

There is another error I was confusing with (3) there.

(3a) In three places, your code binds a temporary to a non-const
reference. Again, this is forbidden by the standard. Two of these places
occur together, at the top of the definition of MathematicalSet::add.

// create an element and a reference pointing to it
MathElement& anElement = MathElement(anObject);

// find the object in the object pool
ObjectPool::iterator& foundObject = find(m_ObjectPool.begin(),
m_ObjectPool.end(), anObject);

In this case the solution is simple.

// create a named element.
MathElement anElement (anObject);
// find the object in the object pool
ObjectPool::iterator foundObject = find ( .... );
So the template typedef thing is something I did which you feel
should be allowed but has yet to be (or may never be) implemented
as part of the standard...ok. Thank you for acknowledging my intent
was doomed as paving to hades.

That's right. No problem.
I realise how unhelpful this post has probably been to you. My advice
is, firstly to forget about most of this stuff and come up with a new
design based on shared_ptr (or, if you insist, intrusive_ptr) from
boost, and secondly, [censored for the sake of international relations].


Now, now, Buster - it wasn't at all unhelpful. Just underscores to me
that I still have a lot to learn. I appreciate your candor as much as a
polite man can. I'm truly sorry if I inadvertantly offended your expert
sensibilities - you're clearly a well-read, rounded and experienced
person. I'm not a programmer by university training, so kindly forgive
me my presumptive foray into your realm.

No presumption. You're a mathematician, right? You'll be fine but you
have to do these things in an incremental fashion: write a small
function whose task is well defined, test it, and when you know it's
working correctly, set it in stone.
I'll have to look into the shared_ptr (or intrusive_ptr?) you mentioned
and rethink the design based upon whatever the heck they are. I appreciate
your recommendations.

It's the same principle. Those components are well-tested, and when
you're debugging code that uses them you can be reasonably confident
you don't have to debug the boost code as well as your own. With the
complexity of the code reduced it is much easier to understand the
underlying design.

If you want to create a generic reference-counted smart pointer, fine,
but don't do it at the same time as your MathematicalSet class.
Now, in the future, if you find my efforts put you off so much just don't
read or reply to them.

That would be up to me, now, wouldn't it.
I'm not certain, but I imagine you're newsreader may
even have a setting to ignore posts from any addresses you would
rather not see.

Clearly you did spend a little time going over the code, so I do owe you
thanks for the consideration, if not the tone of your replies.

You're welcome.
 
B

Buster

Buster said:
In this case the solution is simple.

// create a named element.
MathElement anElement (anObject);
// find the object in the object pool
ObjectPool::iterator foundObject = find ( .... );

Ouch. I mean "typename ObjectPool::iterator". Sorry!
 
N

NKOBAYE027

*gigglefit*

Thanks again, Buster. And no, not a mathematician, but theoretical
physicist. So you're very close...Lord help me if a real mathematician gets
hold of the other stuff I have written towards this library. I'm hoping to
take it into the realm of group theory just for my own pedagogical reasons.
a group being (loosely) defined as a mapping of set onto a set via a binary
relation. I'm certain that there are already libraries to this effect
written by the companies who develop math software - e.g. maple, matlab,
etc. - so it's mostly a pedagogical exercise for me...the things you do when
you're unemployed and not living in Acapulco. Thanks again for your aid.
I'll probably play with the current code a little more to try and ensure I
have this typename thing down pat before I begin implementing the smart
pointers. I don't have the boost libraries which seem to be quite popular
among the denizens of this group, so I should become familiar with their
usage, I'd guess. And I'd STILL like to hear any ideas on how to get around
the end() iterator impasse I mentioned to begin with....

regards,
L.
 
B

Buster

I think I must leave a nasty smell on any posts I respond to that
discourages other humans from approaching.

Anyway. The problem you want to solve is to do with the == and !=
operators defined for your iterator class. They should be comparing
positions in the set, not comparing the pointed-to counted pointers.

Good luck.
 
N

NKOBAYE027

Yes, Buster, I agree to an extent. Actually, I said, in my first post which
has gotten lost in the morass - better morass than nothing at all though -
that I am certain it has something to do with the way pointers are being
compared. I'm not comparing the pointed to counted pointers, by the way, but
the actual objects pointed to by the pointed to counted pointers. :eek:)

Anyway, never mind - I've resigned myself to redefining the classes (using
the auto_ptr or whatever other thingie you described) and defining my own
iterator class from scratch instead of inheriting from the typename
MathematicalSet::Set::(const_)iterator as I had previously. That way I
should be able to ensure that end() and begin() behave as I want them to.

And as to the nasty smell - nahhhh you were the first and the post was up
for a day b4 I got anything. Afterward...I suspect the locals were simply
enjoying the repartee and expecting fisticuffs.

best regards,
L.
 
B

Buster

NKOBAYE027 said:
Yes, Buster, I agree to an extent. Actually, I said, in my first post which
has gotten lost in the morass - better morass than nothing at all though -
that I am certain it has something to do with the way pointers are being
compared. I'm not comparing the pointed to counted pointers, by the way, but
the actual objects pointed to by the pointed to counted pointers. :eek:)

I'm pretty sure you should just compare the iterators. What do you
think? I've posted an incomplete (but compilable) example below. The
definitions for operator -> are by way of a challenge: do you know why
they will work correctly?

#include <list>

template <typename object>
class MathematicalSet
{
public:
// ...
class iterator;
};

template <typename object>
class MathematicalSet <object>::iterator
{
private:
typedef
typename std::list <object>::iterator
base_iterator_type;

base_iterator_type m_base_iterator;

public:
// ... (loads more forwarding functions and typedefs)

bool operator == (const iterator & other) const
{
return this->m_base_iterator == other->m_base_iterator;
}

bool operator != (const iterator & other) const
{
return this->m_base_iterator != other->m_base_iterator;
}

base_iterator_type & operator -> ()
{
return m_base_iterator;
}

const base_iterator_type & operator -> () const
{
return m_base_iterator;
}
};
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,968
Messages
2,570,149
Members
46,695
Latest member
StanleyDri

Latest Threads

Top