fork download
  1. #include <iostream>
  2.  
  3. struct Base
  4. {
  5. public:
  6. virtual ~Base() {};
  7. };
  8.  
  9. struct Derived1 : Base
  10. {
  11. int x = 42;
  12. };
  13.  
  14. struct Derived2 : Base
  15. {
  16. double z = 33.33;
  17. };
  18.  
  19. struct Mixed : Derived1, Derived2
  20. {
  21. };
  22.  
  23. struct Unrelated
  24. {
  25. virtual ~Unrelated(){}
  26. };
  27.  
  28. struct TypeTag
  29. {
  30. virtual ~TypeTag(){}
  31. };
  32.  
  33. template <typename T>
  34. struct TypeTagSpec : virtual TypeTag
  35. {
  36. };
  37.  
  38. template <>
  39. struct TypeTagSpec<Unrelated> : virtual TypeTag
  40. {
  41. };
  42.  
  43. template <>
  44. struct TypeTagSpec<Base> : virtual TypeTag
  45. {
  46. };
  47.  
  48. template <>
  49. struct TypeTagSpec<Derived1> : virtual TypeTagSpec<Base>
  50. {
  51. };
  52.  
  53. template <>
  54. struct TypeTagSpec<Mixed> : virtual TypeTagSpec<Derived1>, virtual TypeTagSpec<Derived2>
  55. {
  56. };
  57.  
  58. // The "solution"
  59. template <typename T>
  60. T *isRelated(void *obj, void *tag)
  61. {
  62. const TypeTag *typetag = reinterpret_cast<TypeTag*>(tag);
  63. if(dynamic_cast<const TypeTagSpec<T>*>(typetag))
  64. return reinterpret_cast<T*>(obj);
  65. return nullptr;
  66. }
  67.  
  68. int main()
  69. {
  70. Mixed *mixed = new Mixed();
  71. TypeTag *typetag = new TypeTagSpec<Mixed>();
  72.  
  73. // Test begins here
  74. void *obj = mixed;
  75. void *tag = typetag;
  76.  
  77. Derived1* d1 = isRelated<Derived1>(obj, tag);
  78. Derived2* d2 = isRelated<Derived2>(obj, tag);
  79.  
  80. if (d1) std::cout << d1->x << "\n";
  81. if (d2) std::cout << d2->z << "\n";
  82.  
  83. delete mixed;
  84. delete typetag;
  85. }
Success #stdin #stdout 0s 15240KB
stdin
Standard input is empty
stdout
42
2.07508e-322