Christopher Haster / mbed-hal

Dependencies:   target-freescale

Fork of mbed-hal by Morpheus

Revision:
6:c2a3aa792960
Parent:
0:9c59db1fbc9e
Child:
7:4fdb3a44f646
--- a/api/FunctionPointer.h	Thu Mar 31 10:37:21 2016 -0500
+++ b/api/FunctionPointer.h	Thu Mar 31 12:18:08 2016 -0500
@@ -13,46 +13,367 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-#ifndef MBED_FUNCTIONPOINTER_H
-#define MBED_FUNCTIONPOINTER_H
+#ifndef MBED_FUNC_H
+#define MBED_FUNC_H
 
 #include <string.h>
 #include <stdint.h>
 
 namespace mbed {
 
-/* If we had variaditic templates, this wouldn't be a problem, but until C++11 is enabled, we are stuck with multiple classes... */
+// Reusable Function class based on template specialization
+template <typename F>
+class Function;
 
 /** A class for storing and calling a pointer to a static or member function
  */
-template <typename R, typename A1>
-class FunctionPointerArg1{
+template <typename R, typename A1, typename A2, typename A3, typename A4>
+class Function<R(A1, A2, A3, A4)> {
 public:
-    /** Create a FunctionPointer, attaching a static function
+    /** Create a Function, attaching a static function
      *
      *  @param function The static function to attach (default is none)
      */
-    FunctionPointerArg1(R (*function)(A1) = 0) {
+    Function(R (*function)(A1, A2, A3, A4) = 0) {
         attach(function);
     }
 
-    /** Create a FunctionPointer, attaching a member function
+    /** Create a Function, attaching a static function with bound pointer
+     *
+     *  @param object Pointer to object to bind to function
+     *  @param function The static function to attach
+     */
+    template<typename T>
+    Function(T *object, R (*function)(T*, A1, A2, A3, A4)) {
+        attach(object, function);
+    }
+
+    /** Create a Function, attaching a member function
      *
      *  @param object The object pointer to invoke the member function on (i.e. the this pointer)
      *  @param function The address of the member function to attach
      */
     template<typename T>
-    FunctionPointerArg1(T *object, R (T::*member)(A1)) {
+    Function(T *object, R (T::*member)(A1, A2, A3, A4)) {
         attach(object, member);
     }
 
+    /** Create a Function from another Function
+     *
+     *  @param func The func to attach
+     */
+    Function(const Function<R(A1, A2, A3, A4)> &func) {
+        attach(func);
+    }
+
     /** Attach a static function
      *
      *  @param function The static function to attach (default is none)
      */
-    void attach(R (*function)(A1)) {
-        _p.function = function;
-        _membercaller = 0;
+    void attach(R (*function)(A1, A2, A3, A4)) {
+        _object = 0;
+        *reinterpret_cast<R (**)(A1)>(_function) = function;
+        _thunk = &Function::staticthunk;
+    }
+
+    /** Attach a static function with bound pointer
+     *
+     *  @param object Pointer to object to bind to function
+     *  @param function The static function to attach
+     */
+    template <typename T>
+    void attach(T *object, R (*function)(A1, A2, A3, A4)) {
+        _object = static_cast<void*>(object);
+        *reinterpret_cast<R (**)(T*, A1)>(_function) = function;
+        _thunk = &Function::boundthunk<T>;
+    }
+
+    /** Attach a member function
+     *
+     *  @param object The object pointer to invoke the member function on (i.e. the this pointer)
+     *  @param function The address of the member function to attach
+     */
+    template<typename T>
+    void attach(T *object, R (T::*method)(A1, A2, A3, A4)) {
+        _object = static_cast<void*>(object);
+        *reinterpret_cast<R (T::**)(A1)>(_function) = method;
+        _thunk = &Function::methodthunk<T>;
+    }
+
+    /** Attach a Function
+     *
+     *  @param func The func to attach
+     */
+    void attach(const Function<R(A1, A2, A3, A4)> &func) {
+        _object = func._object;
+        _function = func._function;
+        _thunk = func._thunk;
+    }
+
+    /** Call the attached static or member function
+     */
+    R call(A1 a1, A2 a2, A3 a3, A4 a4) {
+        return _thunk(_object, _function, a1, a2, a3, a4);
+    }
+
+    /** Get registered static function
+     */
+    R (*get_function(A1, A2, A3, A4))() {
+        return reinterpret_cast<R (*)(A1, A2, A3, A4)>(_object ? 0 : _function);
+    }
+
+#ifdef MBED_OPERATORS
+    R operator ()(A1 a1, A2 a2, A3 a3, A4 a4) {
+        return call(a1, a2, a3, a4);
+    }
+    operator bool(void) const {
+        return reinterpret_cast<bool>(_function);
+    }
+#endif
+private:
+    // Static thunks for various function types
+    static R staticthunk(void *eh, void *func, A1 a1, A2 a2, A3 a3, A4 a4) {
+        R (*f)(A1, A2, A3, A4) = reinterpret_cast<R (*)(A1, A2, A3, A4)>(func);
+        return f(a1, a2, a3, a4);
+    }
+
+    template<typename T>
+    static R boundthunk(void *object, void *func, A1 a1, A2 a2, A3 a3, A4 a4) {
+        T *o = static_cast<T*>(object);
+        R (*f)(T*, A1) = reinterpret_cast<R (*)(T*, A1)>(func);
+        return f(o, a1);
+    }
+
+    template<typename T>
+    static R methodthunk(void *object, void *member, A1 a1, A2 a2, A3 a3, A4 a4) {
+        T* o = static_cast<T*>(object);
+        R (T::**m)(A1, A2, A3, A4) = reinterpret_cast<R (T::**)(A1, A2, A3, A4)>(member);
+        return (o->**m)(a1, a2, a3, a4);
+    }
+
+    // Forward declaration of an unknown class
+    // this kind of declaration is authorized by the standard (see 8.3.3/2 of C++ 03 standard).  
+    // As a result, the compiler will allocate for UnknownFunctionMember_t the biggest size 
+    // and biggest alignment possible for member function. 
+    // This type can be used inside unions, it will help to provide the storage 
+    // with the proper size and alignment guarantees 
+    class UnknownClass;
+
+    // object this pointer
+    void *_object;
+
+    // aligned raw member function pointer storage - converted back by registered thunk
+    char _function[sizeof(void (UnknownClass::*)())];
+
+    // registered function to convert back and call _m.member on _object
+    R (*_thunk)(void*, void*, A1, A2, A3, A4); 
+};
+
+/** A class for storing and calling a pointer to a static or member function
+ */
+template <typename R, typename A1, typename A2, typename A3>
+class Function<R(A1, A2, A3)> {
+public:
+    /** Create a Function, attaching a static function
+     *
+     *  @param function The static function to attach (default is none)
+     */
+    Function(R (*function)(A1, A2, A3) = 0) {
+        attach(function);
+    }
+
+    /** Create a Function, attaching a static function with bound pointer
+     *
+     *  @param object Pointer to object to bind to function
+     *  @param function The static function to attach
+     */
+    template<typename T>
+    Function(T *object, R (*function)(T*, A1, A2, A3)) {
+        attach(object, function);
+    }
+
+    /** Create a Function, attaching a member function
+     *
+     *  @param object The object pointer to invoke the member function on (i.e. the this pointer)
+     *  @param function The address of the member function to attach
+     */
+    template<typename T>
+    Function(T *object, R (T::*member)(A1, A2, A3)) {
+        attach(object, member);
+    }
+
+    /** Create a Function from another Function
+     *
+     *  @param func The func to attach
+     */
+    Function(const Function<R(A1, A2, A3)> &func) {
+        attach(func);
+    }
+
+    /** Attach a static function
+     *
+     *  @param function The static function to attach (default is none)
+     */
+    void attach(R (*function)(A1, A2, A3)) {
+        _object = 0;
+        *reinterpret_cast<R (**)(A1)>(_function) = function;
+        _thunk = &Function::staticthunk;
+    }
+
+    /** Attach a static function with bound pointer
+     *
+     *  @param object Pointer to object to bind to function
+     *  @param function The static function to attach
+     */
+    template <typename T>
+    void attach(T *object, R (*function)(A1, A2, A3)) {
+        _object = static_cast<void*>(object);
+        *reinterpret_cast<R (**)(T*, A1)>(_function) = function;
+        _thunk = &Function::boundthunk<T>;
+    }
+
+    /** Attach a member function
+     *
+     *  @param object The object pointer to invoke the member function on (i.e. the this pointer)
+     *  @param function The address of the member function to attach
+     */
+    template<typename T>
+    void attach(T *object, R (T::*method)(A1, A2, A3)) {
+        _object = static_cast<void*>(object);
+        *reinterpret_cast<R (T::**)(A1)>(_function) = method;
+        _thunk = &Function::methodthunk<T>;
+    }
+
+    /** Attach a Function
+     *
+     *  @param func The func to attach
+     */
+    void attach(const Function<R(A1, A2, A3)> &func) {
+        _object = func._object;
+        _function = func._function;
+        _thunk = func._thunk;
+    }
+
+    /** Call the attached static or member function
+     */
+    R call(A1 a1, A2 a2, A3 a3) {
+        return _thunk(_object, _function, a1, a2, a3);
+    }
+
+    /** Get registered static function
+     */
+    R (*get_function(A1, A2, A3))() {
+        return reinterpret_cast<R (*)(A1, A2, A3)>(_object ? 0 : _function);
+    }
+
+#ifdef MBED_OPERATORS
+    R operator ()(A1 a1, A2 a2, A3 a3) {
+        return call(a1, a2, a3);
+    }
+    operator bool(void) const {
+        return reinterpret_cast<bool>(_function);
+    }
+#endif
+private:
+    // Static thunks for various function types
+    static R staticthunk(void *eh, void *func, A1 a1, A2 a2, A3 a3) {
+        R (*f)(A1, A2, A3) = reinterpret_cast<R (*)(A1, A2, A3)>(func);
+        return f(a1, a2, a3);
+    }
+
+    template<typename T>
+    static R boundthunk(void *object, void *func, A1 a1, A2 a2, A3 a3) {
+        T *o = static_cast<T*>(object);
+        R (*f)(T*, A1) = reinterpret_cast<R (*)(T*, A1)>(func);
+        return f(o, a1);
+    }
+
+    template<typename T>
+    static R methodthunk(void *object, void *member, A1 a1, A2 a2, A3 a3) {
+        T* o = static_cast<T*>(object);
+        R (T::**m)(A1, A2, A3) = reinterpret_cast<R (T::**)(A1, A2, A3)>(member);
+        return (o->**m)(a1, a2, a3);
+    }
+
+    // Forward declaration of an unknown class
+    // this kind of declaration is authorized by the standard (see 8.3.3/2 of C++ 03 standard).  
+    // As a result, the compiler will allocate for UnknownFunctionMember_t the biggest size 
+    // and biggest alignment possible for member function. 
+    // This type can be used inside unions, it will help to provide the storage 
+    // with the proper size and alignment guarantees 
+    class UnknownClass;
+
+    // object this pointer
+    void *_object;
+
+    // aligned raw member function pointer storage - converted back by registered thunk
+    char _function[sizeof(void (UnknownClass::*)())];
+
+    // registered function to convert back and call _m.member on _object
+    R (*_thunk)(void*, void*, A1, A2, A3); 
+};
+
+/** A class for storing and calling a pointer to a static or member function
+ */
+template <typename R, typename A1, typename A2>
+class Function<R(A1, A2)> {
+public:
+    /** Create a Function, attaching a static function
+     *
+     *  @param function The static function to attach (default is none)
+     */
+    Function(R (*function)(A1, A2) = 0) {
+        attach(function);
+    }
+
+    /** Create a Function, attaching a static function with bound pointer
+     *
+     *  @param object Pointer to object to bind to function
+     *  @param function The static function to attach
+     */
+    template<typename T>
+    Function(T *object, R (*function)(T*, A1, A2)) {
+        attach(object, function);
+    }
+
+    /** Create a Function, attaching a member function
+     *
+     *  @param object The object pointer to invoke the member function on (i.e. the this pointer)
+     *  @param function The address of the member function to attach
+     */
+    template<typename T>
+    Function(T *object, R (T::*member)(A1, A2)) {
+        attach(object, member);
+    }
+
+    /** Create a Function from another Function
+     *
+     *  @param func The func to attach
+     */
+    Function(const Function<R(A1, A2)> &func) {
+        attach(func);
+    }
+
+    /** Attach a static function
+     *
+     *  @param function The static function to attach (default is none)
+     */
+    void attach(R (*function)(A1, A2)) {
+        _object = 0;
+        *reinterpret_cast<R (**)(A1)>(_function) = function;
+        _thunk = &Function::staticthunk;
+    }
+
+    /** Attach a static function with bound pointer
+     *
+     *  @param object Pointer to object to bind to function
+     *  @param function The static function to attach
+     */
+    template <typename T>
+    void attach(T *object, R (*function)(A1, A2)) {
+        _object = static_cast<void*>(object);
+        *reinterpret_cast<R (**)(T*, A1)>(_function) = function;
+        _thunk = &Function::boundthunk<T>;
     }
 
     /** Attach a member function
@@ -61,143 +382,379 @@
      *  @param function The address of the member function to attach
      */
     template<typename T>
-    void attach(T *object, R (T::*member)(A1)) {
-        _p.object = static_cast<void*>(object);
-        *reinterpret_cast<R (T::**)(A1)>(_member) = member;
-        _membercaller = &FunctionPointerArg1::membercaller<T>;
+    void attach(T *object, R (T::*method)(A1, A2)) {
+        _object = static_cast<void*>(object);
+        *reinterpret_cast<R (T::**)(A1)>(_function) = method;
+        _thunk = &Function::methodthunk<T>;
+    }
+
+    /** Attach a Function
+     *
+     *  @param func The func to attach
+     */
+    void attach(const Function<R(A1, A2)> &func) {
+        _object = func._object;
+        _function = func._function;
+        _thunk = func._thunk;
     }
 
     /** Call the attached static or member function
      */
-    R call(A1 a) {
-        if (_membercaller == 0 && _p.function) {
-           return _p.function(a);
-        } else if (_membercaller && _p.object) {
-           return _membercaller(_p.object, _member, a);
-        }
-        return (R)0;
+    R call(A1 a1, A2 a2) {
+        return _thunk(_object, _function, a1, a2);
     }
 
     /** Get registered static function
      */
-    R(*get_function(A1))() {
-        return _membercaller ? (R(*)(A1))0 : (R(*)(A1))_p.function;
+    R (*get_function(A1, A2))() {
+        return reinterpret_cast<R (*)(A1, A2)>(_object ? 0 : _function);
     }
 
 #ifdef MBED_OPERATORS
-    R operator ()(A1 a) {
-        return call(a);
+    R operator ()(A1 a1, A2 a2) {
+        return call(a1, a2);
     }
     operator bool(void) const {
-        return (_membercaller != NULL ? _p.object : (void*)_p.function) != NULL;
+        return reinterpret_cast<bool>(_function);
     }
 #endif
 private:
+    // Static thunks for various function types
+    static R staticthunk(void *eh, void *func, A1 a1, A2 a2) {
+        R (*f)(A1, A2) = reinterpret_cast<R (*)(A1, A2)>(func);
+        return f(a1, a2);
+    }
+
     template<typename T>
-    static R membercaller(void *object, uintptr_t *member, A1 a) {
+    static R boundthunk(void *object, void *func, A1 a1, A2 a2) {
+        T *o = static_cast<T*>(object);
+        R (*f)(T*, A1) = reinterpret_cast<R (*)(T*, A1)>(func);
+        return f(o, a1);
+    }
+
+    template<typename T>
+    static R methodthunk(void *object, void *member, A1 a1, A2 a2) {
         T* o = static_cast<T*>(object);
-        R (T::**m)(A1) = reinterpret_cast<R (T::**)(A1)>(member);
-        return (o->**m)(a);
+        R (T::**m)(A1, A2) = reinterpret_cast<R (T::**)(A1, A2)>(member);
+        return (o->**m)(a1, a2);
     }
 
-    union {
-        R (*function)(A1); // static function pointer
-        void *object;      // object this pointer
-    } _p;
-    uintptr_t _member[4]; // aligned raw member function pointer storage - converted back by registered _membercaller
-    R (*_membercaller)(void*, uintptr_t*, A1); // registered membercaller function to convert back and call _m.member on _object
+    // Forward declaration of an unknown class
+    // this kind of declaration is authorized by the standard (see 8.3.3/2 of C++ 03 standard).  
+    // As a result, the compiler will allocate for UnknownFunctionMember_t the biggest size 
+    // and biggest alignment possible for member function. 
+    // This type can be used inside unions, it will help to provide the storage 
+    // with the proper size and alignment guarantees 
+    class UnknownClass;
+
+    // object this pointer
+    void *_object;
+
+    // aligned raw member function pointer storage - converted back by registered thunk
+    char _function[sizeof(void (UnknownClass::*)())];
+
+    // registered function to convert back and call _m.member on _object
+    R (*_thunk)(void*, void*, A1, A2); 
 };
 
-/** A class for storing and calling a pointer to a static or member function (R ()(void))
+/** A class for storing and calling a pointer to a static or member function
  */
-template <typename R>
-class FunctionPointerArg1<R, void>{
+template <typename R, typename A1>
+class Function<R(A1)> {
 public:
-    /** Create a FunctionPointer, attaching a static function
+    /** Create a Function, attaching a static function
      *
      *  @param function The static function to attach (default is none)
      */
-    FunctionPointerArg1(R (*function)(void) = 0) {
+    Function(R (*function)(A1) = 0) {
         attach(function);
     }
 
-    /** Create a FunctionPointer, attaching a member function
+    /** Create a Function, attaching a static function with bound pointer
+     *
+     *  @param object Pointer to object to bind to function
+     *  @param function The static function to attach
+     */
+    template<typename T>
+    Function(T *object, R (*function)(T*, A1)) {
+        attach(object, function);
+    }
+
+    /** Create a Function, attaching a member function
      *
      *  @param object The object pointer to invoke the member function on (i.e. the this pointer)
-     *  @param function The address of the void member function to attach
+     *  @param function The address of the member function to attach
      */
     template<typename T>
-    FunctionPointerArg1(T *object, R (T::*member)(void)) {
+    Function(T *object, R (T::*member)(A1)) {
         attach(object, member);
     }
 
+    /** Create a Function from another Function
+     *
+     *  @param func The func to attach
+     */
+    Function(const Function<R(A1)> &func) {
+        attach(func);
+    }
+
     /** Attach a static function
      *
-     *  @param function The void static function to attach (default is none)
+     *  @param function The static function to attach (default is none)
      */
-    void attach(R (*function)(void)) {
-        _p.function = function;
-        _membercaller = 0;
+    void attach(R (*function)(A1)) {
+        _object = 0;
+        *reinterpret_cast<R (**)(A1)>(_function) = function;
+        _thunk = &Function::staticthunk;
+    }
+
+    /** Attach a static function with bound pointer
+     *
+     *  @param object Pointer to object to bind to function
+     *  @param function The static function to attach
+     */
+    template <typename T>
+    void attach(T *object, R (*function)(A1)) {
+        _object = static_cast<void*>(object);
+        *reinterpret_cast<R (**)(T*, A1)>(_function) = function;
+        _thunk = &Function::boundthunk<T>;
     }
 
     /** Attach a member function
      *
      *  @param object The object pointer to invoke the member function on (i.e. the this pointer)
-     *  @param function The address of the void member function to attach
+     *  @param function The address of the member function to attach
      */
     template<typename T>
-    void attach(T *object, R (T::*member)(void)) {
-        _p.object = static_cast<void*>(object);
-        *reinterpret_cast<R (T::**)(void)>(_member) = member;
-        _membercaller = &FunctionPointerArg1::membercaller<T>;
+    void attach(T *object, R (T::*method)(A1)) {
+        _object = static_cast<void*>(object);
+        *reinterpret_cast<R (T::**)(A1)>(_function) = method;
+        _thunk = &Function::methodthunk<T>;
+    }
+
+    /** Attach a Function
+     *
+     *  @param func The func to attach
+     */
+    void attach(const Function<R(A1)> &func) {
+        _object = func._object;
+        _function = func._function;
+        _thunk = func._thunk;
     }
 
     /** Call the attached static or member function
      */
-    R call(){
-        if (_membercaller == 0 && _p.function) {
-            return _p.function();
-        } else if (_membercaller && _p.object) {
-            return _membercaller(_p.object, _member);
-        }
-        return (R)0;
+    R call(A1 a1) {
+        return _thunk(_object, _function, a1);
     }
 
     /** Get registered static function
      */
-    R(*get_function())() {
-        return _membercaller ? (R(*)())0 : (R(*)())_p.function;
+    R (*get_function(A1))() {
+        return reinterpret_cast<R (*)(A1)>(_object ? 0 : _function);
     }
 
 #ifdef MBED_OPERATORS
-    R operator ()(void) {
+    R operator ()(A1 a1) {
+        return call(a1);
+    }
+    operator bool(void) const {
+        return reinterpret_cast<bool>(_function);
+    }
+#endif
+private:
+    // Static thunks for various function types
+    static R staticthunk(void *eh, void *func, A1 a1) {
+        R (*f)(A1) = reinterpret_cast<R (*)(A1)>(func);
+        return f(a1);
+    }
+
+    template<typename T>
+    static R boundthunk(void *object, void *func, A1 a1) {
+        T *o = static_cast<T*>(object);
+        R (*f)(T*, A1) = reinterpret_cast<R (*)(T*, A1)>(func);
+        return f(o, a1);
+    }
+
+    template<typename T>
+    static R methodthunk(void *object, void *member, A1 a1) {
+        T* o = static_cast<T*>(object);
+        R (T::**m)(A1) = reinterpret_cast<R (T::**)(A1)>(member);
+        return (o->**m)(a1);
+    }
+
+    // Forward declaration of an unknown class
+    // this kind of declaration is authorized by the standard (see 8.3.3/2 of C++ 03 standard).  
+    // As a result, the compiler will allocate for UnknownFunctionMember_t the biggest size 
+    // and biggest alignment possible for member function. 
+    // This type can be used inside unions, it will help to provide the storage 
+    // with the proper size and alignment guarantees 
+    class UnknownClass;
+
+    // object this pointer
+    void *_object;
+
+    // aligned raw member function pointer storage - converted back by registered thunk
+    char _function[sizeof(void (UnknownClass::*)())];
+
+    // registered function to convert back and call _m.member on _object
+    R (*_thunk)(void*, void*, A1); 
+};
+
+/** A class for storing and calling a pointer to a static or member function
+ */
+template <typename R>
+class Function<R()> {
+public:
+    /** Create a Function, attaching a static function
+     *
+     *  @param function The static function to attach (default is none)
+     */
+    Function(R (*function)() = 0) {
+        attach(function);
+    }
+
+    /** Create a Function, attaching a static function with bound pointer
+     *
+     *  @param object Pointer to object to bind to function
+     *  @param function The static function to attach
+     */
+    template<typename T>
+    Function(T *object, R (*function)(T*)) {
+        attach(object, function);
+    }
+
+    /** Create a Function, attaching a member function
+     *
+     *  @param object The object pointer to invoke the member function on (i.e. the this pointer)
+     *  @param function The address of the member function to attach
+     */
+    template<typename T>
+    Function(T *object, R (T::*member)()) {
+        attach(object, member);
+    }
+
+    /** Create a Function from another Function
+     *
+     *  @param func The func to attach
+     */
+    Function(const Function<R()> &func) {
+        attach(func);
+    }
+
+    /** Attach a static function
+     *
+     *  @param function The static function to attach (default is none)
+     */
+    void attach(R (*function)()) {
+        _object = 0;
+        *reinterpret_cast<R (**)()>(_function) = function;
+        _thunk = &Function::staticthunk;
+    }
+
+    /** Attach a static function with bound pointer
+     *
+     *  @param object Pointer to object to bind to function
+     *  @param function The static function to attach
+     */
+    template <typename T>
+    void attach(T *object, R (*function)()) {
+        _object = static_cast<void*>(object);
+        *reinterpret_cast<R (**)(T*)>(_function) = function;
+        _thunk = &Function::boundthunk<T>;
+    }
+
+    /** Attach a member function
+     *
+     *  @param object The object pointer to invoke the member function on (i.e. the this pointer)
+     *  @param function The address of the member function to attach
+     */
+    template<typename T>
+    void attach(T *object, R (T::*method)()) {
+        _object = static_cast<void*>(object);
+        *reinterpret_cast<R (T::**)()>(_function) = method;
+        _thunk = &Function::methodthunk<T>;
+    }
+
+    /** Attach a Function
+     *
+     *  @param func The func to attach
+     */
+    void attach(const Function<R()> &func) {
+        _object = func._object;
+        _function = func._function;
+        _thunk = func._thunk;
+    }
+
+    /** Call the attached static or member function
+     */
+    R call() {
+        return _thunk(_object, _function);
+    }
+
+    /** Get registered static function
+     */
+    R (*get_function())() {
+        return reinterpret_cast<R (*)()>(_object ? 0 : _function);
+    }
+
+#ifdef MBED_OPERATORS
+    R operator ()() {
         return call();
     }
     operator bool(void) const {
-        return (_membercaller != NULL ? _p.object : (void*)_p.function) != NULL;
+        return reinterpret_cast<bool>(_function);
     }
 #endif
+private:
+    // Static thunks for various function types
+    static R staticthunk(void *eh, void *func) {
+        R (*f)() = reinterpret_cast<R (*)()>(func);
+        return f();
+    }
 
-private:
     template<typename T>
-    static R membercaller(void *object, uintptr_t *member) {
+    static R boundthunk(void *object, void *func) {
+        T *o = static_cast<T*>(object);
+        R (*f)(T*) = reinterpret_cast<R (*)(T*)>(func);
+        return f(o);
+    }
+
+    template<typename T>
+    static R methodthunk(void *object, void *member) {
         T* o = static_cast<T*>(object);
-        R (T::**m)(void) = reinterpret_cast<R (T::**)(void)>(member);
+        R (T::**m)() = reinterpret_cast<R (T::**)()>(member);
         return (o->**m)();
     }
 
-    union {
-        R (*function)(void); // static function pointer
-        void *object;        // object this pointer
-    } _p;
-    uintptr_t _member[4]; // aligned raw member function pointer storage - converted back by registered _membercaller
-    R (*_membercaller)(void*, uintptr_t*); // registered membercaller function to convert back and call _m.member on _object
+    // Forward declaration of an unknown class
+    // this kind of declaration is authorized by the standard (see 8.3.3/2 of C++ 03 standard).  
+    // As a result, the compiler will allocate for UnknownFunctionMember_t the biggest size 
+    // and biggest alignment possible for member function. 
+    // This type can be used inside unions, it will help to provide the storage 
+    // with the proper size and alignment guarantees 
+    class UnknownClass;
+
+    // object this pointer
+    void *_object;
+
+    // aligned raw member function pointer storage - converted back by registered thunk
+    char _function[sizeof(void (UnknownClass::*)())];
+
+    // registered function to convert back and call _m.member on _object
+    R (*_thunk)(void*, void*); 
 };
 
-typedef FunctionPointerArg1<void, void> FunctionPointer;
-typedef FunctionPointerArg1<void, int> event_callback_t;
+// Overloads for backwards compatibility
+template <typename R, typename A1>
+class FunctionPointerArg1 : public Function<R(A1)> {};
+
+template <typename R>
+class FunctionPointerArg1<R, void> : public Function<R()> {};
+
+typedef Function<void()> FunctionPointer;
+typedef Function<void(int)> event_callback_t;
 
 } // namespace mbed
 
 #endif
-