#include <iostream>
#include <type_traits>

#define CREATE_CLALLER( cls, method ) \
    struct method { \
        void operator()( cls* obj ) { \
            obj->method(); \
        } \
    }

// classes
struct Base {
    void BaseMethod1(){ std::cout << __PRETTY_FUNCTION__ << std::endl; }
    void BaseMethod2(){ std::cout << __PRETTY_FUNCTION__ << std::endl; }
    void BaseMethod3(){ std::cout << __PRETTY_FUNCTION__ << std::endl; }
};
CREATE_CLALLER( Base, BaseMethod1 );
CREATE_CLALLER( Base, BaseMethod2 );
CREATE_CLALLER( Base, BaseMethod3 );

struct A final : Base {
     void A_Specific_Operations(){ std::cout << __PRETTY_FUNCTION__ << std::endl; }
     void doSomething();
};
CREATE_CLALLER( A, A_Specific_Operations );

struct B final : Base {
     void B_Specific_Operations(){ std::cout << __PRETTY_FUNCTION__ << std::endl; }
     void doSomething();
};
CREATE_CLALLER( B, B_Specific_Operations );

/// utilities
struct a_tag { };
struct b_tag { };

template < typename... Strategy > 
struct strategy_list { };

template < typename Target, typename First, typename... Last >
void execute_strategies( Target* target, strategy_list<First,Last...> ) {
    First()( target );
    execute_strategies( target, strategy_list<Last...>() );
}

template < typename Target >
void execute_strategies( Target* target, strategy_list<> ) { }

template < typename Tag >
using make_steps = strategy_list<
    BaseMethod1
    , typename std::conditional< 
        !std::is_same<Tag,b_tag>::value
        , BaseMethod2
        , B_Specific_Operations
      >::type
    , typename std::conditional< 
        !std::is_same<Tag,a_tag>::value
        , BaseMethod2
        , A_Specific_Operations
      >::type
    , BaseMethod3
>;

// implement codes
void A::doSomething() {
    execute_strategies( this, make_steps<a_tag>() );
}

void B::doSomething() {
    execute_strategies( this, make_steps<b_tag>() );
}

int main() {
    
    using namespace std;
    
    A().doSomething();
    cout << endl;
    B().doSomething();
}