From 161a2ec259aadfe88a166b0f302cd3507222351f Mon Sep 17 00:00:00 2001 From: Christopher Haster Date: Tue, 27 Sep 2016 16:03:00 -0500 Subject: [PATCH] callback - Added size-limited function-object overloads to Callback The callback class can now accept generalized function-objects: class Thing { public: int value; void operator()() { printf("hi! %d\n", value); } }; Callback cb(Thing(2)); However, with the intention of avoiding implicit dynamic-memory allocations, the Callback class is limited to a single word of storage. Exceeding this size will eliminate the function-object type from the overload set and fail to compile. Effort was invested to make this situation very clear to the user. Here is an example error message with noise removed: [ERROR] ./main.cpp: In function 'int main()': ./mbed-os/hal/api/Ticker.h:101:10: note: no known conversion for argument 1 from 'BigFunc' to 'mbed::Callback' The real benefit of this change is the ability for users to hook into the attributes of the Callback class. This mostly allows lifetime management of the function-objects from third-party libraries (such as the Event class from mbed-events). Note: The convenient `callback` function may become ambiguous if provided with a type that defines multiple incompatible `operator()` member functions. --- hal/api/Callback.h | 912 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 912 insertions(+) diff --git a/hal/api/Callback.h b/hal/api/Callback.h index f8089ed70a..78a3b0e9d1 100644 --- a/hal/api/Callback.h +++ b/hal/api/Callback.h @@ -32,6 +32,30 @@ namespace mbed { template class Callback; +// Internal sfinae declarations +// +// These are used to eliminate overloads based on type attributes +// 1. Does a function object have a call operator +// 2. Does a function object fit in the available storage +// +// These eliminations are handled cleanly by the compiler and avoid +// massive and misleading error messages when confronted with an +// invalid type (or worse, runtime failures) +namespace detail { + struct nil {}; + + template + struct enable_if { typedef R type; }; + + template + struct enable_if {}; + + template + struct is_type { + static const bool value = true; + }; +} + /** Callback class based on template specialization * * @Note Synchronization level: Not protected @@ -164,6 +188,54 @@ public: generate(function_context(func, arg)); } + /** Create a Callback with a function object + * @param func Function object to attach + * @note The function object is limited to a single word of storage + */ + template + Callback(F f, typename detail::enable_if< + detail::is_type::value && + sizeof(F) <= sizeof(uintptr_t) + >::type = detail::nil()) { + generate(f); + } + + /** Create a Callback with a function object + * @param func Function object to attach + * @note The function object is limited to a single word of storage + */ + template + Callback(const F f, typename detail::enable_if< + detail::is_type::value && + sizeof(F) <= sizeof(uintptr_t) + >::type = detail::nil()) { + generate(f); + } + + /** Create a Callback with a function object + * @param func Function object to attach + * @note The function object is limited to a single word of storage + */ + template + Callback(volatile F f, typename detail::enable_if< + detail::is_type::value && + sizeof(F) <= sizeof(uintptr_t) + >::type = detail::nil()) { + generate(f); + } + + /** Create a Callback with a function object + * @param func Function object to attach + * @note The function object is limited to a single word of storage + */ + template + Callback(const volatile F f, typename detail::enable_if< + detail::is_type::value && + sizeof(F) <= sizeof(uintptr_t) + >::type = detail::nil()) { + generate(f); + } + /** Create a Callback with a static function and bound pointer * @param obj Pointer to object to bind to function * @param func Static function to attach @@ -404,6 +476,58 @@ public: new (this) Callback(func, arg); } + /** Attach a function object + * @param func Function object to attach + * @note The function object is limited to a single word of storage + */ + template + void attach(F f, typename detail::enable_if< + detail::is_type::value && + sizeof(F) <= sizeof(uintptr_t) + >::type = detail::nil()) { + this->~Callback(); + new (this) Callback(f); + } + + /** Attach a function object + * @param func Function object to attach + * @note The function object is limited to a single word of storage + */ + template + void attach(const F f, typename detail::enable_if< + detail::is_type::value && + sizeof(F) <= sizeof(uintptr_t) + >::type = detail::nil()) { + this->~Callback(); + new (this) Callback(f); + } + + /** Attach a function object + * @param func Function object to attach + * @note The function object is limited to a single word of storage + */ + template + void attach(volatile F f, typename detail::enable_if< + detail::is_type::value && + sizeof(F) <= sizeof(uintptr_t) + >::type = detail::nil()) { + this->~Callback(); + new (this) Callback(f); + } + + /** Attach a function object + * @param func Function object to attach + * @note The function object is limited to a single word of storage + */ + template + void attach(const volatile F f, typename detail::enable_if< + detail::is_type::value && + sizeof(F) <= sizeof(uintptr_t) + >::type = detail::nil()) { + this->~Callback(); + new (this) Callback(f); + } + /** Attach a static function with a bound pointer * @param obj Pointer to object to bind to function * @param func Static function to attach @@ -768,6 +892,54 @@ public: generate(function_context(func, arg)); } + /** Create a Callback with a function object + * @param func Function object to attach + * @note The function object is limited to a single word of storage + */ + template + Callback(F f, typename detail::enable_if< + detail::is_type::value && + sizeof(F) <= sizeof(uintptr_t) + >::type = detail::nil()) { + generate(f); + } + + /** Create a Callback with a function object + * @param func Function object to attach + * @note The function object is limited to a single word of storage + */ + template + Callback(const F f, typename detail::enable_if< + detail::is_type::value && + sizeof(F) <= sizeof(uintptr_t) + >::type = detail::nil()) { + generate(f); + } + + /** Create a Callback with a function object + * @param func Function object to attach + * @note The function object is limited to a single word of storage + */ + template + Callback(volatile F f, typename detail::enable_if< + detail::is_type::value && + sizeof(F) <= sizeof(uintptr_t) + >::type = detail::nil()) { + generate(f); + } + + /** Create a Callback with a function object + * @param func Function object to attach + * @note The function object is limited to a single word of storage + */ + template + Callback(const volatile F f, typename detail::enable_if< + detail::is_type::value && + sizeof(F) <= sizeof(uintptr_t) + >::type = detail::nil()) { + generate(f); + } + /** Create a Callback with a static function and bound pointer * @param obj Pointer to object to bind to function * @param func Static function to attach @@ -1008,6 +1180,58 @@ public: new (this) Callback(func, arg); } + /** Attach a function object + * @param func Function object to attach + * @note The function object is limited to a single word of storage + */ + template + void attach(F f, typename detail::enable_if< + detail::is_type::value && + sizeof(F) <= sizeof(uintptr_t) + >::type = detail::nil()) { + this->~Callback(); + new (this) Callback(f); + } + + /** Attach a function object + * @param func Function object to attach + * @note The function object is limited to a single word of storage + */ + template + void attach(const F f, typename detail::enable_if< + detail::is_type::value && + sizeof(F) <= sizeof(uintptr_t) + >::type = detail::nil()) { + this->~Callback(); + new (this) Callback(f); + } + + /** Attach a function object + * @param func Function object to attach + * @note The function object is limited to a single word of storage + */ + template + void attach(volatile F f, typename detail::enable_if< + detail::is_type::value && + sizeof(F) <= sizeof(uintptr_t) + >::type = detail::nil()) { + this->~Callback(); + new (this) Callback(f); + } + + /** Attach a function object + * @param func Function object to attach + * @note The function object is limited to a single word of storage + */ + template + void attach(const volatile F f, typename detail::enable_if< + detail::is_type::value && + sizeof(F) <= sizeof(uintptr_t) + >::type = detail::nil()) { + this->~Callback(); + new (this) Callback(f); + } + /** Attach a static function with a bound pointer * @param obj Pointer to object to bind to function * @param func Static function to attach @@ -1372,6 +1596,54 @@ public: generate(function_context(func, arg)); } + /** Create a Callback with a function object + * @param func Function object to attach + * @note The function object is limited to a single word of storage + */ + template + Callback(F f, typename detail::enable_if< + detail::is_type::value && + sizeof(F) <= sizeof(uintptr_t) + >::type = detail::nil()) { + generate(f); + } + + /** Create a Callback with a function object + * @param func Function object to attach + * @note The function object is limited to a single word of storage + */ + template + Callback(const F f, typename detail::enable_if< + detail::is_type::value && + sizeof(F) <= sizeof(uintptr_t) + >::type = detail::nil()) { + generate(f); + } + + /** Create a Callback with a function object + * @param func Function object to attach + * @note The function object is limited to a single word of storage + */ + template + Callback(volatile F f, typename detail::enable_if< + detail::is_type::value && + sizeof(F) <= sizeof(uintptr_t) + >::type = detail::nil()) { + generate(f); + } + + /** Create a Callback with a function object + * @param func Function object to attach + * @note The function object is limited to a single word of storage + */ + template + Callback(const volatile F f, typename detail::enable_if< + detail::is_type::value && + sizeof(F) <= sizeof(uintptr_t) + >::type = detail::nil()) { + generate(f); + } + /** Create a Callback with a static function and bound pointer * @param obj Pointer to object to bind to function * @param func Static function to attach @@ -1612,6 +1884,58 @@ public: new (this) Callback(func, arg); } + /** Attach a function object + * @param func Function object to attach + * @note The function object is limited to a single word of storage + */ + template + void attach(F f, typename detail::enable_if< + detail::is_type::value && + sizeof(F) <= sizeof(uintptr_t) + >::type = detail::nil()) { + this->~Callback(); + new (this) Callback(f); + } + + /** Attach a function object + * @param func Function object to attach + * @note The function object is limited to a single word of storage + */ + template + void attach(const F f, typename detail::enable_if< + detail::is_type::value && + sizeof(F) <= sizeof(uintptr_t) + >::type = detail::nil()) { + this->~Callback(); + new (this) Callback(f); + } + + /** Attach a function object + * @param func Function object to attach + * @note The function object is limited to a single word of storage + */ + template + void attach(volatile F f, typename detail::enable_if< + detail::is_type::value && + sizeof(F) <= sizeof(uintptr_t) + >::type = detail::nil()) { + this->~Callback(); + new (this) Callback(f); + } + + /** Attach a function object + * @param func Function object to attach + * @note The function object is limited to a single word of storage + */ + template + void attach(const volatile F f, typename detail::enable_if< + detail::is_type::value && + sizeof(F) <= sizeof(uintptr_t) + >::type = detail::nil()) { + this->~Callback(); + new (this) Callback(f); + } + /** Attach a static function with a bound pointer * @param obj Pointer to object to bind to function * @param func Static function to attach @@ -1976,6 +2300,54 @@ public: generate(function_context(func, arg)); } + /** Create a Callback with a function object + * @param func Function object to attach + * @note The function object is limited to a single word of storage + */ + template + Callback(F f, typename detail::enable_if< + detail::is_type::value && + sizeof(F) <= sizeof(uintptr_t) + >::type = detail::nil()) { + generate(f); + } + + /** Create a Callback with a function object + * @param func Function object to attach + * @note The function object is limited to a single word of storage + */ + template + Callback(const F f, typename detail::enable_if< + detail::is_type::value && + sizeof(F) <= sizeof(uintptr_t) + >::type = detail::nil()) { + generate(f); + } + + /** Create a Callback with a function object + * @param func Function object to attach + * @note The function object is limited to a single word of storage + */ + template + Callback(volatile F f, typename detail::enable_if< + detail::is_type::value && + sizeof(F) <= sizeof(uintptr_t) + >::type = detail::nil()) { + generate(f); + } + + /** Create a Callback with a function object + * @param func Function object to attach + * @note The function object is limited to a single word of storage + */ + template + Callback(const volatile F f, typename detail::enable_if< + detail::is_type::value && + sizeof(F) <= sizeof(uintptr_t) + >::type = detail::nil()) { + generate(f); + } + /** Create a Callback with a static function and bound pointer * @param obj Pointer to object to bind to function * @param func Static function to attach @@ -2216,6 +2588,58 @@ public: new (this) Callback(func, arg); } + /** Attach a function object + * @param func Function object to attach + * @note The function object is limited to a single word of storage + */ + template + void attach(F f, typename detail::enable_if< + detail::is_type::value && + sizeof(F) <= sizeof(uintptr_t) + >::type = detail::nil()) { + this->~Callback(); + new (this) Callback(f); + } + + /** Attach a function object + * @param func Function object to attach + * @note The function object is limited to a single word of storage + */ + template + void attach(const F f, typename detail::enable_if< + detail::is_type::value && + sizeof(F) <= sizeof(uintptr_t) + >::type = detail::nil()) { + this->~Callback(); + new (this) Callback(f); + } + + /** Attach a function object + * @param func Function object to attach + * @note The function object is limited to a single word of storage + */ + template + void attach(volatile F f, typename detail::enable_if< + detail::is_type::value && + sizeof(F) <= sizeof(uintptr_t) + >::type = detail::nil()) { + this->~Callback(); + new (this) Callback(f); + } + + /** Attach a function object + * @param func Function object to attach + * @note The function object is limited to a single word of storage + */ + template + void attach(const volatile F f, typename detail::enable_if< + detail::is_type::value && + sizeof(F) <= sizeof(uintptr_t) + >::type = detail::nil()) { + this->~Callback(); + new (this) Callback(f); + } + /** Attach a static function with a bound pointer * @param obj Pointer to object to bind to function * @param func Static function to attach @@ -2580,6 +3004,54 @@ public: generate(function_context(func, arg)); } + /** Create a Callback with a function object + * @param func Function object to attach + * @note The function object is limited to a single word of storage + */ + template + Callback(F f, typename detail::enable_if< + detail::is_type::value && + sizeof(F) <= sizeof(uintptr_t) + >::type = detail::nil()) { + generate(f); + } + + /** Create a Callback with a function object + * @param func Function object to attach + * @note The function object is limited to a single word of storage + */ + template + Callback(const F f, typename detail::enable_if< + detail::is_type::value && + sizeof(F) <= sizeof(uintptr_t) + >::type = detail::nil()) { + generate(f); + } + + /** Create a Callback with a function object + * @param func Function object to attach + * @note The function object is limited to a single word of storage + */ + template + Callback(volatile F f, typename detail::enable_if< + detail::is_type::value && + sizeof(F) <= sizeof(uintptr_t) + >::type = detail::nil()) { + generate(f); + } + + /** Create a Callback with a function object + * @param func Function object to attach + * @note The function object is limited to a single word of storage + */ + template + Callback(const volatile F f, typename detail::enable_if< + detail::is_type::value && + sizeof(F) <= sizeof(uintptr_t) + >::type = detail::nil()) { + generate(f); + } + /** Create a Callback with a static function and bound pointer * @param obj Pointer to object to bind to function * @param func Static function to attach @@ -2820,6 +3292,58 @@ public: new (this) Callback(func, arg); } + /** Attach a function object + * @param func Function object to attach + * @note The function object is limited to a single word of storage + */ + template + void attach(F f, typename detail::enable_if< + detail::is_type::value && + sizeof(F) <= sizeof(uintptr_t) + >::type = detail::nil()) { + this->~Callback(); + new (this) Callback(f); + } + + /** Attach a function object + * @param func Function object to attach + * @note The function object is limited to a single word of storage + */ + template + void attach(const F f, typename detail::enable_if< + detail::is_type::value && + sizeof(F) <= sizeof(uintptr_t) + >::type = detail::nil()) { + this->~Callback(); + new (this) Callback(f); + } + + /** Attach a function object + * @param func Function object to attach + * @note The function object is limited to a single word of storage + */ + template + void attach(volatile F f, typename detail::enable_if< + detail::is_type::value && + sizeof(F) <= sizeof(uintptr_t) + >::type = detail::nil()) { + this->~Callback(); + new (this) Callback(f); + } + + /** Attach a function object + * @param func Function object to attach + * @note The function object is limited to a single word of storage + */ + template + void attach(const volatile F f, typename detail::enable_if< + detail::is_type::value && + sizeof(F) <= sizeof(uintptr_t) + >::type = detail::nil()) { + this->~Callback(); + new (this) Callback(f); + } + /** Attach a static function with a bound pointer * @param obj Pointer to object to bind to function * @param func Static function to attach @@ -3184,6 +3708,54 @@ public: generate(function_context(func, arg)); } + /** Create a Callback with a function object + * @param func Function object to attach + * @note The function object is limited to a single word of storage + */ + template + Callback(F f, typename detail::enable_if< + detail::is_type::value && + sizeof(F) <= sizeof(uintptr_t) + >::type = detail::nil()) { + generate(f); + } + + /** Create a Callback with a function object + * @param func Function object to attach + * @note The function object is limited to a single word of storage + */ + template + Callback(const F f, typename detail::enable_if< + detail::is_type::value && + sizeof(F) <= sizeof(uintptr_t) + >::type = detail::nil()) { + generate(f); + } + + /** Create a Callback with a function object + * @param func Function object to attach + * @note The function object is limited to a single word of storage + */ + template + Callback(volatile F f, typename detail::enable_if< + detail::is_type::value && + sizeof(F) <= sizeof(uintptr_t) + >::type = detail::nil()) { + generate(f); + } + + /** Create a Callback with a function object + * @param func Function object to attach + * @note The function object is limited to a single word of storage + */ + template + Callback(const volatile F f, typename detail::enable_if< + detail::is_type::value && + sizeof(F) <= sizeof(uintptr_t) + >::type = detail::nil()) { + generate(f); + } + /** Create a Callback with a static function and bound pointer * @param obj Pointer to object to bind to function * @param func Static function to attach @@ -3424,6 +3996,58 @@ public: new (this) Callback(func, arg); } + /** Attach a function object + * @param func Function object to attach + * @note The function object is limited to a single word of storage + */ + template + void attach(F f, typename detail::enable_if< + detail::is_type::value && + sizeof(F) <= sizeof(uintptr_t) + >::type = detail::nil()) { + this->~Callback(); + new (this) Callback(f); + } + + /** Attach a function object + * @param func Function object to attach + * @note The function object is limited to a single word of storage + */ + template + void attach(const F f, typename detail::enable_if< + detail::is_type::value && + sizeof(F) <= sizeof(uintptr_t) + >::type = detail::nil()) { + this->~Callback(); + new (this) Callback(f); + } + + /** Attach a function object + * @param func Function object to attach + * @note The function object is limited to a single word of storage + */ + template + void attach(volatile F f, typename detail::enable_if< + detail::is_type::value && + sizeof(F) <= sizeof(uintptr_t) + >::type = detail::nil()) { + this->~Callback(); + new (this) Callback(f); + } + + /** Attach a function object + * @param func Function object to attach + * @note The function object is limited to a single word of storage + */ + template + void attach(const volatile F f, typename detail::enable_if< + detail::is_type::value && + sizeof(F) <= sizeof(uintptr_t) + >::type = detail::nil()) { + this->~Callback(); + new (this) Callback(f); + } + /** Attach a static function with a bound pointer * @param obj Pointer to object to bind to function * @param func Static function to attach @@ -3812,6 +4436,54 @@ Callback callback(R (*func)(const volatile T*), const volatile T *arg) { return Callback(func, arg); } +/** Create a callback class with type infered from the arguments + * @param func Function object to attach + * @note The function object is limited to a single word of storage + */ +template +Callback callback(F f, typename detail::enable_if< + detail::is_type::value && + sizeof(F) <= sizeof(uintptr_t) + >::type = detail::nil()) { + return Callback(f); +} + +/** Create a callback class with type infered from the arguments + * @param func Function object to attach + * @note The function object is limited to a single word of storage + */ +template +Callback callback(const F f, typename detail::enable_if< + detail::is_type::value && + sizeof(F) <= sizeof(uintptr_t) + >::type = detail::nil()) { + return Callback(f); +} + +/** Create a callback class with type infered from the arguments + * @param func Function object to attach + * @note The function object is limited to a single word of storage + */ +template +Callback callback(volatile F f, typename detail::enable_if< + detail::is_type::value && + sizeof(F) <= sizeof(uintptr_t) + >::type = detail::nil()) { + return Callback(f); +} + +/** Create a callback class with type infered from the arguments + * @param func Function object to attach + * @note The function object is limited to a single word of storage + */ +template +Callback callback(const volatile F f, typename detail::enable_if< + detail::is_type::value && + sizeof(F) <= sizeof(uintptr_t) + >::type = detail::nil()) { + return Callback(f); +} + /** Create a callback class with type infered from the arguments * * @param obj Optional pointer to object to bind to function @@ -4085,6 +4757,54 @@ Callback callback(R (*func)(const volatile T*, A0), const volatile T *arg return Callback(func, arg); } +/** Create a callback class with type infered from the arguments + * @param func Function object to attach + * @note The function object is limited to a single word of storage + */ +template +Callback callback(F f, typename detail::enable_if< + detail::is_type::value && + sizeof(F) <= sizeof(uintptr_t) + >::type = detail::nil()) { + return Callback(f); +} + +/** Create a callback class with type infered from the arguments + * @param func Function object to attach + * @note The function object is limited to a single word of storage + */ +template +Callback callback(const F f, typename detail::enable_if< + detail::is_type::value && + sizeof(F) <= sizeof(uintptr_t) + >::type = detail::nil()) { + return Callback(f); +} + +/** Create a callback class with type infered from the arguments + * @param func Function object to attach + * @note The function object is limited to a single word of storage + */ +template +Callback callback(volatile F f, typename detail::enable_if< + detail::is_type::value && + sizeof(F) <= sizeof(uintptr_t) + >::type = detail::nil()) { + return Callback(f); +} + +/** Create a callback class with type infered from the arguments + * @param func Function object to attach + * @note The function object is limited to a single word of storage + */ +template +Callback callback(const volatile F f, typename detail::enable_if< + detail::is_type::value && + sizeof(F) <= sizeof(uintptr_t) + >::type = detail::nil()) { + return Callback(f); +} + /** Create a callback class with type infered from the arguments * * @param obj Optional pointer to object to bind to function @@ -4358,6 +5078,54 @@ Callback callback(R (*func)(const volatile T*, A0, A1), const volatil return Callback(func, arg); } +/** Create a callback class with type infered from the arguments + * @param func Function object to attach + * @note The function object is limited to a single word of storage + */ +template +Callback callback(F f, typename detail::enable_if< + detail::is_type::value && + sizeof(F) <= sizeof(uintptr_t) + >::type = detail::nil()) { + return Callback(f); +} + +/** Create a callback class with type infered from the arguments + * @param func Function object to attach + * @note The function object is limited to a single word of storage + */ +template +Callback callback(const F f, typename detail::enable_if< + detail::is_type::value && + sizeof(F) <= sizeof(uintptr_t) + >::type = detail::nil()) { + return Callback(f); +} + +/** Create a callback class with type infered from the arguments + * @param func Function object to attach + * @note The function object is limited to a single word of storage + */ +template +Callback callback(volatile F f, typename detail::enable_if< + detail::is_type::value && + sizeof(F) <= sizeof(uintptr_t) + >::type = detail::nil()) { + return Callback(f); +} + +/** Create a callback class with type infered from the arguments + * @param func Function object to attach + * @note The function object is limited to a single word of storage + */ +template +Callback callback(const volatile F f, typename detail::enable_if< + detail::is_type::value && + sizeof(F) <= sizeof(uintptr_t) + >::type = detail::nil()) { + return Callback(f); +} + /** Create a callback class with type infered from the arguments * * @param obj Optional pointer to object to bind to function @@ -4631,6 +5399,54 @@ Callback callback(R (*func)(const volatile T*, A0, A1, A2), const return Callback(func, arg); } +/** Create a callback class with type infered from the arguments + * @param func Function object to attach + * @note The function object is limited to a single word of storage + */ +template +Callback callback(F f, typename detail::enable_if< + detail::is_type::value && + sizeof(F) <= sizeof(uintptr_t) + >::type = detail::nil()) { + return Callback(f); +} + +/** Create a callback class with type infered from the arguments + * @param func Function object to attach + * @note The function object is limited to a single word of storage + */ +template +Callback callback(const F f, typename detail::enable_if< + detail::is_type::value && + sizeof(F) <= sizeof(uintptr_t) + >::type = detail::nil()) { + return Callback(f); +} + +/** Create a callback class with type infered from the arguments + * @param func Function object to attach + * @note The function object is limited to a single word of storage + */ +template +Callback callback(volatile F f, typename detail::enable_if< + detail::is_type::value && + sizeof(F) <= sizeof(uintptr_t) + >::type = detail::nil()) { + return Callback(f); +} + +/** Create a callback class with type infered from the arguments + * @param func Function object to attach + * @note The function object is limited to a single word of storage + */ +template +Callback callback(const volatile F f, typename detail::enable_if< + detail::is_type::value && + sizeof(F) <= sizeof(uintptr_t) + >::type = detail::nil()) { + return Callback(f); +} + /** Create a callback class with type infered from the arguments * * @param obj Optional pointer to object to bind to function @@ -4904,6 +5720,54 @@ Callback callback(R (*func)(const volatile T*, A0, A1, A2, A3 return Callback(func, arg); } +/** Create a callback class with type infered from the arguments + * @param func Function object to attach + * @note The function object is limited to a single word of storage + */ +template +Callback callback(F f, typename detail::enable_if< + detail::is_type::value && + sizeof(F) <= sizeof(uintptr_t) + >::type = detail::nil()) { + return Callback(f); +} + +/** Create a callback class with type infered from the arguments + * @param func Function object to attach + * @note The function object is limited to a single word of storage + */ +template +Callback callback(const F f, typename detail::enable_if< + detail::is_type::value && + sizeof(F) <= sizeof(uintptr_t) + >::type = detail::nil()) { + return Callback(f); +} + +/** Create a callback class with type infered from the arguments + * @param func Function object to attach + * @note The function object is limited to a single word of storage + */ +template +Callback callback(volatile F f, typename detail::enable_if< + detail::is_type::value && + sizeof(F) <= sizeof(uintptr_t) + >::type = detail::nil()) { + return Callback(f); +} + +/** Create a callback class with type infered from the arguments + * @param func Function object to attach + * @note The function object is limited to a single word of storage + */ +template +Callback callback(const volatile F f, typename detail::enable_if< + detail::is_type::value && + sizeof(F) <= sizeof(uintptr_t) + >::type = detail::nil()) { + return Callback(f); +} + /** Create a callback class with type infered from the arguments * * @param obj Optional pointer to object to bind to function @@ -5177,6 +6041,54 @@ Callback callback(R (*func)(const volatile T*, A0, A1, A2 return Callback(func, arg); } +/** Create a callback class with type infered from the arguments + * @param func Function object to attach + * @note The function object is limited to a single word of storage + */ +template +Callback callback(F f, typename detail::enable_if< + detail::is_type::value && + sizeof(F) <= sizeof(uintptr_t) + >::type = detail::nil()) { + return Callback(f); +} + +/** Create a callback class with type infered from the arguments + * @param func Function object to attach + * @note The function object is limited to a single word of storage + */ +template +Callback callback(const F f, typename detail::enable_if< + detail::is_type::value && + sizeof(F) <= sizeof(uintptr_t) + >::type = detail::nil()) { + return Callback(f); +} + +/** Create a callback class with type infered from the arguments + * @param func Function object to attach + * @note The function object is limited to a single word of storage + */ +template +Callback callback(volatile F f, typename detail::enable_if< + detail::is_type::value && + sizeof(F) <= sizeof(uintptr_t) + >::type = detail::nil()) { + return Callback(f); +} + +/** Create a callback class with type infered from the arguments + * @param func Function object to attach + * @note The function object is limited to a single word of storage + */ +template +Callback callback(const volatile F f, typename detail::enable_if< + detail::is_type::value && + sizeof(F) <= sizeof(uintptr_t) + >::type = detail::nil()) { + return Callback(f); +} + /** Create a callback class with type infered from the arguments * * @param obj Optional pointer to object to bind to function