Flexible templated function class and related utilities that avoid dynamic memory allocation without limiting functionality
FuncPtr provides a flexible templated function class and related utilities while avoiding dynamic memory allocation and avoiding limited functionality.
FuncPtr provides an intuitive template interface:
FuncPtr<void(const char *)> func(puts); func("hello!\n"); // prints hello!
Several function types are supported by FuncPtr:
// Simple C functions void func(); FuncPtr<void()> fp(func); // C++ Methods struct Thing { void func(); }; Thing thing; FuncPtr<void()> fp(&thing, &Thing::func); // C functions with context void func(Thing *); FuncPtr<void()> fp(&thing, func); // Function objects struct Thing { void operator()(); }; Thing thing; FuncPtr<void()> fp(&thing);
There is no dynamic memory allocation, managing memory is placed entirely on the user. More advanced function manipulation can be accomplished with statically allocated classes:
// Function binding Binder<void(const char *), const char *> bind(putc, "hi!"); bind(); // prints hi! // Function composition Composer<int(const char *), const char *(int)> comp(puts, itoa); comp(10); // prints 10 // Function chaining Chainer<void(const char *), 2> chain; chain.attach(puts); chain.attach(puts); chain("hi!\n"); // prints hi! twice
FuncPtr allows easy support of a large range of function types in C++ APIs with very few lines of code:
class Thing { public: // The following two methods are sufficient for supporting // every supported function type void attach(FuncPtr<void()> func) { _func.attach(func); } template<typename T, typename M> void attach(T *obj, M method) { attach(FuncPtr<void()>(obj, method)); } private: FuncPtr<void()> _func; }
Additionally, FuncPtrs have several utilities for easy integration with C APIs:
// C style callbacks void register_callback(void (*callback)(void *), void *data); register_callback(&FuncPtr<void()>::thunk, &func); // C style functions without context void register_callback(void (*callback)()); Thunker thunk(func); register_callback(thunk); // mbed style callbacks void register_callback(T *obj, void (T::*M)()); register_callback(&func, &FuncPtr<void()>::call);
FuncPtr.h
- Committer:
- Christopher Haster
- Date:
- 2016-04-17
- Revision:
- 18:a0fde14b6c39
- Parent:
- 14:79be4e700cc9
File content as of revision 18:a0fde14b6c39:
/* FuncPtr * * Flexible templated function class that avoids dynamic memory * allocation without limiting functionality */ #ifndef FUNCPTR_H #define FUNCPTR_H #include <string.h> #include <stdint.h> /** FuncPtr class based on template specialization */ template <typename F> class FuncPtr; /** Flexible templated function class */ template <typename R, typename A0, typename A1, typename A2, typename A3, typename A4> class FuncPtr<R(A0, A1, A2, A3, A4)> { public: /** Create a FuncPtr with a static function * @param func Static function to attach */ FuncPtr(R (*func)(A0, A1, A2, A3, A4) = 0) { attach(func); } /** Create a FuncPtr with a static function and bound pointer * @param obj Pointer to object to bind to function * @param func Static function to attach */ template<typename T> FuncPtr(T *obj, R (*func)(T*, A0, A1, A2, A3, A4)) { attach(obj, func); } /** Create a FuncPtr with a method * @param obj Pointer to object to invoke method on * @param func Method to attach */ template<typename T> FuncPtr(T *obj, R (T::*func)(A0, A1, A2, A3, A4)) { attach(obj, func); } /** Create a FuncPtr with a function object * @param func Function object to attach */ template<typename T> FuncPtr(T *obj) { attach(obj, &T::operator()); } /** Create a FuncPtr with another FuncPtr * @param func FuncPtr to attach */ FuncPtr(const FuncPtr<R(A0, A1, A2, A3, A4)> &func) { attach(func); } /** Attach a static function * @param func Static function to attach */ void attach(R (*func)(A0, A1, A2, A3, A4)) { memcpy(&_func, &func, sizeof func); _thunk = func ? &FuncPtr::_staticthunk : 0; } /** Attach a static function with a bound pointer * @param obj Pointer to object to bind to function * @param func Static function to attach */ template <typename T> void attach(T *obj, R (*func)(T*, A0, A1, A2, A3, A4)) { _obj = static_cast<void*>(obj); memcpy(&_func, &func, sizeof func); _thunk = &FuncPtr::_boundthunk<T>; } /** Attach a method * @param obj Pointer to object to invoke method on * @param func Method to attach */ template<typename T> void attach(T *obj, R (T::*func)(A0, A1, A2, A3, A4)) { _obj = static_cast<void*>(obj); memcpy(&_func, &func, sizeof func); _thunk = &FuncPtr::_methodthunk<T>; } /** Attach a function object * @param func Function object to attach */ template<typename T> void attach(T *func) { attach(func, &T::operator()); } /** Attach a FuncPtr * @param func The FuncPtr to attach */ void attach(const FuncPtr<R(A0, A1, A2, A3, A4)> &func) { _obj = func._obj; memcpy(&_func, &func._func, sizeof _func); _thunk = func._thunk; } /** Call the attached function */ R call(A0 a0, A1 a1, A2 a2, A3 a3, A4 a4) { return _thunk(_obj, &_func, a0, a1, a2, a3, a4); } /** Call the attached function */ R operator()(A0 a0, A1 a1, A2 a2, A3 a3, A4 a4) { return call(a0, a1, a2, a3, a4); } /** Test if function has been attached */ operator bool() const { return _thunk; } /** Static thunk for passing as C-style function * @param func FuncPtr to call passed as void pointer */ static R thunk(void *func, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4) { return static_cast<FuncPtr<R(A0, A1, A2, A3, A4)>*>(func) ->call(a0, a1, a2, a3, a4); } private: // Internal thunks for various function types static R _staticthunk(void*, void *func, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4) { return (*reinterpret_cast<R (**)(A0, A1, A2, A3, A4)>(func)) (a0, a1, a2, a3, a4); } template<typename T> static R _boundthunk(void *obj, void *func, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4) { return (*reinterpret_cast<R (**)(T*, A0, A1, A2, A3, A4)>(func)) (static_cast<T*>(obj), a0, a1, a2, a3, a4); } template<typename T> static R _methodthunk(void *obj, void *func, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4) { return (static_cast<T*>(obj)->* (*reinterpret_cast<R (T::**)(A0, A1, A2, A3, A4)>(func))) (a0, a1, a2, a3, a4); } // Stored as pointer to function and pointer to optional object // Function pointer is stored as union of possible function types // to garuntee proper size and alignment struct _class; union { void (*_staticfunc)(); void (*_boundfunc)(_class *); void (_class::*_methodfunc)(); } _func; void *_obj; // Thunk registered on attach to dispatch calls R (*_thunk)(void*, void*, A0, A1, A2, A3, A4); }; /** Flexible templated function class */ template <typename R, typename A0, typename A1, typename A2, typename A3> class FuncPtr<R(A0, A1, A2, A3)> { public: /** Create a FuncPtr with a static function * @param func Static function to attach */ FuncPtr(R (*func)(A0, A1, A2, A3) = 0) { attach(func); } /** Create a FuncPtr with a static function and bound pointer * @param obj Pointer to object to bind to function * @param func Static function to attach */ template<typename T> FuncPtr(T *obj, R (*func)(T*, A0, A1, A2, A3)) { attach(obj, func); } /** Create a FuncPtr with a method * @param obj Pointer to object to invoke method on * @param func Method to attach */ template<typename T> FuncPtr(T *obj, R (T::*func)(A0, A1, A2, A3)) { attach(obj, func); } /** Create a FuncPtr with a function object * @param func Function object to attach */ template<typename T> FuncPtr(T *obj) { attach(obj, &T::operator()); } /** Create a FuncPtr with another FuncPtr * @param func FuncPtr to attach */ FuncPtr(const FuncPtr<R(A0, A1, A2, A3)> &func) { attach(func); } /** Attach a static function * @param func Static function to attach */ void attach(R (*func)(A0, A1, A2, A3)) { memcpy(&_func, &func, sizeof func); _thunk = func ? &FuncPtr::_staticthunk : 0; } /** Attach a static function with a bound pointer * @param obj Pointer to object to bind to function * @param func Static function to attach */ template <typename T> void attach(T *obj, R (*func)(T*, A0, A1, A2, A3)) { _obj = static_cast<void*>(obj); memcpy(&_func, &func, sizeof func); _thunk = &FuncPtr::_boundthunk<T>; } /** Attach a method * @param obj Pointer to object to invoke method on * @param func Method to attach */ template<typename T> void attach(T *obj, R (T::*func)(A0, A1, A2, A3)) { _obj = static_cast<void*>(obj); memcpy(&_func, &func, sizeof func); _thunk = &FuncPtr::_methodthunk<T>; } /** Attach a function object * @param func Function object to attach */ template<typename T> void attach(T *func) { attach(func, &T::operator()); } /** Attach a FuncPtr * @param func The FuncPtr to attach */ void attach(const FuncPtr<R(A0, A1, A2, A3)> &func) { _obj = func._obj; memcpy(&_func, &func._func, sizeof _func); _thunk = func._thunk; } /** Call the attached function */ R call(A0 a0, A1 a1, A2 a2, A3 a3) { return _thunk(_obj, &_func, a0, a1, a2, a3); } /** Call the attached function */ R operator()(A0 a0, A1 a1, A2 a2, A3 a3) { return call(a0, a1, a2, a3); } /** Test if function has been attached */ operator bool() const { return _thunk; } /** Static thunk for passing as C-style function * @param func FuncPtr to call passed as void pointer */ static R thunk(void *func, A0 a0, A1 a1, A2 a2, A3 a3) { return static_cast<FuncPtr<R(A0, A1, A2, A3)>*>(func) ->call(a0, a1, a2, a3); } private: // Internal thunks for various function types static R _staticthunk(void*, void *func, A0 a0, A1 a1, A2 a2, A3 a3) { return (*reinterpret_cast<R (**)(A0, A1, A2, A3)>(func)) (a0, a1, a2, a3); } template<typename T> static R _boundthunk(void *obj, void *func, A0 a0, A1 a1, A2 a2, A3 a3) { return (*reinterpret_cast<R (**)(T*, A0, A1, A2, A3)>(func)) (static_cast<T*>(obj), a0, a1, a2, a3); } template<typename T> static R _methodthunk(void *obj, void *func, A0 a0, A1 a1, A2 a2, A3 a3) { return (static_cast<T*>(obj)->* (*reinterpret_cast<R (T::**)(A0, A1, A2, A3)>(func))) (a0, a1, a2, a3); } // Stored as pointer to function and pointer to optional object // Function pointer is stored as union of possible function types // to garuntee proper size and alignment struct _class; union { void (*_staticfunc)(); void (*_boundfunc)(_class *); void (_class::*_methodfunc)(); } _func; void *_obj; // Thunk registered on attach to dispatch calls R (*_thunk)(void*, void*, A0, A1, A2, A3); }; /** Flexible templated function class */ template <typename R, typename A0, typename A1, typename A2> class FuncPtr<R(A0, A1, A2)> { public: /** Create a FuncPtr with a static function * @param func Static function to attach */ FuncPtr(R (*func)(A0, A1, A2) = 0) { attach(func); } /** Create a FuncPtr with a static function and bound pointer * @param obj Pointer to object to bind to function * @param func Static function to attach */ template<typename T> FuncPtr(T *obj, R (*func)(T*, A0, A1, A2)) { attach(obj, func); } /** Create a FuncPtr with a method * @param obj Pointer to object to invoke method on * @param func Method to attach */ template<typename T> FuncPtr(T *obj, R (T::*func)(A0, A1, A2)) { attach(obj, func); } /** Create a FuncPtr with a function object * @param func Function object to attach */ template<typename T> FuncPtr(T *func) { attach(func, &T::operator()); } /** Create a FuncPtr with another FuncPtr * @param func FuncPtr to attach */ FuncPtr(const FuncPtr<R(A0, A1, A2)> &func) { attach(func); } /** Attach a static function * @param func Static function to attach */ void attach(R (*func)(A0, A1, A2)) { memcpy(&_func, &func, sizeof func); _thunk = func ? &FuncPtr::_staticthunk : 0; } /** Attach a static function with a bound pointer * @param obj Pointer to object to bind to function * @param func Static function to attach */ template <typename T> void attach(T *obj, R (*func)(T*, A0, A1, A2)) { _obj = static_cast<void*>(obj); memcpy(&_func, &func, sizeof func); _thunk = &FuncPtr::_boundthunk<T>; } /** Attach a method * @param obj Pointer to object to invoke method on * @param func Method to attach */ template<typename T> void attach(T *obj, R (T::*func)(A0, A1, A2)) { _obj = static_cast<void*>(obj); memcpy(&_func, &func, sizeof func); _thunk = &FuncPtr::_methodthunk<T>; } /** Attach a function object * @param func Function object to attach */ template<typename T> void attach(T *func) { attach(func, &T::operator()); } /** Attach a FuncPtr * @param func The FuncPtr to attach */ void attach(const FuncPtr<R(A0, A1, A2)> &func) { _obj = func._obj; memcpy(&_func, &func._func, sizeof _func); _thunk = func._thunk; } /** Call the attached function */ R call(A0 a0, A1 a1, A2 a2) { return _thunk(_obj, &_func, a0, a1, a2); } /** Call the attached function */ R operator()(A0 a0, A1 a1, A2 a2) { return call(a0, a1, a2); } /** Test if function has been attached */ operator bool() const { return _thunk; } /** Static thunk for passing as C-style function * @param func FuncPtr to call passed as void pointer */ static R thunk(void *func, A0 a0, A1 a1, A2 a2) { return static_cast<FuncPtr<R(A0, A1, A2)>*>(func) ->call(a0, a1, a2); } private: // Internal thunks for various function types static R _staticthunk(void*, void *func, A0 a0, A1 a1, A2 a2) { return (*reinterpret_cast<R (**)(A0, A1, A2)>(func)) (a0, a1, a2); } template<typename T> static R _boundthunk(void *obj, void *func, A0 a0, A1 a1, A2 a2) { return (*reinterpret_cast<R (**)(T*, A0, A1, A2)>(func)) (static_cast<T*>(obj), a0, a1, a2); } template<typename T> static R _methodthunk(void *obj, void *func, A0 a0, A1 a1, A2 a2) { return (static_cast<T*>(obj)->* (*reinterpret_cast<R (T::**)(A0, A1, A2)>(func))) (a0, a1, a2); } // Stored as pointer to function and pointer to optional object // Function pointer is stored as union of possible function types // to garuntee proper size and alignment struct _class; union { void (*_staticfunc)(); void (*_boundfunc)(_class *); void (_class::*_methodfunc)(); } _func; void *_obj; // Thunk registered on attach to dispatch calls R (*_thunk)(void*, void*, A0, A1, A2); }; /** Flexible templated function class */ template <typename R, typename A0, typename A1> class FuncPtr<R(A0, A1)> { public: /** Create a FuncPtr with a static function * @param func Static function to attach */ FuncPtr(R (*func)(A0, A1) = 0) { attach(func); } /** Create a FuncPtr with a static function and bound pointer * @param obj Pointer to object to bind to function * @param func Static function to attach */ template<typename T> FuncPtr(T *obj, R (*func)(T*, A0, A1)) { attach(obj, func); } /** Create a FuncPtr with a method * @param obj Pointer to object to invoke method on * @param func Method to attach */ template<typename T> FuncPtr(T *obj, R (T::*func)(A0, A1)) { attach(obj, func); } /** Create a FuncPtr with a function object * @param func Function object to attach */ template<typename T> FuncPtr(T *func) { attach(func, &T::operator()); } /** Create a FuncPtr with another FuncPtr * @param func FuncPtr to attach */ FuncPtr(const FuncPtr<R(A0, A1)> &func) { attach(func); } /** Attach a static function * @param func Static function to attach */ void attach(R (*func)(A0, A1)) { memcpy(&_func, &func, sizeof func); _thunk = func ? &FuncPtr::_staticthunk : 0; } /** Attach a static function with a bound pointer * @param obj Pointer to object to bind to function * @param func Static function to attach */ template <typename T> void attach(T *obj, R (*func)(T*, A0, A1)) { _obj = static_cast<void*>(obj); memcpy(&_func, &func, sizeof func); _thunk = &FuncPtr::_boundthunk<T>; } /** Attach a method * @param obj Pointer to object to invoke method on * @param func Method to attach */ template<typename T> void attach(T *obj, R (T::*func)(A0, A1)) { _obj = static_cast<void*>(obj); memcpy(&_func, &func, sizeof func); _thunk = &FuncPtr::_methodthunk<T>; } /** Attach a function object * @param func Function object to attach */ template<typename T> void attach(T *func) { attach(func, &T::operator()); } /** Attach a FuncPtr * @param func The FuncPtr to attach */ void attach(const FuncPtr<R(A0, A1)> &func) { _obj = func._obj; memcpy(&_func, &func._func, sizeof _func); _thunk = func._thunk; } /** Call the attached function */ R call(A0 a0, A1 a1) { return _thunk(_obj, &_func, a0, a1); } /** Call the attached function */ R operator()(A0 a0, A1 a1) { return call(a0, a1); } /** Test if function has been attached */ operator bool() const { return _thunk; } /** Static thunk for passing as C-style function * @param func FuncPtr to call passed as void pointer */ static R thunk(void *func, A0 a0, A1 a1) { return static_cast<FuncPtr<R(A0, A1)>*>(func) ->call(a0, a1); } private: // Internal thunks for various function types static R _staticthunk(void*, void *func, A0 a0, A1 a1) { return (*reinterpret_cast<R (**)(A0, A1)>(func)) (a0, a1); } template<typename T> static R _boundthunk(void *obj, void *func, A0 a0, A1 a1) { return (*reinterpret_cast<R (**)(T*, A0, A1)>(func)) (static_cast<T*>(obj), a0, a1); } template<typename T> static R _methodthunk(void *obj, void *func, A0 a0, A1 a1) { return (static_cast<T*>(obj)->* (*reinterpret_cast<R (T::**)(A0, A1)>(func))) (a0, a1); } // Stored as pointer to function and pointer to optional object // Function pointer is stored as union of possible function types // to garuntee proper size and alignment struct _class; union { void (*_staticfunc)(); void (*_boundfunc)(_class *); void (_class::*_methodfunc)(); } _func; void *_obj; // Thunk registered on attach to dispatch calls R (*_thunk)(void*, void*, A0, A1); }; /** Flexible templated function class */ template <typename R, typename A0> class FuncPtr<R(A0)> { public: /** Create a FuncPtr with a static function * @param func Static function to attach */ FuncPtr(R (*func)(A0) = 0) { attach(func); } /** Create a FuncPtr with a static function and bound pointer * @param obj Pointer to object to bind to function * @param func Static function to attach */ template<typename T> FuncPtr(T *obj, R (*func)(T*, A0)) { attach(obj, func); } /** Create a FuncPtr with a method * @param obj Pointer to object to invoke method on * @param func Method to attach */ template<typename T> FuncPtr(T *obj, R (T::*func)(A0)) { attach(obj, func); } /** Create a FuncPtr with a function object * @param func Function object to attach */ template<typename T> FuncPtr(T *func) { attach(func, &T::operator()); } /** Create a FuncPtr with another FuncPtr * @param func FuncPtr to attach */ FuncPtr(const FuncPtr<R(A0)> &func) { attach(func); } /** Attach a static function * @param func Static function to attach */ void attach(R (*func)(A0)) { memcpy(&_func, &func, sizeof func); _thunk = func ? &FuncPtr::_staticthunk : 0; } /** Attach a static function with a bound pointer * @param obj Pointer to object to bind to function * @param func Static function to attach */ template <typename T> void attach(T *obj, R (*func)(T*, A0)) { _obj = static_cast<void*>(obj); memcpy(&_func, &func, sizeof func); _thunk = &FuncPtr::_boundthunk<T>; } /** Attach a method * @param obj Pointer to object to invoke method on * @param func Method to attach */ template<typename T> void attach(T *obj, R (T::*func)(A0)) { _obj = static_cast<void*>(obj); memcpy(&_func, &func, sizeof func); _thunk = &FuncPtr::_methodthunk<T>; } /** Attach a function object * @param func Function object to attach */ template<typename T> void attach(T *func) { attach(func, &T::operator()); } /** Attach a FuncPtr * @param func The FuncPtr to attach */ void attach(const FuncPtr<R(A0)> &func) { _obj = func._obj; memcpy(&_func, &func._func, sizeof _func); _thunk = func._thunk; } /** Call the attached function */ R call(A0 a0) { return _thunk(_obj, &_func, a0); } /** Call the attached function */ R operator()(A0 a0) { return call(a0); } /** Test if function has been attached */ operator bool() const { return _thunk; } /** Static thunk for passing as C-style function * @param func FuncPtr to call passed as void pointer */ static R thunk(void *func, A0 a0) { return static_cast<FuncPtr<R(A0)>*>(func) ->call(a0); } private: // Internal thunks for various function types static R _staticthunk(void*, void *func, A0 a0) { return (*reinterpret_cast<R (**)(A0)>(func)) (a0); } template<typename T> static R _boundthunk(void *obj, void *func, A0 a0) { return (*reinterpret_cast<R (**)(T*, A0)>(func)) (static_cast<T*>(obj), a0); } template<typename T> static R _methodthunk(void *obj, void *func, A0 a0) { return (static_cast<T*>(obj)->* (*reinterpret_cast<R (T::**)(A0)>(func))) (a0); } // Stored as pointer to function and pointer to optional object // Function pointer is stored as union of possible function types // to garuntee proper size and alignment struct _class; union { void (*_staticfunc)(); void (*_boundfunc)(_class *); void (_class::*_methodfunc)(); } _func; void *_obj; // Thunk registered on attach to dispatch calls R (*_thunk)(void*, void*, A0); }; /** Flexible templated function class */ template <typename R> class FuncPtr<R()> { public: /** Create a FuncPtr with a static function * @param func Static function to attach */ FuncPtr(R (*func)() = 0) { attach(func); } /** Create a FuncPtr with a static function and bound pointer * @param obj Pointer to object to bind to function * @param func Static function to attach */ template<typename T> FuncPtr(T *obj, R (*func)(T*)) { attach(obj, func); } /** Create a FuncPtr with a method * @param obj Pointer to object to invoke method on * @param func Method to attach */ template<typename T> FuncPtr(T *obj, R (T::*func)()) { attach(obj, func); } /** Create a FuncPtr with a function object * @param func Function object to attach */ template<typename T> FuncPtr(T *func) { attach(func, &T::operator()); } /** Create a FuncPtr with another FuncPtr * @param func FuncPtr to attach */ FuncPtr(const FuncPtr<R()> &func) { attach(func); } /** Attach a static function * @param func Static function to attach */ void attach(R (*func)()) { memcpy(&_func, &func, sizeof func); _thunk = func ? &FuncPtr::_staticthunk : 0; } /** Attach a static function with a bound pointer * @param obj Pointer to object to bind to function * @param func Static function to attach */ template <typename T> void attach(T *obj, R (*func)(T*)) { _obj = static_cast<void*>(obj); memcpy(&_func, &func, sizeof func); _thunk = &FuncPtr::_boundthunk<T>; } /** Attach a method * @param obj Pointer to object to invoke method on * @param func Method to attach */ template<typename T> void attach(T *obj, R (T::*func)()) { _obj = static_cast<void*>(obj); memcpy(&_func, &func, sizeof func); _thunk = &FuncPtr::_methodthunk<T>; } /** Attach a function object * @param func Function object to attach */ template<typename T> void attach(T *func) { attach(func, &T::operator()); } /** Attach a FuncPtr * @param func The FuncPtr to attach */ void attach(const FuncPtr<R()> &func) { _obj = func._obj; memcpy(&_func, &func._func, sizeof _func); _thunk = func._thunk; } /** Call the attached function */ R call() { return _thunk(_obj, &_func); } /** Call the attached function */ R operator()() { return call(); } /** Test if function has been attached */ operator bool() const { return _thunk; } /** Static thunk for passing as C-style function * @param func FuncPtr to call passed as void pointer */ static R thunk(void *func) { return static_cast<FuncPtr<R()>*>(func) ->call(); } private: // Internal thunks for various function types static R _staticthunk(void*, void *func) { return (*reinterpret_cast<R (**)()>(func)) (); } template<typename T> static R _boundthunk(void *obj, void *func) { return (*reinterpret_cast<R (**)(T*)>(func)) (static_cast<T*>(obj)); } template<typename T> static R _methodthunk(void *obj, void *func) { return (static_cast<T*>(obj)->* (*reinterpret_cast<R (T::**)()>(func))) (); } // Stored as pointer to function and pointer to optional object // Function pointer is stored as union of possible function types // to garuntee proper size and alignment struct _class; union { void (*_staticfunc)(); void (*_boundfunc)(_class *); void (_class::*_methodfunc)(); } _func; void *_obj; // Thunk registered on attach to dispatch calls R (*_thunk)(void*, void*); }; #endif