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);
Chainer.h@13:4d8a50d4967e, 2016-04-17 (annotated)
- Committer:
- Christopher Haster
- Date:
- Sun Apr 17 21:15:30 2016 -0500
- Revision:
- 13:4d8a50d4967e
- Parent:
- 8:71037a47492d
- Child:
- 14:79be4e700cc9
Added funcptr namespace
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
Christopher Haster |
7:9a62ba2d3d68 | 1 | /* Chainer |
Christopher Haster |
7:9a62ba2d3d68 | 2 | * Static function chaining |
Christopher Haster |
7:9a62ba2d3d68 | 3 | */ |
Christopher Haster |
7:9a62ba2d3d68 | 4 | #ifndef CHAINER_H |
Christopher Haster |
7:9a62ba2d3d68 | 5 | #define CHAINER_H |
Christopher Haster |
7:9a62ba2d3d68 | 6 | |
Christopher Haster |
7:9a62ba2d3d68 | 7 | #include "FuncPtr.h" |
Christopher Haster |
7:9a62ba2d3d68 | 8 | |
Christopher Haster |
13:4d8a50d4967e | 9 | namespace funcptr { |
Christopher Haster |
13:4d8a50d4967e | 10 | |
Christopher Haster |
7:9a62ba2d3d68 | 11 | |
Christopher Haster |
7:9a62ba2d3d68 | 12 | /** Static function chaining |
Christopher Haster |
7:9a62ba2d3d68 | 13 | */ |
Christopher Haster |
7:9a62ba2d3d68 | 14 | template <int N, typename F> |
Christopher Haster |
7:9a62ba2d3d68 | 15 | class Chainer; |
Christopher Haster |
7:9a62ba2d3d68 | 16 | |
Christopher Haster |
7:9a62ba2d3d68 | 17 | /** Static function composition |
Christopher Haster |
7:9a62ba2d3d68 | 18 | */ |
Christopher Haster |
7:9a62ba2d3d68 | 19 | template <int N, typename A0, typename A1, typename A2, typename A3> |
Christopher Haster |
7:9a62ba2d3d68 | 20 | class Chainer<N, void(A0, A1, A2, A3)> { |
Christopher Haster |
7:9a62ba2d3d68 | 21 | public: |
Christopher Haster |
7:9a62ba2d3d68 | 22 | /** Access a function in the chain |
Christopher Haster |
7:9a62ba2d3d68 | 23 | */ |
Christopher Haster |
7:9a62ba2d3d68 | 24 | FuncPtr<void(A0, A1, A2, A3)> &operator[](int i) { |
Christopher Haster |
7:9a62ba2d3d68 | 25 | return _funcs[i]; |
Christopher Haster |
7:9a62ba2d3d68 | 26 | } |
Christopher Haster |
7:9a62ba2d3d68 | 27 | |
Christopher Haster |
7:9a62ba2d3d68 | 28 | /** Attach a function to the chain |
Christopher Haster |
7:9a62ba2d3d68 | 29 | */ |
Christopher Haster |
7:9a62ba2d3d68 | 30 | bool attach(FuncPtr<void(A0, A1, A2, A3)> func) { |
Christopher Haster |
7:9a62ba2d3d68 | 31 | for (int i = 0; i < N; i++) { |
Christopher Haster |
7:9a62ba2d3d68 | 32 | if (!_funcs[i]) { |
Christopher Haster |
7:9a62ba2d3d68 | 33 | _funcs[i].attach(func); |
Christopher Haster |
7:9a62ba2d3d68 | 34 | return true; |
Christopher Haster |
7:9a62ba2d3d68 | 35 | } |
Christopher Haster |
7:9a62ba2d3d68 | 36 | } |
Christopher Haster |
7:9a62ba2d3d68 | 37 | |
Christopher Haster |
7:9a62ba2d3d68 | 38 | return false; |
Christopher Haster |
7:9a62ba2d3d68 | 39 | } |
Christopher Haster |
7:9a62ba2d3d68 | 40 | |
Christopher Haster |
7:9a62ba2d3d68 | 41 | /** Attach a function to the chain |
Christopher Haster |
7:9a62ba2d3d68 | 42 | */ |
Christopher Haster |
7:9a62ba2d3d68 | 43 | template <typename T, typename M> |
Christopher Haster |
7:9a62ba2d3d68 | 44 | bool attach(T *obj, M method) { |
Christopher Haster |
7:9a62ba2d3d68 | 45 | return attach(FuncPtr<void(A0, A1, A2, A3)>(obj, method)); |
Christopher Haster |
7:9a62ba2d3d68 | 46 | } |
Christopher Haster |
7:9a62ba2d3d68 | 47 | |
Christopher Haster |
7:9a62ba2d3d68 | 48 | /** Call each function in the chain |
Christopher Haster |
7:9a62ba2d3d68 | 49 | */ |
Christopher Haster |
7:9a62ba2d3d68 | 50 | void call(A0 a0, A1 a1, A2 a2, A3 a3) { |
Christopher Haster |
7:9a62ba2d3d68 | 51 | for (int i = 0; i < N; i++) { |
Christopher Haster |
7:9a62ba2d3d68 | 52 | if (_funcs[i]) { |
Christopher Haster |
7:9a62ba2d3d68 | 53 | _funcs[i](a0, a1, a2, a3); |
Christopher Haster |
7:9a62ba2d3d68 | 54 | } |
Christopher Haster |
7:9a62ba2d3d68 | 55 | } |
Christopher Haster |
7:9a62ba2d3d68 | 56 | } |
Christopher Haster |
7:9a62ba2d3d68 | 57 | |
Christopher Haster |
7:9a62ba2d3d68 | 58 | /** Call each function in the chain |
Christopher Haster |
7:9a62ba2d3d68 | 59 | */ |
Christopher Haster |
7:9a62ba2d3d68 | 60 | void operator()(A0 a0, A1 a1, A2 a2, A3 a3) { |
Christopher Haster |
7:9a62ba2d3d68 | 61 | return call(a0, a1, a2, a3); |
Christopher Haster |
7:9a62ba2d3d68 | 62 | } |
Christopher Haster |
7:9a62ba2d3d68 | 63 | |
Christopher Haster |
7:9a62ba2d3d68 | 64 | /** Test if any functions have been attached |
Christopher Haster |
7:9a62ba2d3d68 | 65 | */ |
Christopher Haster |
8:71037a47492d | 66 | operator bool() const { |
Christopher Haster |
7:9a62ba2d3d68 | 67 | for (int i = 0; i < N; i++) { |
Christopher Haster |
7:9a62ba2d3d68 | 68 | if (_funcs[i]) { |
Christopher Haster |
7:9a62ba2d3d68 | 69 | return true; |
Christopher Haster |
7:9a62ba2d3d68 | 70 | } |
Christopher Haster |
7:9a62ba2d3d68 | 71 | } |
Christopher Haster |
7:9a62ba2d3d68 | 72 | return false; |
Christopher Haster |
7:9a62ba2d3d68 | 73 | } |
Christopher Haster |
7:9a62ba2d3d68 | 74 | |
Christopher Haster |
7:9a62ba2d3d68 | 75 | /** Static thunk for passing as C-style function |
Christopher Haster |
7:9a62ba2d3d68 | 76 | * @param func Chainer to call passed as void pointer |
Christopher Haster |
7:9a62ba2d3d68 | 77 | */ |
Christopher Haster |
7:9a62ba2d3d68 | 78 | static void thunk(void *func, A0 a0, A1 a1, A2 a2, A3 a3) { |
Christopher Haster |
7:9a62ba2d3d68 | 79 | return static_cast<Chainer<N, void(A0, A1, A2, A3)>*>(func) |
Christopher Haster |
7:9a62ba2d3d68 | 80 | ->call(a0, a1, a2, a3); |
Christopher Haster |
7:9a62ba2d3d68 | 81 | } |
Christopher Haster |
7:9a62ba2d3d68 | 82 | |
Christopher Haster |
7:9a62ba2d3d68 | 83 | private: |
Christopher Haster |
7:9a62ba2d3d68 | 84 | FuncPtr<void(A0, A1, A2, A3)> _funcs[N]; |
Christopher Haster |
7:9a62ba2d3d68 | 85 | }; |
Christopher Haster |
7:9a62ba2d3d68 | 86 | |
Christopher Haster |
7:9a62ba2d3d68 | 87 | /** Static function composition |
Christopher Haster |
7:9a62ba2d3d68 | 88 | */ |
Christopher Haster |
7:9a62ba2d3d68 | 89 | template <int N, typename A0, typename A1, typename A2> |
Christopher Haster |
7:9a62ba2d3d68 | 90 | class Chainer<N, void(A0, A1, A2)> { |
Christopher Haster |
7:9a62ba2d3d68 | 91 | public: |
Christopher Haster |
7:9a62ba2d3d68 | 92 | /** Access a function in the chain |
Christopher Haster |
7:9a62ba2d3d68 | 93 | */ |
Christopher Haster |
7:9a62ba2d3d68 | 94 | FuncPtr<void(A0, A1, A2)> &operator[](int i) { |
Christopher Haster |
7:9a62ba2d3d68 | 95 | return _funcs[i]; |
Christopher Haster |
7:9a62ba2d3d68 | 96 | } |
Christopher Haster |
7:9a62ba2d3d68 | 97 | |
Christopher Haster |
7:9a62ba2d3d68 | 98 | /** Attach a function to the chain |
Christopher Haster |
7:9a62ba2d3d68 | 99 | */ |
Christopher Haster |
7:9a62ba2d3d68 | 100 | bool attach(FuncPtr<void(A0, A1, A2)> func) { |
Christopher Haster |
7:9a62ba2d3d68 | 101 | for (int i = 0; i < N; i++) { |
Christopher Haster |
7:9a62ba2d3d68 | 102 | if (!_funcs[i]) { |
Christopher Haster |
7:9a62ba2d3d68 | 103 | _funcs[i].attach(func); |
Christopher Haster |
7:9a62ba2d3d68 | 104 | return true; |
Christopher Haster |
7:9a62ba2d3d68 | 105 | } |
Christopher Haster |
7:9a62ba2d3d68 | 106 | } |
Christopher Haster |
7:9a62ba2d3d68 | 107 | |
Christopher Haster |
7:9a62ba2d3d68 | 108 | return false; |
Christopher Haster |
7:9a62ba2d3d68 | 109 | } |
Christopher Haster |
7:9a62ba2d3d68 | 110 | |
Christopher Haster |
7:9a62ba2d3d68 | 111 | /** Attach a function to the chain |
Christopher Haster |
7:9a62ba2d3d68 | 112 | */ |
Christopher Haster |
7:9a62ba2d3d68 | 113 | template <typename T, typename M> |
Christopher Haster |
7:9a62ba2d3d68 | 114 | bool attach(T *obj, M method) { |
Christopher Haster |
7:9a62ba2d3d68 | 115 | return attach(FuncPtr<void(A0, A1, A2)>(obj, method)); |
Christopher Haster |
7:9a62ba2d3d68 | 116 | } |
Christopher Haster |
7:9a62ba2d3d68 | 117 | |
Christopher Haster |
7:9a62ba2d3d68 | 118 | /** Call each function in the chain |
Christopher Haster |
7:9a62ba2d3d68 | 119 | */ |
Christopher Haster |
7:9a62ba2d3d68 | 120 | void call(A0 a0, A1 a1, A2 a2) { |
Christopher Haster |
7:9a62ba2d3d68 | 121 | for (int i = 0; i < N; i++) { |
Christopher Haster |
7:9a62ba2d3d68 | 122 | if (_funcs[i]) { |
Christopher Haster |
7:9a62ba2d3d68 | 123 | _funcs[i](a0, a1, a2); |
Christopher Haster |
7:9a62ba2d3d68 | 124 | } |
Christopher Haster |
7:9a62ba2d3d68 | 125 | } |
Christopher Haster |
7:9a62ba2d3d68 | 126 | } |
Christopher Haster |
7:9a62ba2d3d68 | 127 | |
Christopher Haster |
7:9a62ba2d3d68 | 128 | /** Call each function in the chain |
Christopher Haster |
7:9a62ba2d3d68 | 129 | */ |
Christopher Haster |
7:9a62ba2d3d68 | 130 | void operator()(A0 a0, A1 a1, A2 a2) { |
Christopher Haster |
7:9a62ba2d3d68 | 131 | return call(a0, a1, a2); |
Christopher Haster |
7:9a62ba2d3d68 | 132 | } |
Christopher Haster |
7:9a62ba2d3d68 | 133 | |
Christopher Haster |
7:9a62ba2d3d68 | 134 | /** Test if any functions have been attached |
Christopher Haster |
7:9a62ba2d3d68 | 135 | */ |
Christopher Haster |
8:71037a47492d | 136 | operator bool() const { |
Christopher Haster |
7:9a62ba2d3d68 | 137 | for (int i = 0; i < N; i++) { |
Christopher Haster |
7:9a62ba2d3d68 | 138 | if (_funcs[i]) { |
Christopher Haster |
7:9a62ba2d3d68 | 139 | return true; |
Christopher Haster |
7:9a62ba2d3d68 | 140 | } |
Christopher Haster |
7:9a62ba2d3d68 | 141 | } |
Christopher Haster |
7:9a62ba2d3d68 | 142 | return false; |
Christopher Haster |
7:9a62ba2d3d68 | 143 | } |
Christopher Haster |
7:9a62ba2d3d68 | 144 | |
Christopher Haster |
7:9a62ba2d3d68 | 145 | /** Static thunk for passing as C-style function |
Christopher Haster |
7:9a62ba2d3d68 | 146 | * @param func Chainer to call passed as void pointer |
Christopher Haster |
7:9a62ba2d3d68 | 147 | */ |
Christopher Haster |
7:9a62ba2d3d68 | 148 | static void thunk(void *func, A0 a0, A1 a1, A2 a2) { |
Christopher Haster |
7:9a62ba2d3d68 | 149 | return static_cast<Chainer<N, void(A0, A1, A2)>*>(func) |
Christopher Haster |
7:9a62ba2d3d68 | 150 | ->call(a0, a1, a2); |
Christopher Haster |
7:9a62ba2d3d68 | 151 | } |
Christopher Haster |
7:9a62ba2d3d68 | 152 | |
Christopher Haster |
7:9a62ba2d3d68 | 153 | private: |
Christopher Haster |
7:9a62ba2d3d68 | 154 | FuncPtr<void(A0, A1, A2)> _funcs[N]; |
Christopher Haster |
7:9a62ba2d3d68 | 155 | }; |
Christopher Haster |
7:9a62ba2d3d68 | 156 | |
Christopher Haster |
7:9a62ba2d3d68 | 157 | /** Static function composition |
Christopher Haster |
7:9a62ba2d3d68 | 158 | */ |
Christopher Haster |
7:9a62ba2d3d68 | 159 | template <int N, typename A0, typename A1> |
Christopher Haster |
7:9a62ba2d3d68 | 160 | class Chainer<N, void(A0, A1)> { |
Christopher Haster |
7:9a62ba2d3d68 | 161 | public: |
Christopher Haster |
7:9a62ba2d3d68 | 162 | /** Access a function in the chain |
Christopher Haster |
7:9a62ba2d3d68 | 163 | */ |
Christopher Haster |
7:9a62ba2d3d68 | 164 | FuncPtr<void(A0, A1)> &operator[](int i) { |
Christopher Haster |
7:9a62ba2d3d68 | 165 | return _funcs[i]; |
Christopher Haster |
7:9a62ba2d3d68 | 166 | } |
Christopher Haster |
7:9a62ba2d3d68 | 167 | |
Christopher Haster |
7:9a62ba2d3d68 | 168 | /** Attach a function to the chain |
Christopher Haster |
7:9a62ba2d3d68 | 169 | */ |
Christopher Haster |
7:9a62ba2d3d68 | 170 | bool attach(FuncPtr<void(A0, A1)> func) { |
Christopher Haster |
7:9a62ba2d3d68 | 171 | for (int i = 0; i < N; i++) { |
Christopher Haster |
7:9a62ba2d3d68 | 172 | if (!_funcs[i]) { |
Christopher Haster |
7:9a62ba2d3d68 | 173 | _funcs[i].attach(func); |
Christopher Haster |
7:9a62ba2d3d68 | 174 | return true; |
Christopher Haster |
7:9a62ba2d3d68 | 175 | } |
Christopher Haster |
7:9a62ba2d3d68 | 176 | } |
Christopher Haster |
7:9a62ba2d3d68 | 177 | |
Christopher Haster |
7:9a62ba2d3d68 | 178 | return false; |
Christopher Haster |
7:9a62ba2d3d68 | 179 | } |
Christopher Haster |
7:9a62ba2d3d68 | 180 | |
Christopher Haster |
7:9a62ba2d3d68 | 181 | /** Attach a function to the chain |
Christopher Haster |
7:9a62ba2d3d68 | 182 | */ |
Christopher Haster |
7:9a62ba2d3d68 | 183 | template <typename T, typename M> |
Christopher Haster |
7:9a62ba2d3d68 | 184 | bool attach(T *obj, M method) { |
Christopher Haster |
7:9a62ba2d3d68 | 185 | return attach(FuncPtr<void(A0, A1)>(obj, method)); |
Christopher Haster |
7:9a62ba2d3d68 | 186 | } |
Christopher Haster |
7:9a62ba2d3d68 | 187 | |
Christopher Haster |
7:9a62ba2d3d68 | 188 | /** Call each function in the chain |
Christopher Haster |
7:9a62ba2d3d68 | 189 | */ |
Christopher Haster |
7:9a62ba2d3d68 | 190 | void call(A0 a0, A1 a1) { |
Christopher Haster |
7:9a62ba2d3d68 | 191 | for (int i = 0; i < N; i++) { |
Christopher Haster |
7:9a62ba2d3d68 | 192 | if (_funcs[i]) { |
Christopher Haster |
7:9a62ba2d3d68 | 193 | _funcs[i](a0, a1); |
Christopher Haster |
7:9a62ba2d3d68 | 194 | } |
Christopher Haster |
7:9a62ba2d3d68 | 195 | } |
Christopher Haster |
7:9a62ba2d3d68 | 196 | } |
Christopher Haster |
7:9a62ba2d3d68 | 197 | |
Christopher Haster |
7:9a62ba2d3d68 | 198 | /** Call each function in the chain |
Christopher Haster |
7:9a62ba2d3d68 | 199 | */ |
Christopher Haster |
7:9a62ba2d3d68 | 200 | void operator()(A0 a0, A1 a1) { |
Christopher Haster |
7:9a62ba2d3d68 | 201 | return call(a0, a1); |
Christopher Haster |
7:9a62ba2d3d68 | 202 | } |
Christopher Haster |
7:9a62ba2d3d68 | 203 | |
Christopher Haster |
7:9a62ba2d3d68 | 204 | /** Test if any functions have been attached |
Christopher Haster |
7:9a62ba2d3d68 | 205 | */ |
Christopher Haster |
8:71037a47492d | 206 | operator bool() const { |
Christopher Haster |
7:9a62ba2d3d68 | 207 | for (int i = 0; i < N; i++) { |
Christopher Haster |
7:9a62ba2d3d68 | 208 | if (_funcs[i]) { |
Christopher Haster |
7:9a62ba2d3d68 | 209 | return true; |
Christopher Haster |
7:9a62ba2d3d68 | 210 | } |
Christopher Haster |
7:9a62ba2d3d68 | 211 | } |
Christopher Haster |
7:9a62ba2d3d68 | 212 | return false; |
Christopher Haster |
7:9a62ba2d3d68 | 213 | } |
Christopher Haster |
7:9a62ba2d3d68 | 214 | |
Christopher Haster |
7:9a62ba2d3d68 | 215 | /** Static thunk for passing as C-style function |
Christopher Haster |
7:9a62ba2d3d68 | 216 | * @param func Chainer to call passed as void pointer |
Christopher Haster |
7:9a62ba2d3d68 | 217 | */ |
Christopher Haster |
7:9a62ba2d3d68 | 218 | static void thunk(void *func, A0 a0, A1 a1) { |
Christopher Haster |
7:9a62ba2d3d68 | 219 | return static_cast<Chainer<N, void(A0, A1)>*>(func) |
Christopher Haster |
7:9a62ba2d3d68 | 220 | ->call(a0, a1); |
Christopher Haster |
7:9a62ba2d3d68 | 221 | } |
Christopher Haster |
7:9a62ba2d3d68 | 222 | |
Christopher Haster |
7:9a62ba2d3d68 | 223 | private: |
Christopher Haster |
7:9a62ba2d3d68 | 224 | FuncPtr<void(A0, A1)> _funcs[N]; |
Christopher Haster |
7:9a62ba2d3d68 | 225 | }; |
Christopher Haster |
7:9a62ba2d3d68 | 226 | |
Christopher Haster |
7:9a62ba2d3d68 | 227 | /** Static function composition |
Christopher Haster |
7:9a62ba2d3d68 | 228 | */ |
Christopher Haster |
7:9a62ba2d3d68 | 229 | template <int N, typename A0> |
Christopher Haster |
7:9a62ba2d3d68 | 230 | class Chainer<N, void(A0)> { |
Christopher Haster |
7:9a62ba2d3d68 | 231 | public: |
Christopher Haster |
7:9a62ba2d3d68 | 232 | /** Access a function in the chain |
Christopher Haster |
7:9a62ba2d3d68 | 233 | */ |
Christopher Haster |
7:9a62ba2d3d68 | 234 | FuncPtr<void(A0)> &operator[](int i) { |
Christopher Haster |
7:9a62ba2d3d68 | 235 | return _funcs[i]; |
Christopher Haster |
7:9a62ba2d3d68 | 236 | } |
Christopher Haster |
7:9a62ba2d3d68 | 237 | |
Christopher Haster |
7:9a62ba2d3d68 | 238 | /** Attach a function to the chain |
Christopher Haster |
7:9a62ba2d3d68 | 239 | */ |
Christopher Haster |
7:9a62ba2d3d68 | 240 | bool attach(FuncPtr<void(A0)> func) { |
Christopher Haster |
7:9a62ba2d3d68 | 241 | for (int i = 0; i < N; i++) { |
Christopher Haster |
7:9a62ba2d3d68 | 242 | if (!_funcs[i]) { |
Christopher Haster |
7:9a62ba2d3d68 | 243 | _funcs[i].attach(func); |
Christopher Haster |
7:9a62ba2d3d68 | 244 | return true; |
Christopher Haster |
7:9a62ba2d3d68 | 245 | } |
Christopher Haster |
7:9a62ba2d3d68 | 246 | } |
Christopher Haster |
7:9a62ba2d3d68 | 247 | |
Christopher Haster |
7:9a62ba2d3d68 | 248 | return false; |
Christopher Haster |
7:9a62ba2d3d68 | 249 | } |
Christopher Haster |
7:9a62ba2d3d68 | 250 | |
Christopher Haster |
7:9a62ba2d3d68 | 251 | /** Attach a function to the chain |
Christopher Haster |
7:9a62ba2d3d68 | 252 | */ |
Christopher Haster |
7:9a62ba2d3d68 | 253 | template <typename T, typename M> |
Christopher Haster |
7:9a62ba2d3d68 | 254 | bool attach(T *obj, M method) { |
Christopher Haster |
7:9a62ba2d3d68 | 255 | return attach(FuncPtr<void(A0)>(obj, method)); |
Christopher Haster |
7:9a62ba2d3d68 | 256 | } |
Christopher Haster |
7:9a62ba2d3d68 | 257 | |
Christopher Haster |
7:9a62ba2d3d68 | 258 | /** Call each function in the chain |
Christopher Haster |
7:9a62ba2d3d68 | 259 | */ |
Christopher Haster |
7:9a62ba2d3d68 | 260 | void call(A0 a0) { |
Christopher Haster |
7:9a62ba2d3d68 | 261 | for (int i = 0; i < N; i++) { |
Christopher Haster |
7:9a62ba2d3d68 | 262 | if (_funcs[i]) { |
Christopher Haster |
7:9a62ba2d3d68 | 263 | _funcs[i](a0); |
Christopher Haster |
7:9a62ba2d3d68 | 264 | } |
Christopher Haster |
7:9a62ba2d3d68 | 265 | } |
Christopher Haster |
7:9a62ba2d3d68 | 266 | } |
Christopher Haster |
7:9a62ba2d3d68 | 267 | |
Christopher Haster |
7:9a62ba2d3d68 | 268 | /** Call each function in the chain |
Christopher Haster |
7:9a62ba2d3d68 | 269 | */ |
Christopher Haster |
7:9a62ba2d3d68 | 270 | void operator()(A0 a0) { |
Christopher Haster |
7:9a62ba2d3d68 | 271 | return call(a0); |
Christopher Haster |
7:9a62ba2d3d68 | 272 | } |
Christopher Haster |
7:9a62ba2d3d68 | 273 | |
Christopher Haster |
7:9a62ba2d3d68 | 274 | /** Test if any functions have been attached |
Christopher Haster |
7:9a62ba2d3d68 | 275 | */ |
Christopher Haster |
8:71037a47492d | 276 | operator bool() const { |
Christopher Haster |
7:9a62ba2d3d68 | 277 | for (int i = 0; i < N; i++) { |
Christopher Haster |
7:9a62ba2d3d68 | 278 | if (_funcs[i]) { |
Christopher Haster |
7:9a62ba2d3d68 | 279 | return true; |
Christopher Haster |
7:9a62ba2d3d68 | 280 | } |
Christopher Haster |
7:9a62ba2d3d68 | 281 | } |
Christopher Haster |
7:9a62ba2d3d68 | 282 | return false; |
Christopher Haster |
7:9a62ba2d3d68 | 283 | } |
Christopher Haster |
7:9a62ba2d3d68 | 284 | |
Christopher Haster |
7:9a62ba2d3d68 | 285 | /** Static thunk for passing as C-style function |
Christopher Haster |
7:9a62ba2d3d68 | 286 | * @param func Chainer to call passed as void pointer |
Christopher Haster |
7:9a62ba2d3d68 | 287 | */ |
Christopher Haster |
7:9a62ba2d3d68 | 288 | static void thunk(void *func, A0 a0) { |
Christopher Haster |
7:9a62ba2d3d68 | 289 | return static_cast<Chainer<N, void(A0)>*>(func) |
Christopher Haster |
7:9a62ba2d3d68 | 290 | ->call(a0); |
Christopher Haster |
7:9a62ba2d3d68 | 291 | } |
Christopher Haster |
7:9a62ba2d3d68 | 292 | |
Christopher Haster |
7:9a62ba2d3d68 | 293 | private: |
Christopher Haster |
7:9a62ba2d3d68 | 294 | FuncPtr<void(A0)> _funcs[N]; |
Christopher Haster |
7:9a62ba2d3d68 | 295 | }; |
Christopher Haster |
7:9a62ba2d3d68 | 296 | |
Christopher Haster |
7:9a62ba2d3d68 | 297 | /** Static function composition |
Christopher Haster |
7:9a62ba2d3d68 | 298 | */ |
Christopher Haster |
7:9a62ba2d3d68 | 299 | template <int N> |
Christopher Haster |
7:9a62ba2d3d68 | 300 | class Chainer<N, void()> { |
Christopher Haster |
7:9a62ba2d3d68 | 301 | public: |
Christopher Haster |
7:9a62ba2d3d68 | 302 | /** Access a function in the chain |
Christopher Haster |
7:9a62ba2d3d68 | 303 | */ |
Christopher Haster |
7:9a62ba2d3d68 | 304 | FuncPtr<void()> &operator[](int i) { |
Christopher Haster |
7:9a62ba2d3d68 | 305 | return _funcs[i]; |
Christopher Haster |
7:9a62ba2d3d68 | 306 | } |
Christopher Haster |
7:9a62ba2d3d68 | 307 | |
Christopher Haster |
7:9a62ba2d3d68 | 308 | /** Attach a function to the chain |
Christopher Haster |
7:9a62ba2d3d68 | 309 | */ |
Christopher Haster |
7:9a62ba2d3d68 | 310 | bool attach(FuncPtr<void()> func) { |
Christopher Haster |
7:9a62ba2d3d68 | 311 | for (int i = 0; i < N; i++) { |
Christopher Haster |
7:9a62ba2d3d68 | 312 | if (!_funcs[i]) { |
Christopher Haster |
7:9a62ba2d3d68 | 313 | _funcs[i].attach(func); |
Christopher Haster |
7:9a62ba2d3d68 | 314 | return true; |
Christopher Haster |
7:9a62ba2d3d68 | 315 | } |
Christopher Haster |
7:9a62ba2d3d68 | 316 | } |
Christopher Haster |
7:9a62ba2d3d68 | 317 | |
Christopher Haster |
7:9a62ba2d3d68 | 318 | return false; |
Christopher Haster |
7:9a62ba2d3d68 | 319 | } |
Christopher Haster |
7:9a62ba2d3d68 | 320 | |
Christopher Haster |
7:9a62ba2d3d68 | 321 | /** Attach a function to the chain |
Christopher Haster |
7:9a62ba2d3d68 | 322 | */ |
Christopher Haster |
7:9a62ba2d3d68 | 323 | template <typename T, typename M> |
Christopher Haster |
7:9a62ba2d3d68 | 324 | bool attach(T *obj, M method) { |
Christopher Haster |
7:9a62ba2d3d68 | 325 | return attach(FuncPtr<void()>(obj, method)); |
Christopher Haster |
7:9a62ba2d3d68 | 326 | } |
Christopher Haster |
7:9a62ba2d3d68 | 327 | |
Christopher Haster |
7:9a62ba2d3d68 | 328 | /** Call each function in the chain |
Christopher Haster |
7:9a62ba2d3d68 | 329 | */ |
Christopher Haster |
7:9a62ba2d3d68 | 330 | void call() { |
Christopher Haster |
7:9a62ba2d3d68 | 331 | for (int i = 0; i < N; i++) { |
Christopher Haster |
7:9a62ba2d3d68 | 332 | if (_funcs[i]) { |
Christopher Haster |
7:9a62ba2d3d68 | 333 | _funcs[i](); |
Christopher Haster |
7:9a62ba2d3d68 | 334 | } |
Christopher Haster |
7:9a62ba2d3d68 | 335 | } |
Christopher Haster |
7:9a62ba2d3d68 | 336 | } |
Christopher Haster |
7:9a62ba2d3d68 | 337 | |
Christopher Haster |
7:9a62ba2d3d68 | 338 | /** Call each function in the chain |
Christopher Haster |
7:9a62ba2d3d68 | 339 | */ |
Christopher Haster |
7:9a62ba2d3d68 | 340 | void operator()() { |
Christopher Haster |
7:9a62ba2d3d68 | 341 | return call(); |
Christopher Haster |
7:9a62ba2d3d68 | 342 | } |
Christopher Haster |
7:9a62ba2d3d68 | 343 | |
Christopher Haster |
7:9a62ba2d3d68 | 344 | /** Test if any functions have been attached |
Christopher Haster |
7:9a62ba2d3d68 | 345 | */ |
Christopher Haster |
8:71037a47492d | 346 | operator bool() const { |
Christopher Haster |
7:9a62ba2d3d68 | 347 | for (int i = 0; i < N; i++) { |
Christopher Haster |
7:9a62ba2d3d68 | 348 | if (_funcs[i]) { |
Christopher Haster |
7:9a62ba2d3d68 | 349 | return true; |
Christopher Haster |
7:9a62ba2d3d68 | 350 | } |
Christopher Haster |
7:9a62ba2d3d68 | 351 | } |
Christopher Haster |
7:9a62ba2d3d68 | 352 | return false; |
Christopher Haster |
7:9a62ba2d3d68 | 353 | } |
Christopher Haster |
7:9a62ba2d3d68 | 354 | |
Christopher Haster |
7:9a62ba2d3d68 | 355 | /** Static thunk for passing as C-style function |
Christopher Haster |
7:9a62ba2d3d68 | 356 | * @param func Chainer to call passed as void pointer |
Christopher Haster |
7:9a62ba2d3d68 | 357 | */ |
Christopher Haster |
7:9a62ba2d3d68 | 358 | static void thunk(void *func) { |
Christopher Haster |
7:9a62ba2d3d68 | 359 | return static_cast<Chainer<N, void()>*>(func) |
Christopher Haster |
7:9a62ba2d3d68 | 360 | ->call(); |
Christopher Haster |
7:9a62ba2d3d68 | 361 | } |
Christopher Haster |
7:9a62ba2d3d68 | 362 | |
Christopher Haster |
7:9a62ba2d3d68 | 363 | private: |
Christopher Haster |
7:9a62ba2d3d68 | 364 | FuncPtr<void()> _funcs[N]; |
Christopher Haster |
7:9a62ba2d3d68 | 365 | }; |
Christopher Haster |
7:9a62ba2d3d68 | 366 | |
Christopher Haster |
7:9a62ba2d3d68 | 367 | |
Christopher Haster |
13:4d8a50d4967e | 368 | } |
Christopher Haster |
13:4d8a50d4967e | 369 | |
Christopher Haster |
7:9a62ba2d3d68 | 370 | #endif |