diff --git a/core-util/FunctionPointer.h b/core-util/FunctionPointer.h index 4df53b8..2241c08 100644 --- a/core-util/FunctionPointer.h +++ b/core-util/FunctionPointer.h @@ -27,114 +27,27 @@ namespace mbed { namespace util { -/** A class for storing and calling a pointer to a static or member void function without arguments - */ -template -class FunctionPointer0 : public FunctionPointerBase{ -public: - typedef R(*static_fp)(void); - typedef struct arg_struct{ - } ArgStruct; - /** Create a FunctionPointer, attaching a static function - * - * @param function The void static function to attach (default is none) - */ - FunctionPointer0(static_fp function = 0): - FunctionPointerBase() - { - attach(function); - } - - /** Create a FunctionPointer, 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 - */ - template - FunctionPointer0(T *object, R (T::*member)(void)): - FunctionPointerBase() - { - attach(object, member); - } - - /** Attach a static function - * - * @param function The void static function to attach (default is none) - */ - void attach(static_fp function) { - FunctionPointerBase::_object = reinterpret_cast(function); - FunctionPointerBase::_membercaller = &FunctionPointer0::staticcaller; - } - - /** 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 - */ - template - void attach(T *object, R (T::*member)(void)) { - FunctionPointerBase::_object = static_cast(object); - *reinterpret_cast(FunctionPointerBase::_member) = member; - FunctionPointerBase::_membercaller = &FunctionPointer0::membercaller; - } - - /** Call the attached static or member function - */ - R call(){ - return FunctionPointerBase::call(NULL); - } - - FunctionPointerBind bind() { - FunctionPointerBind fp; - fp.bind(&FunctionPointerBase::_nullops, (ArgStruct *) NULL, this); - return fp; - } - - static_fp get_function()const { - return reinterpret_cast(FunctionPointerBase::_object); - } - - R operator ()(void) { - return call(); - } - -private: - template - static R membercaller(void *object, uintptr_t *member, void *arg) { - (void) arg; - T* o = static_cast(object); - R (T::**m)(void) = reinterpret_cast(member); - return (o->**m)(); - } - static R staticcaller(void *object, uintptr_t *member, void *arg) { - (void) arg; - (void) member; - static_fp f = reinterpret_cast(object); - return f(); - } -}; +template +class FunctionPointerV : public FunctionPointerBase { +protected: + template struct tuple {}; -/* If we had variaditic templates, this wouldn't be a problem, but until C++11 is enabled, we are stuck with multiple classes... */ + template + struct tuple : tuple { + tuple(T& t, Ts... ts) : tuple(ts...), tail(t) {} + tuple(const struct tuple& t) : tuple(t), tail(t.tail) {} -/** A class for storing and calling a pointer to a static or member void function with one argument - */ -template -class FunctionPointer1 : public FunctionPointerBase { -protected: - typedef struct arg_struct{ - A1 a1; - arg_struct(const A1 *b1) { - a1 = *b1; - } - } ArgStruct; + T tail; + }; + typedef struct tuple ArgStruct; public: - typedef R(*static_fp)(A1); + typedef R(*static_fp)(Args...); /** Create a FunctionPointer, attaching a static function * * @param function The void static function to attach (default is none) */ - FunctionPointer1(static_fp function = 0) { + FunctionPointerV(static_fp function = 0) { attach(function); } @@ -144,7 +57,7 @@ class FunctionPointer1 : public FunctionPointerBase { * @param function The address of the void member function to attach */ template - FunctionPointer1(T *object, R (T::*member)(A1)) { + FunctionPointerV(T *object, R (T::*member)(Args...)) { attach(object, member); } @@ -154,7 +67,7 @@ class FunctionPointer1 : public FunctionPointerBase { */ void attach(static_fp function) { FunctionPointerBase::_object = reinterpret_cast(function); - FunctionPointerBase::_membercaller = &FunctionPointer1::staticcaller; + FunctionPointerBase::_membercaller = &FunctionPointerV::staticcaller; } /** Attach a member function @@ -163,440 +76,115 @@ class FunctionPointer1 : public FunctionPointerBase { * @param function The address of the void member function to attach */ template - void attach(T *object, R (T::*member)(A1)) + void attach(T *object, R (T::*member)(Args...)) { FunctionPointerBase::_object = static_cast(object); - *reinterpret_cast(FunctionPointerBase::_member) = member; - FunctionPointerBase::_membercaller = &FunctionPointer1::membercaller; + *reinterpret_cast(FunctionPointerBase::_member) = member; + FunctionPointerBase::_membercaller = &FunctionPointerV::membercaller; } - FunctionPointerBind bind(const A1 &a1) { + FunctionPointerBind bind(Args... args) { FunctionPointerBind fp; - fp.bind(&_fp1_ops, (ArgStruct *) NULL, this, &a1); + fp.bind(&_fpv_ops, (ArgStruct *) NULL, this, std::forward(args)...); return fp; } /** Call the attached static or member function */ - R call(A1 a1) - { - ArgStruct Args(&a1); - return FunctionPointerBase::call(&Args); - } - - static_fp get_function()const + R call(Args... args) { - return reinterpret_cast(FunctionPointerBase::_object); + ArgStruct as(args...); + // return (R)0; + return FunctionPointerBase::call(&as); } - - R operator ()(A1 a) { - return call(a); +// +// static_fp get_function()const +// { +// return reinterpret_cast(FunctionPointerBase::_object); +// } +// + R operator ()(Args... args) { + return call(std::forward(args)...); } private: - template - static R membercaller(void *object, uintptr_t *member, void *arg) { - ArgStruct *Args = static_cast(arg); - T* o = static_cast(object); - R (T::**m)(A1) = reinterpret_cast(member); - return (o->**m)(Args->a1); + template + static R membercaller(T* o, R (T::**m)(Args...), struct tuple<>* t, FArgs... args) { + return (o->**m)(std::forward(args)...); } - static R staticcaller(void *object, uintptr_t *member, void *arg) { - ArgStruct *Args = static_cast(arg); - (void) member; - static_fp f = reinterpret_cast(object); - return f(Args->a1); - } - static void constructor(void * dest, va_list args) { - new(dest) ArgStruct(va_arg(args,A1*)); - } - static void copy_constructor(void *dest , void* src) { - ArgStruct *src_args = static_cast(src); - new(dest) ArgStruct(&(src_args->a1)); - } - static void destructor(void *args) { - ArgStruct *argstruct = static_cast(args); - argstruct->~arg_struct(); - } - -protected: - static const struct FunctionPointerBase::ArgOps _fp1_ops; -}; - -template -const struct FunctionPointerBase::ArgOps FunctionPointer1::_fp1_ops = { - FunctionPointer1::constructor, - FunctionPointer1::copy_constructor, - FunctionPointer1::destructor -}; - - -/** A class for storing and calling a pointer to a static or member void function with two arguments - */ -template -class FunctionPointer2 : public FunctionPointerBase { -protected: - typedef struct arg_struct{ - A1 a1; - A2 a2; - arg_struct(const A1 *b1, const A2 *b2) { - a1 = *b1; - a2 = *b2; - } - } ArgStruct; - -public: - typedef R(*static_fp)(A1, A2); - /** Create a FunctionPointer, attaching a static function - * - * @param function The void static function to attach (default is none) - */ - FunctionPointer2(static_fp function = 0) { - attach(function); - } - - /** Create a FunctionPointer, 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 - */ - template - FunctionPointer2(T *object, R (T::*member)(A1, A2)) { - attach(object, member); - } - - /** Attach a static function - * - * @param function The void static function to attach (default is none) - */ - void attach(static_fp function) { - FunctionPointerBase::_object = reinterpret_cast(function); - FunctionPointerBase::_membercaller = &FunctionPointer2::staticcaller; + template + static R membercaller(T* o, R (T::**m)(Args...), struct tuple* t, FArgs... args) { + return membercaller(o, m, static_cast* >(t), std::forward(args)..., t->tail); } - /** 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 - */ - template - void attach(T *object, R (T::*member)(A1, A2)) - { - FunctionPointerBase::_object = static_cast(object); - *reinterpret_cast(FunctionPointerBase::_member) = member; - FunctionPointerBase::_membercaller = &FunctionPointer2::membercaller; - } - - FunctionPointerBind bind(const A1 &a1, const A2 &a2) { - FunctionPointerBind fp; - fp.bind(&_fp2_ops, (ArgStruct *) NULL, this, &a1, &a2); - return fp; - } - - - /** Call the attached static or member function - */ - R call(A1 a1, A2 a2) - { - ArgStruct Args(&a1, &a2); - return FunctionPointerBase::call(&Args); - } - - static_fp get_function()const - { - return reinterpret_cast(FunctionPointerBase::_object); - } - - R operator ()(A1 a1, A2 a2) { - return call(a1, a2); - } - -private: template static R membercaller(void *object, uintptr_t *member, void *arg) { - ArgStruct *Args = static_cast(arg); + ArgStruct *as = static_cast(arg); T* o = static_cast(object); - R (T::**m)(A1, A2) = reinterpret_cast(member); - return (o->**m)(Args->a1, Args->a2); - } - static R staticcaller(void *object, uintptr_t *member, void *arg) { - ArgStruct *Args = static_cast(arg); - (void) member; - static_fp f = reinterpret_cast(object); - return f(Args->a1, Args->a2); - } - static void constructor(void * dest, va_list args) { - A1 *a1 = va_arg(args, A1*); - A2 *a2 = va_arg(args, A2*); - new(dest) ArgStruct(a1, a2); - } - static void copy_constructor(void *dest , void* src) { - ArgStruct *src_args = static_cast(src); - new(dest) ArgStruct(&(src_args->a1), &(src_args->a2)); - } - static void destructor(void *args) { - ArgStruct *argstruct = static_cast(args); - argstruct->~arg_struct(); - } - -protected: - static const struct FunctionPointerBase::ArgOps _fp2_ops; -}; - -template -const struct FunctionPointerBase::ArgOps FunctionPointer2::_fp2_ops = { - FunctionPointer2::constructor, - FunctionPointer2::copy_constructor, - FunctionPointer2::destructor -}; - -/** A class for storing and calling a pointer to a static or member void function with three arguments - */ -template -class FunctionPointer3 : public FunctionPointerBase { -protected: - typedef struct arg_struct{ - A1 a1; - A2 a2; - A3 a3; - arg_struct(const A1 *b1, const A2 *b2, const A3* b3) { - a1 = *b1; - a2 = *b2; - a3 = *b3; - } - } ArgStruct; - -public: - typedef R(*static_fp)(A1, A2, A3); - /** Create a FunctionPointer, attaching a static function - * - * @param function The void static function to attach (default is none) - */ - FunctionPointer3(static_fp function = 0) { - attach(function); - } - - /** Create a FunctionPointer, 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 - */ - template - FunctionPointer3(T *object, R (T::*member)(A1, A2, A3)) { - attach(object, member); - } - - /** Attach a static function - * - * @param function The void static function to attach (default is none) - */ - void attach(static_fp function) { - FunctionPointerBase::_object = reinterpret_cast(function); - FunctionPointerBase::_membercaller = &FunctionPointer3::staticcaller; + R (T::**m)(Args...) = reinterpret_cast(member); + return membercaller(o,m,as); } - /** 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 - */ - template - void attach(T *object, R (T::*member)(A1, A2, A3)) - { - FunctionPointerBase::_object = static_cast(object); - *reinterpret_cast(FunctionPointerBase::_member) = member; - FunctionPointerBase::_membercaller = &FunctionPointer3::membercaller; + template + static R staticcaller(static_fp f, struct tuple<>* t, FArgs... args) { + return f(std::forward(args)...); } - - FunctionPointerBind bind(const A1 &a1, const A2 &a2, const A3 &a3) { - FunctionPointerBind fp; - fp.bind(&_fp3_ops, (ArgStruct *) NULL, this, &a1, &a2, &a3); - return fp; + template + static R staticcaller(static_fp f, struct tuple* t, FArgs... args) { + return staticcaller(f, static_cast* >(t), std::forward(args)..., t->tail); } - - /** Call the attached static or member function - */ - R call(A1 a1, A2 a2, A3 a3) - { - ArgStruct Args(&a1, &a2, &a3); - return FunctionPointerBase::call(&Args); - } - - static_fp get_function()const - { - return reinterpret_cast(FunctionPointerBase::_object); - } - - R operator ()(A1 a1, A2 a2, A3 a3) { - return call(a1, a2, a3); - } - -private: - template - static R membercaller(void *object, uintptr_t *member, void *arg) { - ArgStruct *Args = static_cast(arg); - T* o = static_cast(object); - R (T::**m)(A1, A2, A3) = reinterpret_cast(member); - return (o->**m)(Args->a1, Args->a2, Args->a3); - } static R staticcaller(void *object, uintptr_t *member, void *arg) { - ArgStruct *Args = static_cast(arg); + ArgStruct *as = static_cast(arg); (void) member; static_fp f = reinterpret_cast(object); - return f(Args->a1, Args->a2, Args->a3); - } - static void constructor(void * dest, va_list args) { - A1 *a1 = va_arg(args, A1*); - A2 *a2 = va_arg(args, A2*); - A3 *a3 = va_arg(args, A3*); - new(dest) ArgStruct(a1, a2, a3); - } - static void copy_constructor(void *dest , void* src) { - ArgStruct *src_args = static_cast(src); - new(dest) ArgStruct(&(src_args->a1), &(src_args->a2), &(src_args->a3)); - } - static void destructor(void *args) { - ArgStruct *argstruct = static_cast(args); - argstruct->~arg_struct(); - } - -protected: - static const struct FunctionPointerBase::ArgOps _fp3_ops; -}; - -template -const struct FunctionPointerBase::ArgOps FunctionPointer3::_fp3_ops = { - FunctionPointer3::constructor, - FunctionPointer3::copy_constructor, - FunctionPointer3::destructor -}; - -/** A class for storing and calling a pointer to a static or member void function with four arguments - */ -template -class FunctionPointer4 : public FunctionPointerBase { -protected: - typedef struct arg_struct{ - A1 a1; - A2 a2; - A3 a3; - A4 a4; - arg_struct(const A1 *b1, const A2 *b2, const A3* b3, const A4* b4) { - a1 = *b1; - a2 = *b2; - a3 = *b3; - a4 = *b4; - } - } ArgStruct; - -public: - typedef R(*static_fp)(A1, A2, A3, A4); - /** Create a FunctionPointer, attaching a static function - * - * @param function The void static function to attach (default is none) - */ - FunctionPointer4(static_fp function = 0) { - attach(function); - } - - /** Create a FunctionPointer, 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 - */ - template - FunctionPointer4(T *object, R (T::*member)(A1, A2, A3, A4)) { - attach(object, member); - } - - /** Attach a static function - * - * @param function The void static function to attach (default is none) - */ - void attach(static_fp function) { - FunctionPointerBase::_object = reinterpret_cast(function); - FunctionPointerBase::_membercaller = &FunctionPointer4::staticcaller; + return staticcaller(f,as); } - /** 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 - */ - template - void attach(T *object, R (T::*member)(A1, A2, A3, A4)) - { - FunctionPointerBase::_object = static_cast(object); - *reinterpret_cast(FunctionPointerBase::_member) = member; - FunctionPointerBase::_membercaller = &FunctionPointer4::membercaller; - } - FunctionPointerBind bind(const A1 &a1, const A2 &a2, const A3 &a3, const A4 &a4) { - FunctionPointerBind fp; - fp.bind(&_fp4_ops, (ArgStruct *) NULL, this, &a1, &a2, &a3, &a4); - return fp; + template + static void constructor(void *dest, va_list vargs, struct tuple<>* t, FArgs... args) { + new(dest) ArgStruct(args...); } - - - /** Call the attached static or member function - */ - R call(A1 a1, A2 a2, A3 a3, A4 a4) - { - ArgStruct Args(&a1, &a2, &a3, &a4); - return FunctionPointerBase::call(&Args); + template + static void constructor(void *dest, va_list vargs, struct tuple* t, FArgs... args) { + constructor(dest, vargs, static_cast* >(t), std::forward(args)..., va_arg(vargs, TA)); } - static_fp get_function()const - { - return reinterpret_cast(FunctionPointerBase::_object); - } - - R operator ()(A1 a1, A2 a2, A3 a3, A4 a4) { - return call(a1, a2, a3, a4); - } - -private: - template - static R membercaller(void *object, uintptr_t *member, void *arg) { - ArgStruct *Args = static_cast(arg); - T* o = static_cast(object); - R (T::**m)(A1, A2, A3, A4) = reinterpret_cast(member); - return (o->**m)(Args->a1, Args->a2, Args->a3, Args->a4); - } - static R staticcaller(void *object, uintptr_t *member, void *arg) { - ArgStruct *Args = static_cast(arg); - (void) member; - static_fp f = reinterpret_cast(object); - return f(Args->a1, Args->a2, Args->a3, Args->a4); - } static void constructor(void * dest, va_list args) { - A1 *a1 = va_arg(args, A1*); - A2 *a2 = va_arg(args, A2*); - A3 *a3 = va_arg(args, A3*); - A4 *a4 = va_arg(args, A4*); - new(dest) ArgStruct(a1, a2, a3, a4); + constructor(dest, args, (ArgStruct *)NULL); } static void copy_constructor(void *dest , void* src) { ArgStruct *src_args = static_cast(src); - new(dest) ArgStruct(&(src_args->a1), &(src_args->a2), &(src_args->a3), &(src_args->a4)); + new(dest) ArgStruct(*src_args); } static void destructor(void *args) { ArgStruct *argstruct = static_cast(args); - argstruct->~arg_struct(); + argstruct->~ArgStruct(); } protected: - static const struct FunctionPointerBase::ArgOps _fp4_ops; + static const struct FunctionPointerBase::ArgOps _fpv_ops; +}; +// +template +const struct FunctionPointerBase::ArgOps FunctionPointerV::_fpv_ops = { + FunctionPointerV::constructor, + FunctionPointerV::copy_constructor, + FunctionPointerV::destructor }; +template +using FunctionPointer0 = FunctionPointerV; +template +using FunctionPointer1 = FunctionPointerV; +template +using FunctionPointer2 = FunctionPointerV; +template +using FunctionPointer3 = FunctionPointerV; template -const struct FunctionPointerBase::ArgOps FunctionPointer4::_fp4_ops = { - FunctionPointer4::constructor, - FunctionPointer4::copy_constructor, - FunctionPointer4::destructor -}; +using FunctionPointer4 = FunctionPointerV; typedef FunctionPointer0 FunctionPointer; //typedef FunctionPointer1 event_callback_t; diff --git a/core-util/FunctionPointerBind.h b/core-util/FunctionPointerBind.h index dea5890..3f7ff09 100644 --- a/core-util/FunctionPointerBind.h +++ b/core-util/FunctionPointerBind.h @@ -28,11 +28,6 @@ #define EVENT_STORAGE_SIZE 32 #endif -#define MBED_STATIC_ASSERT(MBED_STATIC_ASSERT_FAILED,MSG)\ - switch(0){\ - case 0:case (MBED_STATIC_ASSERT_FAILED): \ - break;} - namespace mbed { namespace util { @@ -81,7 +76,7 @@ class FunctionPointerBind : public FunctionPointerBase { template FunctionPointerBind & bind(const struct FunctionPointerBase::ArgOps * ops , S * argStruct, FunctionPointerBase *fp, ...) { - MBED_STATIC_ASSERT(sizeof(S) <= sizeof(_storage), ERROR: Arguments too large for FunctionPointerBind internal storage) + static_assert(sizeof(S) <= sizeof(_storage), "ERROR: Arguments too large for FunctionPointerBind internal storage") if (_ops != &FunctionPointerBase::_nullops) { _ops->destructor(_storage); }