#include <iostream>
#include <vector>
template<typename TFuncSignature>
class Callback;
template<typename R, typename ...Arg>
class Callback<R ( Arg... ) > {
public:
typedef R ( *TFunc ) ( void*, Arg... );
Callback() : obj ( 0 ), func ( 0 ) {}
Callback ( void* o, TFunc f ) : obj ( o ), func ( f ) {}
R operator() ( Arg... a1 ) const {
return ( *func ) ( obj, a1... );
}
typedef void* Callback::* SafeBoolType;
operator SafeBoolType () const {
return func != 0 ? &Callback::obj : 0;
}
bool operator! () const {
return func == 0;
}
bool operator== ( const Callback<R ( Arg... ) >& right ) const {
return obj == right.obj && func == right.func;
}
bool operator!= ( const Callback<R ( Arg... ) >& right ) const {
return obj != right.obj || func != right.func;
}
private:
void* obj;
TFunc func;
};
template<typename R, class T, typename ...Arg>
struct DeduceMemCallbackTag {
template<R ( T::*Func ) ( Arg... ) >
static R Wrapper ( void* o, Arg... a ) {
return ( static_cast<T*> ( o )->*Func ) ( a... );
}
template<R ( T::*Func ) ( Arg... ) >
inline static Callback<R ( Arg... ) > Bind ( T* o ) {
return Callback<R ( Arg... ) > ( o, &DeduceMemCallbackTag::Wrapper<Func> );
}
};
template<typename R, typename ...Arg>
struct DeduceStaticCallbackTag {
template<R ( *Func ) ( Arg... ) >
static R Wrapper ( void*, Arg... a ) {
return ( *Func ) ( a... );
}
template<R ( *Func ) ( Arg... ) >
inline static Callback<R ( Arg... ) > Bind( ) {
return Callback<R ( Arg... ) > ( 0, &DeduceStaticCallbackTag::Wrapper<Func> );
}
};
template<typename R, class T, typename ...Arg>
DeduceMemCallbackTag<R, T, Arg...> DeduceMemCallback ( R ( T::* ) ( Arg... ) ) {
return DeduceMemCallbackTag<R, T, Arg...>();
}
template<typename R, typename ...Arg>
DeduceStaticCallbackTag<R, Arg...> DeduceStaticCallback ( R ( * ) ( Arg... ) ) {
return DeduceStaticCallbackTag<R, Arg...>();
}
template <typename... T1> class Event {
public:
typedef void ( * TSignature ) ( T1... );
typedef Callback<void ( T1... ) > TCallback;
protected:
std::vector<TCallback> invocations;
std::vector<Event<T1...>*> events;
public:
const static int ExpectedFunctorCount = 2;
Event () : invocations(), events() {
invocations.reserve ( ExpectedFunctorCount );
events.reserve ( ExpectedFunctorCount );
}
template <void ( * TFunc ) ( T1... ) > void Add ( ) {
TCallback c = DeduceStaticCallback ( 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 = DeduceMemCallback ( TFunc ).template Bind< TFunc > ( object );
invocations.push_back ( c );
}
void Invoke ( T1... t1 ) {
size_t i;
for ( i = 0; i < invocations.size(); ++i ) {
invocations[i] ( t1... );
}
for ( i = 0; i < events.size(); ++i ) {
( *events[i] ) ( t1... );
}
}
void operator() ( T1... t1 ) {
Invoke ( t1... );
}
size_t InvocationCount ( ) {
return events.size( ) + invocations.size( );
}
template <void ( * TFunc ) ( T1... ) > bool Remove ( ) {
TCallback target = DeduceStaticCallback ( TFunc ).template Bind< TFunc >( );
for ( size_t i = 0; i < invocations.size(); ++i ) {
TCallback& inv = invocations[i];
if ( target == inv ) {
invocations.erase ( invocations.begin() + i );
return true;
}
}
return false;
}
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 ) {
TCallback target = DeduceMemCallback ( TFunc ).template Bind< TFunc > ( object );
for ( size_t i = 0; i < invocations.size(); ++i ) {
TCallback& inv = invocations[i];
if ( target == inv ) {
invocations.erase ( invocations.begin() + i );
return true;
}
}
return false;
}
};
namespace IntStatic {
void VoidTest ( ) {
std::cout << "INTO THE VOID" << std::endl;
}
void IntTest ( int num ) {
std::cout << "Got myself a " << num << " !" << std::endl;
}
void IntTest2 ( int num ) {
std::cout << "Now _I_ Got myself a " << num << " !" << std::endl;
}
}
struct Int {
void Test ( int num ) {
std::cout << num << " on the inside of a class... ?" << std::endl;
}
void Test2 ( int num ) {
std::cout << num << " on the inside of a struct, yo !" << std::endl;
}
static void Test3 ( int snum ) {
std::cout << snum << " on the inside of a STATIC method?!" << std::endl;
}
};
struct Multi {
void Test ( std::string woo, std::string yeah ) {
std::cout << "Dat Multi Member Function: ";
std::cout << woo << " | " << yeah << std::endl;
}
void static Test2 ( std::string woo, std::string yeah ) {
std::cout << "Dat Static Multi Function: ";
std::cout << woo << " | " << yeah << std::endl;
}
};
int main ( int argc, char* argv[] ) {
Event<int> intev;
Int i;
Multi m;
intev.Add<Int, &Int::Test>(i);
intev.Add<&IntStatic::IntTest>();
intev.Add<&IntStatic::IntTest2>();
intev(20);
intev.Remove<&IntStatic::IntTest>();
intev.Remove<&IntStatic::IntTest>();
intev.Remove<Int, &Int::Test>(i);
intev(20);
Event<std::string, std::string> doublestringev;
doublestringev.Add<Multi, &Multi::Test>( m );
doublestringev( "Bark Bark", "Meow Meow" );
doublestringev.Remove<Multi, &Multi::Test>( m );
doublestringev.Add<&Multi::Test2>( );
doublestringev( "Bahh Bahh", "Moo Moo" );
return 0;
}