fork download
  1. #include <typeinfo>
  2. #include <typeindex>
  3. #include <unordered_map>
  4.  
  5. struct Command { virtual ~Command() {}; };
  6.  
  7. struct SpecificCommandA: Command {};
  8. struct SpecificCommandB: Command {};
  9. struct SpecificCommandC: Command {};
  10.  
  11.  
  12. struct Base {
  13. virtual ~Base() {};
  14.  
  15. virtual void modify_command(Command &c, std::type_index); // default
  16.  
  17. void modify_command(Command &c) {
  18. modify_command(c, std::type_index(typeid(c)));
  19. }
  20. };
  21.  
  22. template<typename Der, typename SpecC> struct Modifier {
  23. static void execute(Der &d, Command &c) {
  24. d.modify_command(static_cast<SpecC &>(c));
  25. }
  26. };
  27.  
  28. struct Derived: Base {
  29. using Base::modify_command;
  30. virtual void modify_command(SpecificCommandB &); // overload & override
  31.  
  32. void modify_command(Command &c, std::type_index ti) override {
  33. using callable = void (*)(Derived &, Command &);
  34. const static std::unordered_map<std::type_index, callable> derived_map =
  35. {
  36. { std::type_index(typeid(SpecificCommandB)), Modifier<Derived, SpecificCommandB>::execute }
  37. };
  38. auto find_result = derived_map.find(ti);
  39. if(derived_map.end() == find_result) { Base::modify_command(c, ti); }
  40. else { (*find_result->second)(*this, c); }
  41. }
  42. };
  43.  
  44. struct DerivedOfDerived: Derived {
  45. using Derived::modify_command;
  46. virtual void modify_command(SpecificCommandB &); // overload & override
  47. virtual void modify_command(SpecificCommandC &);
  48.  
  49. void modify_command(Command &c, std::type_index ti) override {
  50. using callable = void (*)(DerivedOfDerived &, Command &);
  51. const static std::unordered_map<std::type_index, callable> derived_map =
  52. {
  53. { std::type_index(typeid(SpecificCommandB)), Modifier<DerivedOfDerived, SpecificCommandB>::execute },
  54. { std::type_index(typeid(SpecificCommandC)), Modifier<DerivedOfDerived, SpecificCommandC>::execute }
  55. };
  56. auto find_result = derived_map.find(ti);
  57. if(derived_map.end() == find_result) { Derived::modify_command(c, ti); }
  58. else { (*find_result->second)(*this, c); }
  59. }
  60. };
  61.  
  62. #include <iostream>
  63.  
  64. void Base::modify_command(Command &, std::type_index) { std::cout << "Default" << std::endl; }
  65.  
  66. void Derived::modify_command(SpecificCommandB &) { std::cout << "B in Derived" << std::endl; }
  67. void DerivedOfDerived::modify_command(SpecificCommandB &) { std::cout << "B in DerivedOfDerived" << std::endl; }
  68. void DerivedOfDerived::modify_command(SpecificCommandC &) { std::cout << "C" << std::endl; }
  69.  
  70.  
  71.  
  72. int main(int argc, const char *argv[]) {
  73. SpecificCommandA a;
  74. SpecificCommandB b;
  75. Derived d;
  76. d.modify_command(a);
  77. d.modify_command(static_cast<Command &>(b));
  78. d.modify_command(b);
  79. DerivedOfDerived dod;
  80. SpecificCommandC c;
  81. dod.modify_command(a);
  82. dod.modify_command(b);
  83. dod.modify_command(c);
  84. return 0;
  85. }
Success #stdin #stdout 0s 3420KB
stdin
Standard input is empty
stdout
Default
B in Derived
B in Derived
Default
B in DerivedOfDerived
C