// 注意  以下內容通通都省略了需要delete的問題
 
#include <iostream>
#include <vector>


// 這可以不用看 
class _Event{
public:
    template<typename T, typename TMemFun>
    void Attach(T* obj, TMemFun mf) {_handler = new _eventHandler<T, TMemFun>(obj, mf);}
    void _RaiseEvent() {_handler->f();}
private:
    class _eventHandlerBase;
private:
    _eventHandlerBase* _handler;
private:
    class _eventHandlerBase{
    public:
        virtual void f() = 0;
    };
    
    template<typename T, typename TMemFun>
    class _eventHandler : public _eventHandlerBase{
    public:
        _eventHandler(T* obj, TMemFun mf) : _obj(obj), _mf(mf) {}
        
        // overrides
        void f() {(_obj->*_mf)();}
    private:
        T* _obj;
        TMemFun _mf;
    };
};

// 假設出來的Happy 
class Happy{
public:
    _Event OnSent;
    _Event OnReceive;
    _Event OnConnect;
};

class Handler_Happy{
public:
    Handler_Happy(Happy* happy) : _happy(happy) {}
    
    // 假設處理函數都是長這樣的 
    void OnSent() {std::cout << "OnSent: " << _happy << std::endl;}
    void OnReceive() {std::cout << "OnReceive: " << _happy << std::endl;}
    void OnConnect() {std::cout << "OnConnect: " << _happy << std::endl;}
    
private:
    Happy *_happy;
};

void test(Happy* happys[], int size_happys, Handler_Happy handlers[])
{
    for (int i=0; i<size_happys; i++){
        happys[i]->OnSent.Attach(&handlers[i], &Handler_Happy::OnSent);
        happys[i]->OnReceive.Attach(&handlers[i], &Handler_Happy::OnReceive);
        happys[i]->OnConnect.Attach(&handlers[i], &Handler_Happy::OnConnect);
    }
}

int main()
{

    Happy* happys[10];
    for (int i=0; i<10; i++)
        happys[i] = new Happy();
    
    std::vector<Handler_Happy> handlers;
    for (int i=0; i<10; i++){
        handlers.push_back(Handler_Happy(happys[i]));
    }
    
    test(happys, 10, &handlers[0]); // 假設10個 
    
    for (int i=0; i<10; i++)
        happys[i]->OnSent._RaiseEvent();
        
    for (int i=0; i<10; i++)
        happys[i]->OnReceive._RaiseEvent();
        
    for (int i=0; i<10; i++)
        happys[i]->OnConnect._RaiseEvent();
    
    return 0;
}
