"Sharad Kala" <no*****************@yahoo.com> wrote in message
news:c0*************@ID-221354.news.uni-berlin.de...
"John Harrison" <jo*************@hotmail.com> wrote in message
news:c0*************@ID-196037.news.uni-berlin.de...
"Grey Plastic" <gr*********@hotmail.com> wrote in message
news:1d**************************@posting.google.c om... I have a program where several classes each have a single static
std::map to keep track of all the instances of that class. For each
of these classes, I want a static lookupByID(int id) method which
returns a pointer to the instance that the id references... e.g...
Item * Item::lookupByID(Uint32 id);
Level * Level::lookupByID(Uint32 id);
Lifeform * Lifeform::lookupByID(Uint32 id);
... etc. Instead of rewriting the same code for each of these
classes, I instead wrote an Indexable class...
template <class Child> class Indexable {
private:
static std::map<Uint32,Child*> mapByID;
static Uint32 _nextID;
Uint32 _id;
public:
static Child * lookupByID(Uint32 id) { return mapByID[id]; }
Indexable() { _id=_nextID++; mapByID[_id]=(Child*)this; }
~Indexable() { mapByID[_id]=NULL; }
Uint32 id() const { return _id; }
};
and made each of my other classes subclass Indexable...
class Item : public Indexable<Item> { ... };
class Level : public Indexable<Level> { ... };
class Lifeform : public Indexable<Lifeform> { ... };
This achieves what I've wanted, but it still seems a bit weird to me.
How would you guys handle this situation?
It's a well known technique. Make a base class aware of a derived class
by passing the derived class as a template parameter to the base class.
Congratulations on discovering it yourself I'd say.
And it's called the "Curiously recurring template pattern (CRTP)".
Also as you have correctly noted that even though the base class depends
on the derived class, it cannot do so in a way that requires the complete
type of derived to be known. That means you can refer to Child*/Child& but not
Child in the base class.
-Sharad
I don't think that's right. How about this?
template <class Rep>
class RCObject
{
friend class RCPtr<Rep>;
public:
RCObject() : _ref(0) {}
RCObject(const RCObject<Rep>&) : _ref(0) {}
RCObject<Rep>& operator=(const RCObject<Rep>&) {}
~RCObject() { assert(_ref == 0); }
Rep* clone() const { return new Rep(*static_cast<const Rep*>(this)); }
private:
size_t _ref;
};
RCObject is a base class for intrusively reference counted objects. It
defines a clone method that calls the derived class copy ctor and therefore
needs to have the complete type.
I think the point is that Rep needs to be known when RCObject is
instantiated not when it is compiled.
john