If you don't want to use RTTI at all (including dynamic_cast
), you could simulate its behaviour like Qt does it with qgraphicsitem_cast
Outline:
class Base {
public:
enum { Type = 0 };
virtual int type() { return Type; }
};
class Derived : public Base {
public:
enum { Type = 1 };
int type() { return Type; }
};
template<typename T>
inline T myobject_cast(Base *b) {
if (b) {
// Requires C++11
if (int(std::remove_pointer<T>::type::Type) == b->type()) {
return static_cast<T>(b);
}
/* Pre C++11 (might be UB, but works on many compilers, OpenSource and Commercial)
if (int(static_cast<T>(0)->Type) == b->type()) {
return static_cast<T>(b);
}
*/
}
return NULL;
}
// use:
Base *b = new Base;
Base *d = new Derived;
Derived *o1 = myobject_cast<Derived*> (b); // NULL
Derived *o2 = myobject_cast<Derived*> (d); // d
Each class would require a unique Type
member for this to work.
Be aware that this will not work with "intermediate" classes in the hierarchy. Only the actual, most derived type will can be cast to (e.g. a DerivedDerived
cannot be cast to a Derived
, or Base
for that matter).
You might also find an overload for const handy:
template<typename T> inline T myobject_cast(const Base *b)
{ return (b && int(static_cast<T>(0)->Type) == b->type()) ? static_cast<T>(p) : 0; }
const Base *cb = new Derived;
const Derived *co = myobject_cast<const Derived *>(cb);