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: Chainer.h
- Revision:
- 15:0c3d1c4a050b
- Parent:
- 14:79be4e700cc9
- Child:
- 18:a0fde14b6c39
--- a/Chainer.h Sun Apr 17 21:25:00 2016 -0500 +++ b/Chainer.h Sun Apr 17 22:01:07 2016 -0500 @@ -9,13 +9,13 @@ /** Static function chaining */ -template <int N, typename F> +template <typename F, int N> class Chainer; /** Static function composition */ -template <int N, typename A0, typename A1, typename A2, typename A3> -class Chainer<N, void(A0, A1, A2, A3)> { +template <typename A0, typename A1, typename A2, typename A3, int N> +class Chainer<void(A0, A1, A2, A3), N> { public: /** Access a function in the chain */ @@ -74,7 +74,7 @@ * @param func Chainer to call passed as void pointer */ static void thunk(void *func, A0 a0, A1 a1, A2 a2, A3 a3) { - return static_cast<Chainer<N, void(A0, A1, A2, A3)>*>(func) + return static_cast<Chainer<void(A0, A1, A2, A3), N>*>(func) ->call(a0, a1, a2, a3); } @@ -84,8 +84,8 @@ /** Static function composition */ -template <int N, typename A0, typename A1, typename A2> -class Chainer<N, void(A0, A1, A2)> { +template <typename A0, typename A1, typename A2, int N> +class Chainer<void(A0, A1, A2), N> { public: /** Access a function in the chain */ @@ -144,7 +144,7 @@ * @param func Chainer to call passed as void pointer */ static void thunk(void *func, A0 a0, A1 a1, A2 a2) { - return static_cast<Chainer<N, void(A0, A1, A2)>*>(func) + return static_cast<Chainer<void(A0, A1, A2), N>*>(func) ->call(a0, a1, a2); } @@ -154,8 +154,8 @@ /** Static function composition */ -template <int N, typename A0, typename A1> -class Chainer<N, void(A0, A1)> { +template <typename A0, typename A1, int N> +class Chainer<void(A0, A1), N> { public: /** Access a function in the chain */ @@ -214,7 +214,7 @@ * @param func Chainer to call passed as void pointer */ static void thunk(void *func, A0 a0, A1 a1) { - return static_cast<Chainer<N, void(A0, A1)>*>(func) + return static_cast<Chainer<void(A0, A1), N>*>(func) ->call(a0, a1); } @@ -224,8 +224,8 @@ /** Static function composition */ -template <int N, typename A0> -class Chainer<N, void(A0)> { +template <typename A0, int N> +class Chainer<void(A0), N> { public: /** Access a function in the chain */ @@ -284,7 +284,7 @@ * @param func Chainer to call passed as void pointer */ static void thunk(void *func, A0 a0) { - return static_cast<Chainer<N, void(A0)>*>(func) + return static_cast<Chainer<void(A0), N>*>(func) ->call(a0); } @@ -295,7 +295,7 @@ /** Static function composition */ template <int N> -class Chainer<N, void()> { +class Chainer<void(), N> { public: /** Access a function in the chain */ @@ -354,7 +354,7 @@ * @param func Chainer to call passed as void pointer */ static void thunk(void *func) { - return static_cast<Chainer<N, void()>*>(func) + return static_cast<Chainer<void(), N>*>(func) ->call(); }