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);
Diff: FuncPtr.h
- Revision:
- 2:56e1906f7103
- Parent:
- 1:9c28068feddc
- Child:
- 6:b5f0551273f6
--- a/FuncPtr.h Sun Apr 17 13:34:58 2016 -0500 +++ b/FuncPtr.h Sun Apr 17 14:23:24 2016 -0500 @@ -1,4 +1,5 @@ -/** FuncPtr +/* FuncPtr + * * Flexible templated function class that avoids dynamic memory * allocation without limiting functionality */ @@ -106,13 +107,13 @@ _thunk = func._thunk; } - /** Call the attached static or member function + /** 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 static or member function + /** Call the attached function */ R operator()(A0 a0, A1 a1, A2 a2, A3 a3) { return call(a0, a1, a2, a3); @@ -125,10 +126,10 @@ } /** Static thunk for passing as C-style function - * @param funcptr FuncPtr to call passed as void pointer + * @param func FuncPtr to call passed as void pointer */ - static R thunk(void *funcptr, A0 a0, A1 a1, A2 a2, A3 a3) { - return static_cast<FuncPtr<R(A0, A1, A2, A3)>*>(funcptr) + 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); } @@ -259,13 +260,13 @@ _thunk = func._thunk; } - /** Call the attached static or member function + /** Call the attached function */ R call(A0 a0, A1 a1, A2 a2) { return _thunk(_obj, &_func, a0, a1, a2); } - /** Call the attached static or member function + /** Call the attached function */ R operator()(A0 a0, A1 a1, A2 a2) { return call(a0, a1, a2); @@ -278,10 +279,10 @@ } /** Static thunk for passing as C-style function - * @param funcptr FuncPtr to call passed as void pointer + * @param func FuncPtr to call passed as void pointer */ - static R thunk(void *funcptr, A0 a0, A1 a1, A2 a2) { - return static_cast<FuncPtr<R(A0, A1, A2)>*>(funcptr) + static R thunk(void *func, A0 a0, A1 a1, A2 a2) { + return static_cast<FuncPtr<R(A0, A1, A2)>*>(func) ->call(a0, a1, a2); } @@ -412,13 +413,13 @@ _thunk = func._thunk; } - /** Call the attached static or member function + /** Call the attached function */ R call(A0 a0, A1 a1) { return _thunk(_obj, &_func, a0, a1); } - /** Call the attached static or member function + /** Call the attached function */ R operator()(A0 a0, A1 a1) { return call(a0, a1); @@ -431,10 +432,10 @@ } /** Static thunk for passing as C-style function - * @param funcptr FuncPtr to call passed as void pointer + * @param func FuncPtr to call passed as void pointer */ - static R thunk(void *funcptr, A0 a0, A1 a1) { - return static_cast<FuncPtr<R(A0, A1)>*>(funcptr) + static R thunk(void *func, A0 a0, A1 a1) { + return static_cast<FuncPtr<R(A0, A1)>*>(func) ->call(a0, a1); } @@ -565,13 +566,13 @@ _thunk = func._thunk; } - /** Call the attached static or member function + /** Call the attached function */ R call(A0 a0) { return _thunk(_obj, &_func, a0); } - /** Call the attached static or member function + /** Call the attached function */ R operator()(A0 a0) { return call(a0); @@ -584,10 +585,10 @@ } /** Static thunk for passing as C-style function - * @param funcptr FuncPtr to call passed as void pointer + * @param func FuncPtr to call passed as void pointer */ - static R thunk(void *funcptr, A0 a0) { - return static_cast<FuncPtr<R(A0)>*>(funcptr) + static R thunk(void *func, A0 a0) { + return static_cast<FuncPtr<R(A0)>*>(func) ->call(a0); } @@ -718,13 +719,13 @@ _thunk = func._thunk; } - /** Call the attached static or member function + /** Call the attached function */ R call() { return _thunk(_obj, &_func); } - /** Call the attached static or member function + /** Call the attached function */ R operator()() { return call(); @@ -737,10 +738,10 @@ } /** Static thunk for passing as C-style function - * @param funcptr FuncPtr to call passed as void pointer + * @param func FuncPtr to call passed as void pointer */ - static R thunk(void *funcptr) { - return static_cast<FuncPtr<R()>*>(funcptr) + static R thunk(void *func) { + return static_cast<FuncPtr<R()>*>(func) ->call(); }