#include <iostream>
#include <vector>
#include <algorithm>
#include <cassert>
 
template<typename TFuncSignature>
class Callback;
 
template<typename R, typename... Args>
class Callback<R(Args...)> {
public:
    typedef R(*TFunc)(void*, Args...);

    Callback() : obj(0), func(0) {}
    Callback(void* o, TFunc f) : obj(o), func(f) {}

    R operator()(Args... a1) const {
        return (*func)(obj, a1...);
    }
    typedef void* Callback::*SafeBoolType;
    operator SafeBoolType() const {
        return func? &Callback::obj : 0;
    }
    bool operator!() const {
        return func == 0;
    }
    bool operator== (const Callback<R(Args...)>& right) const {
        return obj == right.obj && func == right.func;
    }
    bool operator!= (const Callback<R(Args...)>& right) const {
        return obj != right.obj || func != right.func;
    }
private:
    void* obj;
    TFunc func;
};

namespace detail
{
    template<typename R, class T, typename... Args>
    struct DeduceMemCallback { 
        template<R(T::*Func)(Args...)> inline static Callback<R(Args...)> Bind(T* o) {
            struct _ { static R wrapper(void* o, Args... a1) { return (static_cast<T*>(o)->*Func)(a1...); } };
            return Callback<R(Args...)>(o, (R(*)(void*, Args...)) _::wrapper);
        }
    };

    template<typename R, typename... Args>
    struct DeduceStaticCallback { 
        template<R(*Func)(Args...)> inline static Callback<R(Args...)> Bind() { 
            struct _ { static R wrapper(void*, Args... a1) { return (*Func)(a1...); } };
            return Callback<R(Args...)>(0, (R(*)(void*, Args...)) _::wrapper); 
        }
    };
}
 
template<typename R, class T, typename... Args>
detail::DeduceMemCallback<R, T, Args...> DeduceCallback(R(T::*)(Args...)) {
    return detail::DeduceMemCallback<R, T, Args...>();
}

template<typename R, typename... Args>
detail::DeduceStaticCallback<R, Args...> DeduceCallback(R(*)(Args...)) {
    return detail::DeduceStaticCallback<R, Args...>();
}

template <typename... T1> class Event {
public:
    typedef void(*TSignature)(T1...);
    typedef Callback<void(T1...)> TCallback;

protected:
    typedef std::vector<TCallback> Table;
    Table invocations;

public:
    const static int ExpectedFunctorCount = 2;

    Event() : invocations() {
        invocations.reserve(ExpectedFunctorCount);
    }

    template <void (* TFunc)(T1...)> void Add() {
        TCallback c = DeduceCallback(TFunc).template Bind<TFunc>();
        invocations.push_back(c);
    }

    template <typename T, void (T::* TFunc)(T1...)> void Add(T& object) {
        Add<T, TFunc>(&object);
    }

    template <typename T, void (T::* TFunc)(T1...)> void Add(T* object) {
        TCallback c = DeduceCallback(TFunc).template Bind<TFunc>(object);
        invocations.push_back(c);
    }

    void Invoke(T1... t1) {
        for(size_t i = 0; i < invocations.size() ; ++i) invocations[i](t1...); 
    }

    void operator()(T1... t1) {
        Invoke(t1...);
    }

    size_t InvocationCount() { return invocations.size(); }

    template <void (* TFunc)(T1...)> bool Remove ()          
        { return Remove (DeduceCallback(TFunc).template Bind<TFunc>()); } 
    template <typename T, void (T::* TFunc)(T1...)> bool Remove (T& object) 
        { return Remove <T, TFunc>(&object); } 
    template <typename T, void (T::* TFunc)(T1...)> bool Remove (T* object) 
        { return Remove (DeduceCallback(TFunc).template Bind<TFunc>(object)); } 

protected:
    bool Remove(TCallback const& target) {
        auto it = std::find(invocations.begin(), invocations.end(), target);
        if (it==invocations.end()) 
            return false;
        invocations.erase(it);
        return true;
    }
};
 
namespace Static {
           void Test1(int num)  { std::cout << "Static: " << num << " !"        << std::endl; }
}
struct Sink {
           void Test1(int num)  { std::cout << num        << " member function" << std::endl; }
           void Test2(std::string s, double d)  
                                { std::cout << s  << d    << " member function" << std::endl; }
    static void Test3(int snum) { std::cout << snum       << " static member"   << std::endl; }
};
 
int main(int argc, char* argv[]) {
    Event<int> intev;
    Sink sink;
    int count = 20; 
    intev(count++); intev.Add<Sink, &Sink::Test1>(sink);

    intev(count++); intev.Add<&Static::Test1>();
    intev(count++); intev.Add<&Static::Test1>();
    intev(count++); intev.Add<&Static::Test1>();

    intev(count++); assert(intev.Remove<&Static::Test1>());
    intev(count++); assert(intev.Remove<&Static::Test1>());
    intev(count++); assert(intev.Remove<&Static::Test1>());

    assert(!intev.Remove<&Static::Test1>());

    intev(count++); intev.Remove<Sink, &Sink::Test1>(sink);
    intev(count++);

    Event<std::string, double> complex_ev;
    complex_ev.Add<Sink, &Sink::Test2>(sink);

    complex_ev("hello world: ", 42.31415926);
}
