#include <iostream>
#include <vector>
#include <algorithm>
const static auto null = 0;
template<typename TFuncSignature>
class Callback;
/////////////////
/* 0 ARGUMENTS */
/////////////////
template<typename R>
class Callback<R ()> {
public:
typedef R (*TFunc)(void*);
const static size_t Arity = 0;
Callback() : obj(0), func(0) {}
Callback(void* o, TFunc f) : obj(o), func(f) {}
R operator()( ) const {
return (*func)(obj);
}
typedef void* Callback::*SafeBoolType;
operator SafeBoolType () const {
return func != 0? &Callback::obj : 0;
}
bool operator! () const {
return func == 0;
}
bool operator== ( const Callback<R ()>& right ) const {
return obj == right.obj && func == right.func;
}
bool operator!= ( const Callback<R ()>& right ) const {
return obj != right.obj || func != right.func;
}
private:
void* obj;
TFunc func;
};
namespace detail {
template<typename R, class T>
struct DeduceConstMemCallback0 {
template<R(T::*Func)() const> inline static Callback<R()> Bind(T* o) {
struct _ { static R wrapper(void* o) { return (static_cast<T*>(o)->*Func)(); } };
return Callback<R()>(o, (R(*)(void*)) _::wrapper);
}
};
template<typename R, class T>
struct DeduceMemCallback0 {
template<R(T::*Func)()> inline static Callback<R()> Bind(T* o) {
struct _ { static R wrapper(void* o) { return (static_cast<T*>(o)->*Func)(); } };
return Callback<R()>(o, (R(*)(void*)) _::wrapper);
}
};
template<typename R>
struct DeduceStaticCallback0 {
template<R(*Func)()> inline static Callback<R()> Bind() {
struct _ { static R wrapper(void* ) { return (*Func)(); } };
return Callback<R()>(0, (R(*)(void*)) _::wrapper);
}
};
}
template<typename R, class T>
detail::DeduceConstMemCallback0<R, T> DeduceCallback0( R(T::*)() const ) {
return detail::DeduceConstMemCallback0<R, T>();
}
template<typename R, class T>
detail::DeduceMemCallback0<R, T> DeduceCallback0(R(T::*)()) {
return detail::DeduceMemCallback0<R, T>();
}
template<typename R>
detail::DeduceStaticCallback0<R> DeduceCallback0(R(*)()) {
return detail::DeduceStaticCallback0<R>();
}
class EventBase {
public:
const static int ExpectedFunctorCount = 2;
};
class Event {
public:
typedef void(* TSignature)( );
typedef Callback<void( )> TCallback;
typedef std::vector<TCallback> InvocationTable;
protected:
InvocationTable invocations;
public:
const static int ExpectedFunctorCount = 2;
Event () : invocations() {
invocations.reserve( ExpectedFunctorCount );
}
Event ( int expectedfunctorcount ) : invocations() {
invocations.reserve( expectedfunctorcount );
}
template <void (* TFunc)( )> void Add ( ) {
TCallback c = DeduceCallback0( TFunc ).template Bind< TFunc >( );
invocations.push_back( c );
}
template <typename T, void (T::* TFunc)( )> void Add ( T& object ) {
Add<T, TFunc>( &object );
}
template <typename T, void (T::* TFunc)( )> void Add ( T* object ) {
TCallback c = DeduceCallback0( TFunc ).template Bind< TFunc >( object );
invocations.push_back( c );
}
template <typename T, void (T::* TFunc)( ) const> void Add ( T& object ) {
Add<T, TFunc>( &object );
}
template <typename T, void (T::* TFunc)( ) const> void Add ( T* object ) {
TCallback c = DeduceCallback0( TFunc ).template Bind< TFunc >( object );
invocations.push_back( c );
}
void Invoke ( ) {
size_t i;
for ( i = 0; i < invocations.size(); ++i ) {
invocations[i]( );
}
}
void operator() ( ) {
Invoke( );
}
size_t InvocationCount ( ) {
return invocations.size( );
}
template <void (* TFunc)( )> bool Remove ()
{ return Remove (DeduceCallback0(TFunc).template Bind<TFunc>()); }
template <typename T, void (T::* TFunc)( )> bool Remove (T& object)
{ return Remove <T, TFunc>(&object); }
template <typename T, void (T::* TFunc)( )> bool Remove (T* object)
{ return Remove (DeduceCallback0(TFunc).template Bind<TFunc>(object)); }
template <typename T, void (T::* TFunc)( ) const> bool Remove (T& object)
{ return Remove <T, TFunc>(&object); }
template <typename T, void (T::* TFunc)( ) const> bool Remove (T* object)
{ return Remove (DeduceCallback0(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;
}
};
void Arf () {
std::cout << "Puppy Static Function" << std::endl;
}
struct Robot {
void Beep () {
std::cout << "RoZ Beep() Member Function" << std::endl;
}
void operator() () {
std::cout << "RoZ Operator() Member Function" << std::endl;
}
};
int main(int argc, char* argv[]) {
Event ev;
int i = 500;
auto a = [] () {
std::cout << "Lambda me baby!" << std::endl;
};
typedef decltype( a ) alambda;
auto b = [&i] () {
std::cout << "Lambda's captured my " << i << "<3!" << std::endl;
};
typedef decltype( b ) blambda;
i = 600;
void( * funcpointer )() = null;
void( Robot::* robotmemfuncpointer )() = null;
// No good, operator() is const ( Why ? )
//void( blambda::* memfuncpointer )() const = null;
void( alambda::* amemfuncpointer )() const = null;
void( blambda::* bmemfuncpointer )() const = null;
funcpointer = a;
robotmemfuncpointer = &Robot::operator();
amemfuncpointer = &alambda::operator();
bmemfuncpointer = &blambda::operator();
std::cout <<
"===========================================================\n" <<
"Calling Lambdas statically, using Member Function Pointers\n" <<
"===========================================================\n" <<
std::endl;
(a.*amemfuncpointer)();
(b.*bmemfuncpointer)();
std::cout <<
"===============================================================\n" <<
"Calling Lambdas through Callback, because I can, Mother Fucker.\n" <<
"I will also change a captured-by-value integer on the lambda...\n" <<
" because I can, Mother Fucker!\n" <<
"===============================================================\n" <<
std::endl;
i = 200;
ev.Add<alambda, &alambda::operator()>( a );
ev.Add<blambda, &blambda::operator()>( b );
ev();
ev.Remove<blambda, &blambda::operator()>( b );
ev();
// Doesn't remove alambda, it's unique!
ev.Remove<blambda, &blambda::operator()>( b );
ev();
// Now removes alambda
ev.Remove<alambda, &alambda::operator()>( a );
ev();
return 0;
}