fork download
  1. #include <iostream>
  2. #include <type_traits>
  3.  
  4. #define CREATE_CLALLER( cls, method ) \
  5.   struct method { \
  6.   void operator()( cls* obj ) { \
  7.   obj->method(); \
  8.   } \
  9.   }
  10.  
  11. // classes
  12. struct Base {
  13. void BaseMethod1(){ std::cout << __PRETTY_FUNCTION__ << std::endl; }
  14. void BaseMethod2(){ std::cout << __PRETTY_FUNCTION__ << std::endl; }
  15. void BaseMethod3(){ std::cout << __PRETTY_FUNCTION__ << std::endl; }
  16. };
  17. CREATE_CLALLER( Base, BaseMethod1 );
  18. CREATE_CLALLER( Base, BaseMethod2 );
  19. CREATE_CLALLER( Base, BaseMethod3 );
  20.  
  21. struct A final : Base {
  22. void A_Specific_Operations(){ std::cout << __PRETTY_FUNCTION__ << std::endl; }
  23. void doSomething();
  24. };
  25. CREATE_CLALLER( A, A_Specific_Operations );
  26.  
  27. struct B final : Base {
  28. void B_Specific_Operations(){ std::cout << __PRETTY_FUNCTION__ << std::endl; }
  29. void doSomething();
  30. };
  31. CREATE_CLALLER( B, B_Specific_Operations );
  32.  
  33. /// utilities
  34. struct a_tag { };
  35. struct b_tag { };
  36.  
  37. template < typename... Strategy >
  38. struct strategy_list { };
  39.  
  40. template < typename Target, typename First, typename... Last >
  41. void execute_strategies( Target* target, strategy_list<First,Last...> ) {
  42. First()( target );
  43. execute_strategies( target, strategy_list<Last...>() );
  44. }
  45.  
  46. template < typename Target >
  47. void execute_strategies( Target* target, strategy_list<> ) { }
  48.  
  49. template < typename Tag >
  50. using make_steps = strategy_list<
  51. BaseMethod1
  52. , typename std::conditional<
  53. !std::is_same<Tag,b_tag>::value
  54. , BaseMethod2
  55. , B_Specific_Operations
  56. >::type
  57. , typename std::conditional<
  58. !std::is_same<Tag,a_tag>::value
  59. , BaseMethod2
  60. , A_Specific_Operations
  61. >::type
  62. , BaseMethod3
  63. >;
  64.  
  65. // implement codes
  66. void A::doSomething() {
  67. execute_strategies( this, make_steps<a_tag>() );
  68. }
  69.  
  70. void B::doSomething() {
  71. execute_strategies( this, make_steps<b_tag>() );
  72. }
  73.  
  74. int main() {
  75.  
  76. using namespace std;
  77.  
  78. A().doSomething();
  79. cout << endl;
  80. B().doSomething();
  81. }
Success #stdin #stdout 0s 2852KB
stdin
Standard input is empty
stdout
void Base::BaseMethod1()
void Base::BaseMethod2()
void A::A_Specific_Operations()
void Base::BaseMethod3()

void Base::BaseMethod1()
void B::B_Specific_Operations()
void Base::BaseMethod2()
void Base::BaseMethod3()