I've got a class hierarchy as this one:
class A { } //
class AA : A { } // A
class AAA : AA { } // / \
class AAB : AA { } // AA AB
class AB : A { } // / \ / \
class ABA : AB { } // AAA AAB ABA ABB
class ABB : AB { } //
I'd like to emulate RTTI (without using it, of course) for this ierarchy, in a way that, given a pointer/reference to A
, I can find out its actual type (similarly to what typeid
does), as an integer identifying the class.
Moreover I'd like that the set of integers identifying my types is contiguous and goes from 0 to N-1 (from 0 to 6 in my example):
class A { virtual int t(){return 0;} } //
class AA : A { virtual int t(){return 1;} } // A(0)
class AAA : AA { virtual int t(){return 2;} } // / \
class AAB : AA { virtual int t(){return 3;} } // AA(1) AB(4)
class AB : A { virtual int t(){return 4;} } // / \ / \
class ABA : AB { virtual int t(){return 5;} } // AAA(2) AAB(3) ABA(5) ABB(6)
class ABB : AB { virtual int t(){return 6;} } //
(the order doesn't really matter: A::t
could return 3 and AAB::t
0, for example.
Is it possible to let the compiler assign the indexes to my classes?
I think that CRTP could help me; something like:
class X : A, AssignFirstAvailableIndex< X > { }
but I'm not good enough with templates. How could I implement that AssignFirstAvailableIndex
template class?
(of course the compiler can see all of the classes at compile time)
There is a standard method to implement what you need. Standard locale facets use it to identify themselves. Consider examining standard header "locale".
class Base {
public:
// Being constructed contains a new unique identifier
class Id {
// An id factory returns a sequence of nonnegative ints
static int allocate() {
static int total = 0;
return total++;
}
int _local;
public:
Id(): _local(allocate()) {}
int get() const {return _local;}
};
//Child classes should make this function return an id generated by Base::Id constructed as static member.
virtual int id() const = 0;
};
class Child1{
public:
static const Base::Id _id;
virtual int id() { return _id.get(); }
};
class Child2 {
public:
static const Base::Id _id;
virtual int id() { return _id.get(); }
};
class Child3 {
public:
static const Base::Id _id;
virtual int id() { return _id.get(); }
};
Static members might be initialized in implementation files or be templated to allow instantiation directly from headers or be refactored for lazy initialization.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With