fork download
  1. #include <iostream>
  2. #include <string>
  3. #include <map>
  4. #include <type_traits>
  5.  
  6. #define DEFINE_BASES(class, ...) \
  7.   static const std::string& GetClassNameStatic() \
  8.   { \
  9.   static std::string className(#class); \
  10.   return className; \
  11.   } \
  12.   \
  13.   const std::string& GetClassName() const \
  14.   { \
  15.   return GetClassNameStatic(); \
  16.   } \
  17.   \
  18.   template <typename _empty> \
  19.   void RegisterAllSubclasses() const \
  20.   { \
  21.   \
  22.   } \
  23.   \
  24.   template <typename _empty, typename T, typename... Args> \
  25.   void RegisterAllSubclasses() const \
  26.   { \
  27.   T::RegisterAllSubclasses(); \
  28.   RegisterAllSubclasses<void, Args...>(); \
  29.   } \
  30.   \
  31.   virtual void RegisterAllSubclasses() const \
  32.   { \
  33.   RegisterSubclass(static_cast<const void*>(this), class::GetClassName());\
  34.   RegisterAllSubclasses<void, __VA_ARGS__>(); \
  35.   }
  36.  
  37. class Object
  38. {
  39. public:
  40. virtual ~Object() { }
  41.  
  42. static std::string& GetClassNameStatic()
  43. {
  44. static std::string className("Object");
  45. return className;
  46. }
  47.  
  48. virtual const std::string& GetClassName() const
  49. {
  50. return GetClassNameStatic();
  51. }
  52.  
  53. void* To(const std::string& className)
  54. {
  55. if (_bases.size() == 0)
  56. {
  57. RegisterAllSubclasses();
  58. }
  59.  
  60. auto result = _bases.find(className);
  61. return (result != _bases.end() ? (*result).second : NULL);
  62. }
  63.  
  64. const void* To(const std::string& className) const
  65. {
  66. if (_bases.size() == 0)
  67. {
  68. RegisterAllSubclasses();
  69. }
  70.  
  71. auto result = _bases.find(className);
  72. return (result != _bases.end() ? (*result).second : NULL);
  73. }
  74.  
  75. protected:
  76. void RegisterSubclass(const void* ptr, const std::string& className) const
  77. {
  78. _bases[className] = const_cast<void*>(ptr);
  79. }
  80.  
  81. virtual void RegisterAllSubclasses() const
  82. {
  83. RegisterSubclass(static_cast<const void*>(this), Object::GetClassName());
  84. }
  85.  
  86. private:
  87. mutable std::map<std::string, void*> _bases;
  88. };
  89.  
  90. ////////////////////////////////////////////////////////////////////////////////
  91.  
  92. template <typename T>
  93. T my_dynamic_cast(Object* ptr)
  94. {
  95. return static_cast<T>(ptr->To(std::remove_pointer<T>::type::GetClassNameStatic()));
  96. }
  97.  
  98. template <typename T>
  99. T my_dynamic_cast(const Object* ptr)
  100. {
  101. return static_cast<T>(ptr->To(std::remove_pointer<T>::type::GetClassNameStatic()));
  102. }
  103.  
  104. ////////////////////////////////////////////////////////////////////////////////
  105.  
  106. class InputStream : virtual public Object
  107. {
  108. public:
  109. DEFINE_BASES(InputStream, Object);
  110. void Read() { }
  111. };
  112.  
  113. class OutputStream : virtual public Object
  114. {
  115. public:
  116. DEFINE_BASES(OutputStream, Object);
  117. void Write() { }
  118. };
  119.  
  120. class IOStream : public InputStream, public OutputStream
  121. {
  122. int _value;
  123.  
  124. public:
  125. DEFINE_BASES(IOStream, InputStream, OutputStream);
  126. IOStream() : _value(0) { }
  127.  
  128. int GetValue() const { return _value; }
  129. void SetValue(int value) { _value = value; }
  130. };
  131.  
  132. int main()
  133. {
  134. const Object* co = new IOStream;
  135. const IOStream* cd = my_dynamic_cast<const IOStream*>(co);
  136.  
  137. Object* o = new IOStream;
  138. IOStream* d = my_dynamic_cast<IOStream*>(o);
  139.  
  140. d->SetValue(42);
  141.  
  142. printf("const: %i, %p, %p\n", cd->GetValue(), co, cd);
  143. printf("non-const: %i, %p, %p\n", d->GetValue(), o, d);
  144.  
  145. delete cd;
  146. delete d;
  147.  
  148. return 0;
  149. }
Success #stdin #stdout 0s 3040KB
stdin
Standard input is empty
stdout
const:     0, 0x8237014, 0x8237008
non-const: 42, 0x823713c, 0x8237130