#include <iostream>
#include <string>
#include <tuple>
#include <vector>

#define USE_MEDIATOR

using namespace std;

template<class T>
void show(T tup)
{
    cout << "-----------------" << endl;
    cout << get<0>(tup) << endl;
    cout << get<1>(tup) << endl;
    cout << get<2>(tup) << endl;
    cout << "-----------------" << endl;
}

template <class T>
class NotifyParam
{
public:
    NotifyParam(T body)
        :body(body)
    {}
    T body;
};

#ifdef USE_MEDIATOR

class MediatorBase
{
public:
    virtual void doCommand(int which, void* notifyParam) = 0;
};

template<class T1, class T2>
class MediatorA : public MediatorBase
{
public:
    virtual void doCommand(int which, void* notifyParam)
    {
        cout << "-----------------" << endl;
        cout << "----MediatorA----" << endl;
        switch (which)
        {
        case 1:
        	show(*static_cast<T1*>(notifyParam));
        	break;
        case 2:
        	show(*static_cast<T2*>(notifyParam));
        	break;
        }
    }
};

template<class T1, class T2>
class MediatorB : public MediatorBase
{
public:
    virtual void doCommand(int which, void* notifyParam)
    {
        cout << "-----------------" << endl;
        cout << "----MediatorB----" << endl;
        switch (which)
        {
        case 1:
        	show(*static_cast<T1*>(notifyParam));
        	break;
        case 2:
        	show(*static_cast<T2*>(notifyParam));
        	break;
        }
    }
};

#endif

int main ()
{
    auto tup1 = make_tuple("A", 1, 0.3);
    NotifyParam<decltype(tup1)> pp1(tup1);
    show(pp1.body);

    auto tup2 = make_tuple("B", "cc", 1);
    NotifyParam<decltype(tup2)> pp2(tup2);
    show(pp2.body);

 #ifdef USE_MEDIATOR

    vector<MediatorBase*> vt = {new MediatorA<decltype(tup1), decltype(tup2)>, new MediatorB<decltype(tup1), decltype(tup2)>};

    for(auto it : vt)
    {
        it->doCommand(1, &pp1.body);
        it->doCommand(2, &pp2.body);
    }

#endif

    return 0;
}
