Name: Anonymous 2012-05-17 10:44
discuss
#include <vector>
#include <cstdio>
#include <cstring>
#include <cassert>
class typeinfo_t;
typedef std::vector<typeinfo_t*> typelist_t;
typelist_t* types = NULL;
void rtti_init();
size_t rtti_init_r(typeinfo_t* p, size_t n);
void rtti_uninit();
typeinfo_t* rtti_find(const char* classname);
class typeinfo_t
{
public:
typeinfo_t(const char* classname_, const char* supername_)
: classname(classname_), supername(supername_), begin(0), end(0)
{
bool inserted = false;
if(!types)
types = new typelist_t;
super = rtti_find(supername);
if(super)
super->subs.push_back(this);
for(auto it = types->begin(); it != types->end(); ++it)
{
int c = strcmp(classname, (*it)->classname);
assert(c);
if((*it)->super == NULL && strcmp((*it)->supername, classname) == 0)
{
(*it)->super = this;
subs.push_back(*it);
}
if(c < 0)
{
it = types->insert(it, this) + 1;
inserted = true;
}
}
if(!inserted)
types->push_back(this);
}
typeinfo_t* get_super() const
{
return super;
}
bool is_type(const typeinfo_t& t) const
{
if(begin >= t.begin && begin <= t.end)
return true;
return false;
}
const char* classname;
const char* supername;
friend size_t rtti_init_r(typeinfo_t*, size_t);
private:
size_t begin, end;
typeinfo_t* super;
typelist_t subs;
};
size_t rtti_init_r(typeinfo_t* p, size_t n)
{
p->begin = n;
p->end += n;
for(auto s = p->get_super(); s; s = s->get_super())
s->end++;
for(auto it = p->subs.begin(); it != p->subs.end(); ++it)
n = rtti_init_r(*it, n + 1);
return n;
}
void rtti_init()
{
assert(types->size());
typeinfo_t* p = types->at(0);
while(p->get_super())
p = p->get_super();
rtti_init_r(p, 0);
}
void rtti_uninit()
{
delete types;
}
typeinfo_t* rtti_find(const char* classname)
{
size_t i = 0, j = types->size();
while(i < j)
{
size_t k = i + ((j - i) / 2);
int c = strcmp(classname, types->at(k)->classname);
if(c < 0)
j = k;
else if(c > 0)
i = k + 1;
else
return types->at(k);
}
return NULL;
}
#define DECLARE_CLASS \
static typeinfo_t type; \
virtual typeinfo_t* get_type() const;
#define DEFINE_CLASS(classname, supername) \
typeinfo_t classname::type(#classname, #supername); \
typeinfo_t* classname::get_type() const { return &classname::type; }
class base_class
{
public:
DECLARE_CLASS
bool is_type(const typeinfo_t& t) const
{
return this->get_type()->is_type(t);
}
const char* get_name() const
{
return this->get_type()->classname;
}
};
DEFINE_CLASS(base_class, none)
class A : public base_class
{
public:
DECLARE_CLASS
};
DEFINE_CLASS(A, base_class)
class B : public base_class
{
public:
DECLARE_CLASS
};
DEFINE_CLASS(B, base_class)
class C : public A
{
public:
DECLARE_CLASS
};
DEFINE_CLASS(C, A)
class D : public B
{
public:
DECLARE_CLASS
};
DEFINE_CLASS(D, B)
class E : public C
{
public:
DECLARE_CLASS
};
DEFINE_CLASS(E, C)
class F : public C
{
public:
DECLARE_CLASS
};
DEFINE_CLASS(F, C)
class G : public F
{
public:
DECLARE_CLASS
};
DEFINE_CLASS(G, F)
const char* boolstr(bool b)
{
return b ? "true" : "false";
}
void print_test(base_class& c)
{
printf("Testing class %s\n", c.get_name());
printf("is_type(A) : %s\n", boolstr(c.is_type(A::type)));
printf("is_type(B) : %s\n", boolstr(c.is_type(B::type)));
printf("is_type(C) : %s\n", boolstr(c.is_type(C::type)));
printf("is_type(D) : %s\n", boolstr(c.is_type(D::type)));
printf("is_type(E) : %s\n", boolstr(c.is_type(E::type)));
printf("is_type(F) : %s\n", boolstr(c.is_type(F::type)));
printf("is_type(G) : %s\n\n", boolstr(c.is_type(G::type)));
}
int main()
{
rtti_init();
print_test(A());
print_test(B());
print_test(C());
print_test(D());
print_test(E());
print_test(F());
print_test(G());
rtti_uninit();
}