#include <iostream>
#include <string>
#include <map>
#include <type_traits>
#define DEFINE_BASES(class, ...) \
static const std::string& GetClassNameStatic() \
{ \
static std::string className(#class); \
return className; \
} \
\
const std::string& GetClassName() const \
{ \
return GetClassNameStatic(); \
} \
\
template <typename _empty> \
void RegisterAllSubclasses() const \
{ \
\
} \
\
template <typename _empty, typename T, typename... Args> \
void RegisterAllSubclasses() const \
{ \
T::RegisterAllSubclasses(); \
RegisterAllSubclasses<void, Args...>(); \
} \
\
virtual void RegisterAllSubclasses() const \
{ \
RegisterSubclass(static_cast<const void*>(this), class::GetClassName());\
RegisterAllSubclasses<void, __VA_ARGS__>(); \
}
class Object
{
public:
virtual ~Object() { }
static std::string& GetClassNameStatic()
{
static std::string className("Object");
return className;
}
virtual const std::string& GetClassName() const
{
return GetClassNameStatic();
}
void* To(const std::string& className)
{
if (_bases.size() == 0)
{
RegisterAllSubclasses();
}
auto result = _bases.find(className);
return (result != _bases.end() ? (*result).second : NULL);
}
const void* To(const std::string& className) const
{
if (_bases.size() == 0)
{
RegisterAllSubclasses();
}
auto result = _bases.find(className);
return (result != _bases.end() ? (*result).second : NULL);
}
protected:
void RegisterSubclass(const void* ptr, const std::string& className) const
{
_bases[className] = const_cast<void*>(ptr);
}
virtual void RegisterAllSubclasses() const
{
RegisterSubclass(static_cast<const void*>(this), Object::GetClassName());
}
private:
mutable std::map<std::string, void*> _bases;
};
////////////////////////////////////////////////////////////////////////////////
template <typename T>
T my_dynamic_cast(Object* ptr)
{
return static_cast<T>(ptr->To(std::remove_pointer<T>::type::GetClassNameStatic()));
}
template <typename T>
T my_dynamic_cast(const Object* ptr)
{
return static_cast<T>(ptr->To(std::remove_pointer<T>::type::GetClassNameStatic()));
}
////////////////////////////////////////////////////////////////////////////////
class InputStream : virtual public Object
{
public:
DEFINE_BASES(InputStream, Object);
void Read() { }
};
class OutputStream : virtual public Object
{
public:
DEFINE_BASES(OutputStream, Object);
void Write() { }
};
class IOStream : public InputStream, public OutputStream
{
int _value;
public:
DEFINE_BASES(IOStream, InputStream, OutputStream);
IOStream() : _value(0) { }
int GetValue() const { return _value; }
void SetValue(int value) { _value = value; }
};
int main()
{
const Object* co = new IOStream;
const IOStream* cd = my_dynamic_cast<const IOStream*>(co);
Object* o = new IOStream;
IOStream* d = my_dynamic_cast<IOStream*>(o);
d->SetValue(42);
printf("const: %i, %p, %p\n", cd->GetValue(), co, cd);
printf("non-const: %i, %p, %p\n", d->GetValue(), o, d);
delete cd;
delete d;
return 0;
}