// Copyright ©2010 Erik McClure
#ifndef __FUNCTOR_H__
#define __FUNCTOR_H__
namespace bss_util {
#define __EMPTY
#define __FUNCTOR(name, treturn, rt, argsdef, args, argsval) struct name##_base \
{ \
virtual ~##name##_base() {} \
virtual treturn __fastcall Call(args)const =0; \
inline virtual name##_base* __fastcall Clone() const=0; \
treturn operator()(args) const { rt Call(argsval); } \
}; \
template<class T> \
struct name : name##_base \
{ \
name(T* source, treturn (__fastcall T::*funcptr)(argsdef)) : _funcptr(funcptr), _source(source) {} \
virtual treturn __fastcall Call(args) const { rt (_source->*_funcptr)(argsval); } \
inline virtual name##<T>* __fastcall Clone() const { return new name##<T>(*this); } \
protected: \
T* _source; \
treturn (__fastcall T::*_funcptr)(argsdef); \
}
#define __FUNCTOR0(name,treturn, rt) __FUNCTOR(name,treturn, rt, void, void, __EMPTY)
#define FUNCTOR0(name,treturn) __FUNCTOR0(name, treturn, return)
#define FUNCTOR0V(name) __FUNCTOR0(name, void, __EMPTY)
#define __FUNCTOR_COMBINE(p1,p2) p1##,##p2
#define __FUNCTOR1(name,treturn, rt, arg1type, arg1name) __FUNCTOR(name,treturn, rt, arg1type, arg1type arg1name, arg1name)
#define FUNCTOR1(name,treturn, arg1type) __FUNCTOR1(name, treturn, return, arg1type, arg1)
#define FUNCTOR1V(name,arg1type) __FUNCTOR1(name, void, __EMPTY, arg1type, arg1)
#define __FUNCTOR2(name,treturn, rt, arg1type, arg1name, arg2type, arg2name) __FUNCTOR(name,treturn, rt, __FUNCTOR_COMBINE(arg1type,arg2type), __FUNCTOR_COMBINE(arg1type arg1name,arg2type arg2name), __FUNCTOR_COMBINE(arg1name,arg2name))
#define FUNCTOR2(name,treturn, arg1type, arg2type) __FUNCTOR2(name, treturn, return, arg1type, arg1, arg2type, arg2)
#define FUNCTOR2V(name,arg1type,arg2type) __FUNCTOR2(name, void, __EMPTY, arg1type, arg1, arg2type, arg2)
#define __FUNCTOR3(name,treturn, rt, arg1type, arg1name, arg2type, arg2name, arg3type, arg3name) __FUNCTOR(name,treturn, rt, __FUNCTOR_COMBINE(__FUNCTOR_COMBINE(arg1type,arg2type),arg3type), __FUNCTOR_COMBINE(__FUNCTOR_COMBINE(arg1type arg1name,arg2type arg2name), arg3type arg3name), __FUNCTOR_COMBINE(__FUNCTOR_COMBINE(arg1name,arg2name),arg3name))
#define FUNCTOR3(name,treturn, arg1type, arg2type, arg3type) __FUNCTOR3(name, treturn, return, arg1type, arg1, arg2type, arg2, arg3type, arg3)
#define FUNCTOR3V(name,arg1type,arg2type,arg3type) __FUNCTOR3(name, void, __EMPTY, arg1type, arg1, arg2type, arg2, arg3type, arg3)
//If you go up to 4 the compiler starts having issues with all the defines
}
#endif
I have an unhealthy obsession with metaprogramming