Skip to content

Instantly share code, notes, and snippets.

@heroboy
Created January 8, 2014 08:19
Show Gist options
  • Select an option

  • Save heroboy/8313489 to your computer and use it in GitHub Desktop.

Select an option

Save heroboy/8313489 to your computer and use it in GitHub Desktop.
#pragma once
#include <functional>
template<typename FuncT> class Event;
template<typename FuncT>
class _EventBase
{
protected:
std::vector<std::function<FuncT>* > funcs;
public:
_EventBase()
{
}
~_EventBase()
{
for(auto it=funcs.begin();it!=funcs.end();++it)
{
if (*it != nullptr)
delete *it;
}
}
template<typename T>
void * Advise(T&& f)
{
std::function<FuncT> * p = new std::function<FuncT>(std::forward<T>(f));
funcs.push_back(p);
return (void*)p;
}
void Unadvise(void * p)
{
if (p == NULL) return;
bool bHasDelete = false;;
for(auto it=funcs.begin();it!=funcs.end();++it)
{
if (*it == (std::function<FuncT>*)p)
{
bHasDelete = true;
delete *it;
*it = NULL;
}
}
ATLASSERT(bHasDelete);
}
//C# like operator
template<typename T>
void * operator+=(T&& f)
{
return Advise(std::forward<T>(f));
}
void operator-=(void *p)
{
Unadvise(p);
}
};
#define IMPLEMENT_OPERATOR \
void operator()(ARG_LIST1){\
bool bHasNull = false;\
size_t count = funcs.size();\
for(size_t i=0;i<count;++i)\
{\
if (funcs[i])\
{\
(*funcs[i])(ARG_LIST2);\
}\
else\
{\
bHasNull = true;\
}\
}\
if (bHasNull)\
{\
auto newEnd = std::remove(funcs.begin(),funcs.end(),nullptr);\
funcs.erase(newEnd,funcs.end());\
}\
}
class Event0:public _EventBase<void()>
{
public:
#define ARG_LIST1
#define ARG_LIST2
IMPLEMENT_OPERATOR
#undef ARG_LIST1
#undef ARG_LIST2
};
template<typename Arg0>
class Event1:public _EventBase<void(Arg0)>
{
public:
#define ARG_LIST1 Arg0 a0
#define ARG_LIST2 a0
IMPLEMENT_OPERATOR
#undef ARG_LIST1
#undef ARG_LIST2
};
template<typename Arg0,typename Arg1>
class Event2:public _EventBase<void(Arg0,Arg1)>
{
public:
#define ARG_LIST1 Arg0 a0,Arg1 a1
#define ARG_LIST2 a0,a1
IMPLEMENT_OPERATOR
#undef ARG_LIST1
#undef ARG_LIST2
};
template<typename Arg0,typename Arg1,typename Arg2>
class Event3:public _EventBase<void(Arg0,Arg1,Arg2)>
{
public:
#define ARG_LIST1 Arg0 a0,Arg1 a1,Arg2 a2
#define ARG_LIST2 a0,a1,a2
IMPLEMENT_OPERATOR
#undef ARG_LIST1
#undef ARG_LIST2
};
template<typename Arg0,typename Arg1,typename Arg2,typename Arg3>
class Event4:public _EventBase<void(Arg0,Arg1,Arg2,Arg3)>
{
public:
#define ARG_LIST1 Arg0 a0,Arg1 a1,Arg2 a2,Arg3 a3
#define ARG_LIST2 a0,a1,a2,a3
IMPLEMENT_OPERATOR
#undef ARG_LIST1
#undef ARG_LIST2
};
template<typename Arg0,typename Arg1,typename Arg2,typename Arg3,typename Arg4>
class Event5:public _EventBase<void(Arg0,Arg1,Arg2,Arg3,Arg4)>
{
public:
#define ARG_LIST1 Arg0 a0,Arg1 a1,Arg2 a2,Arg3 a3,Arg4 a4
#define ARG_LIST2 a0,a1,a2,a3,a4
IMPLEMENT_OPERATOR
#undef ARG_LIST1
#undef ARG_LIST2
};
template<typename Arg0,typename Arg1,typename Arg2,typename Arg3,typename Arg4,typename Arg5>
class Event6:public _EventBase<void(Arg0,Arg1,Arg2,Arg3,Arg4,Arg5)>
{
public:
#define ARG_LIST1 Arg0 a0,Arg1 a1,Arg2 a2,Arg3 a3,Arg4 a4,Arg5 a5
#define ARG_LIST2 a0,a1,a2,a3,a4,a5
IMPLEMENT_OPERATOR
#undef ARG_LIST1
#undef ARG_LIST2
};
template<typename Arg0,typename Arg1,typename Arg2,typename Arg3,typename Arg4,typename Arg5,typename Arg6>
class Event7:public _EventBase<void(Arg0,Arg1,Arg2,Arg3,Arg4,Arg5,Arg6)>
{
public:
#define ARG_LIST1 Arg0 a0,Arg1 a1,Arg2 a2,Arg3 a3,Arg4 a4,Arg5 a5,Arg6 a6
#define ARG_LIST2 a0,a1,a2,a3,a4,a5,a6
IMPLEMENT_OPERATOR
#undef ARG_LIST1
#undef ARG_LIST2
};
template<typename Arg0,typename Arg1,typename Arg2,typename Arg3,typename Arg4,typename Arg5,typename Arg6,typename Arg7>
class Event8:public _EventBase<void(Arg0,Arg1,Arg2,Arg3,Arg4,Arg5,Arg6,Arg7)>
{
public:
#define ARG_LIST1 Arg0 a0,Arg1 a1,Arg2 a2,Arg3 a3,Arg4 a4,Arg5 a5,Arg6 a6,Arg7 a7
#define ARG_LIST2 a0,a1,a2,a3,a4,a5,a6,a7
IMPLEMENT_OPERATOR
#undef ARG_LIST1
#undef ARG_LIST2
};
template<typename T>
class Event;
template<>
class Event<void()>:public Event0{};
template<typename Arg0>
class Event<void(Arg0)>:public Event1<Arg0>{};
template<typename Arg0,typename Arg1>
class Event<void(Arg0,Arg1)>:public Event2<Arg0,Arg1>{};
template<typename Arg0,typename Arg1,typename Arg2>
class Event<void(Arg0,Arg1,Arg2)>:public Event3<Arg0,Arg1,Arg2>{};
template<typename Arg0,typename Arg1,typename Arg2,typename Arg3>
class Event<void(Arg0,Arg1,Arg2,Arg3)>:public Event4<Arg0,Arg1,Arg2,Arg3>{};
template<typename Arg0,typename Arg1,typename Arg2,typename Arg3,typename Arg4>
class Event<void(Arg0,Arg1,Arg2,Arg3,Arg4)>:public Event5<Arg0,Arg1,Arg2,Arg3,Arg4>{};
template<typename Arg0,typename Arg1,typename Arg2,typename Arg3,typename Arg4,typename Arg5>
class Event<void(Arg0,Arg1,Arg2,Arg3,Arg4,Arg5)>:public Event6<Arg0,Arg1,Arg2,Arg3,Arg4,Arg5>{};
template<typename Arg0,typename Arg1,typename Arg2,typename Arg3,typename Arg4,typename Arg5,typename Arg6>
class Event<void(Arg0,Arg1,Arg2,Arg3,Arg4,Arg5,Arg6)>:public Event7<Arg0,Arg1,Arg2,Arg3,Arg4,Arg5,Arg6>{};
template<typename Arg0,typename Arg1,typename Arg2,typename Arg3,typename Arg4,typename Arg5,typename Arg6,typename Arg7>
class Event<void(Arg0,Arg1,Arg2,Arg3,Arg4,Arg5,Arg6,Arg7)>:public Event8<Arg0,Arg1,Arg2,Arg3,Arg4,Arg5,Arg6,Arg7>{};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment