Skip to content

Commit

Permalink
Constrain context argument types
Browse files Browse the repository at this point in the history
Previous commit just replaced instances of "class B0, class B1, class
C0, class C1" with "class... BoundArgs, class... ContextArgs".

This loses the requirement that the numbers must match.

Now, the original code was also inconsistent as to whether it used
separate types for the target function and the call input parameters.
Some forms just used B0, B1 as parameters rather than separate C0, C1.

I believe the separate parameters would have been primarily to avoid
template deduction confusion - eg if int was supplied to a B0 parameter
but the function took char as B0, there would be an ambiguity. But the
fix didn't seem to be fully applied.

Rewritten all templates parameterising on function pointer type and
input arguments so that they use `type_identity_t<BoundArgTs>...` as
input parameters to match the target function.

This has the subtle effect that any conversion happens at invocation,
before storing to the context, rather than when the context calls the
target.
  • Loading branch information
kjbracey committed Jun 25, 2019
1 parent 4d9148a commit 62062ef
Show file tree
Hide file tree
Showing 2 changed files with 57 additions and 46 deletions.
32 changes: 16 additions & 16 deletions events/Event.h
Original file line number Diff line number Diff line change
Expand Up @@ -252,28 +252,28 @@ class Event<void(ArgTs...)> {
* @see Event::Event
*/
template <typename T, typename R, typename... BoundArgTs>
Event(EventQueue *q, T *obj, R(T::*method)(BoundArgTs..., ArgTs...), BoundArgTs... context_args) :
Event(EventQueue *q, T *obj, R(T::*method)(BoundArgTs..., ArgTs...), impl::type_identity_t<BoundArgTs>... context_args) :
Event(q, mbed::callback(obj, method), context_args...) { }

/** Create an event
* @see Event::Event
*/
template <typename T, typename R, typename... BoundArgTs>
Event(EventQueue *q, const T *obj, R(T::*method)(BoundArgTs..., ArgTs...) const, BoundArgTs... context_args) :
Event(EventQueue *q, const T *obj, R(T::*method)(BoundArgTs..., ArgTs...) const, impl::type_identity_t<BoundArgTs>... context_args) :
Event(q, mbed::callback(obj, method), context_args...) { }

/** Create an event
* @see Event::Event
*/
template <typename T, typename R, typename... BoundArgTs>
Event(EventQueue *q, volatile T *obj, R(T::*method)(BoundArgTs..., ArgTs...) volatile, BoundArgTs... context_args) :
Event(EventQueue *q, volatile T *obj, R(T::*method)(BoundArgTs..., ArgTs...) volatile, impl::type_identity_t<BoundArgTs>... context_args) :
Event(q, mbed::callback(obj, method), context_args...) { }

/** Create an event
* @see Event::Event
*/
template <typename T, typename R, typename... BoundArgTs>
Event(EventQueue *q, const volatile T *obj, R(T::*method)(BoundArgTs..., ArgTs...) const volatile, BoundArgTs... context_args) :
Event(EventQueue *q, const volatile T *obj, R(T::*method)(BoundArgTs..., ArgTs...) const volatile, impl::type_identity_t<BoundArgTs>... context_args) :
Event(q, mbed::callback(obj, method), context_args...) { }
};

Expand All @@ -283,38 +283,38 @@ class Event<void(ArgTs...)> {

// Convenience functions declared here to avoid cyclic
// dependency between Event and EventQueue
template <typename R, typename... BoundArgTs, typename... ContextArgTs, typename... ArgTs>
Event<void(ArgTs...)> EventQueue::event(R(*func)(BoundArgTs..., ArgTs...), ContextArgTs... context_args)
template <typename R, typename... BoundArgTs, typename... ArgTs>
Event<void(ArgTs...)> EventQueue::event(R(*func)(BoundArgTs..., ArgTs...), impl::type_identity_t<BoundArgTs>... context_args)
{
return Event<void(ArgTs...)>(this, func, context_args...);
}

template <typename T, typename R, typename... BoundArgTs, typename... ContextArgTs, typename... ArgTs>
Event<void(ArgTs...)> EventQueue::event(T *obj, R(T::*method)(BoundArgTs..., ArgTs...), ContextArgTs... context_args)
template <typename T, typename R, typename... BoundArgTs, typename... ArgTs>
Event<void(ArgTs...)> EventQueue::event(T *obj, R(T::*method)(BoundArgTs..., ArgTs...), impl::type_identity_t<BoundArgTs>... context_args)
{
return Event<void(ArgTs...)>(this, mbed::callback(obj, method), context_args...);
}

template <typename T, typename R, typename... BoundArgTs, typename... ContextArgTs, typename... ArgTs>
Event<void(ArgTs...)> EventQueue::event(const T *obj, R(T::*method)(BoundArgTs..., ArgTs...) const, ContextArgTs... context_args)
template <typename T, typename R, typename... BoundArgTs, typename... ArgTs>
Event<void(ArgTs...)> EventQueue::event(const T *obj, R(T::*method)(BoundArgTs..., ArgTs...) const, impl::type_identity_t<BoundArgTs>... context_args)
{
return Event<void(ArgTs...)>(this, mbed::callback(obj, method), context_args...);
}

template <typename T, typename R, typename... BoundArgTs, typename... ContextArgTs, typename... ArgTs>
Event<void(ArgTs...)> EventQueue::event(volatile T *obj, R(T::*method)(BoundArgTs..., ArgTs...) volatile, ContextArgTs... context_args)
template <typename T, typename R, typename... BoundArgTs, typename... ArgTs>
Event<void(ArgTs...)> EventQueue::event(volatile T *obj, R(T::*method)(BoundArgTs..., ArgTs...) volatile, impl::type_identity_t<BoundArgTs>... context_args)
{
return Event<void(ArgTs...)>(this, mbed::callback(obj, method), context_args...);
}

template <typename T, typename R, typename... BoundArgTs, typename... ContextArgTs, typename... ArgTs>
Event<void(ArgTs...)> EventQueue::event(const volatile T *obj, R(T::*method)(BoundArgTs..., ArgTs...) const volatile, ContextArgTs... context_args)
template <typename T, typename R, typename... BoundArgTs, typename... ArgTs>
Event<void(ArgTs...)> EventQueue::event(const volatile T *obj, R(T::*method)(BoundArgTs..., ArgTs...) const volatile, impl::type_identity_t<BoundArgTs>... context_args)
{
return Event<void(ArgTs...)>(this, mbed::callback(obj, method), context_args...);
}

template <typename R, typename... BoundArgTs, typename... ContextArgTs, typename... ArgTs>
Event<void(ArgTs...)> EventQueue::event(mbed::Callback<R(BoundArgTs..., ArgTs...)> cb, ContextArgTs... context_args)
template <typename R, typename... BoundArgTs, typename... ArgTs>
Event<void(ArgTs...)> EventQueue::event(mbed::Callback<R(BoundArgTs..., ArgTs...)> cb, impl::type_identity_t<BoundArgTs>... context_args)
{
return Event<void(ArgTs...)>(this, cb, context_args...);
}
Expand Down
71 changes: 41 additions & 30 deletions events/EventQueue.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,17 @@ namespace events {
*/
#define EVENTS_QUEUE_SIZE (32*EVENTS_EVENT_SIZE)

namespace impl {
/* C++20 type identity */
template<typename T>
struct type_identity {
using type = T;
};

template <typename T>
using type_identity_t = typename type_identity<T>::type;
}

// Predeclared classes
template <typename F>
class Event;
Expand Down Expand Up @@ -498,8 +509,8 @@ class EventQueue : private mbed::NonCopyable<EventQueue> {
*/
// AStyle ignore, not handling correctly below
// *INDENT-OFF*
template <typename R, typename ...BoundArgs, typename ...ContextArgs, typename ...Args>
Event<void(Args...)> event(R (*func)(BoundArgs..., Args...), ContextArgs ...context_args);
template <typename R, typename ...BoundArgs, typename ...Args>
Event<void(Args...)> event(R (*func)(BoundArgs..., Args...), BoundArgs ...context_args);
// *INDENT-ON*

/** Creates an event bound to the event queue
Expand Down Expand Up @@ -546,8 +557,8 @@ class EventQueue : private mbed::NonCopyable<EventQueue> {
*/
// AStyle ignore, not handling correctly below
// *INDENT-OFF*
template <typename T, typename R, typename ...BoundArgs, typename ...ContextArgs, typename ...Args>
Event<void(Args...)> event(T *obj, R (T::*method)(BoundArgs..., Args...), ContextArgs ...context_args);
template <typename T, typename R, typename ...BoundArgs, typename ...Args>
Event<void(Args...)> event(T *obj, R (T::*method)(BoundArgs..., Args...), BoundArgs ...context_args);
// *INDENT-ON*

/** Creates an event bound to the event queue
Expand Down Expand Up @@ -585,8 +596,8 @@ class EventQueue : private mbed::NonCopyable<EventQueue> {
* }
* @endcode
*/
template <typename R, typename ...BoundArgs, typename ...ContextArgs, typename ...Args>
Event<void(Args...)> event(mbed::Callback<R(BoundArgs..., Args...)> cb, ContextArgs ...context_args);
template <typename R, typename ...BoundArgs, typename ...Args>
Event<void(Args...)> event(mbed::Callback<R(BoundArgs..., Args...)> cb, BoundArgs ...context_args);

#else

Expand Down Expand Up @@ -650,7 +661,7 @@ class EventQueue : private mbed::NonCopyable<EventQueue> {
* @see EventQueue::call
*/
template <typename T, typename R, typename... ArgTs>
int call(T *obj, R(T::*method)(ArgTs...), ArgTs... args)
int call(T *obj, R(T::*method)(ArgTs...), impl::type_identity_t<ArgTs>... args)
{
return call(mbed::callback(obj, method), args...);
}
Expand All @@ -659,7 +670,7 @@ class EventQueue : private mbed::NonCopyable<EventQueue> {
* @see EventQueue::call
*/
template <typename T, typename R, typename... ArgTs>
int call(const T *obj, R(T::*method)(ArgTs...) const, ArgTs... args)
int call(const T *obj, R(T::*method)(ArgTs...) const, impl::type_identity_t<ArgTs>... args)
{
return call(mbed::callback(obj, method), args...);
}
Expand All @@ -668,7 +679,7 @@ class EventQueue : private mbed::NonCopyable<EventQueue> {
* @see EventQueue::call
*/
template <typename T, typename R, typename... ArgTs>
int call(volatile T *obj, R(T::*method)(ArgTs...) volatile, ArgTs... args)
int call(volatile T *obj, R(T::*method)(ArgTs...) volatile, impl::type_identity_t<ArgTs>... args)
{
return call(mbed::callback(obj, method), args...);
}
Expand All @@ -677,7 +688,7 @@ class EventQueue : private mbed::NonCopyable<EventQueue> {
* @see EventQueue::call
*/
template <typename T, typename R, typename... ArgTs>
int call(const volatile T *obj, R(T::*method)(ArgTs...) const volatile, ArgTs... args)
int call(const volatile T *obj, R(T::*method)(ArgTs...) const volatile, impl::type_identity_t<ArgTs>... args)
{
return call(mbed::callback(obj, method), args...);
}
Expand Down Expand Up @@ -726,7 +737,7 @@ class EventQueue : private mbed::NonCopyable<EventQueue> {
* @see EventQueue::call_in
*/
template <typename T, typename R, typename... ArgTs>
int call_in(int ms, T *obj, R(T::*method)(ArgTs...), ArgTs... args)
int call_in(int ms, T *obj, R(T::*method)(ArgTs...), impl::type_identity_t<ArgTs>... args)
{
return call_in(ms, mbed::callback(obj, method), args...);
}
Expand All @@ -735,7 +746,7 @@ class EventQueue : private mbed::NonCopyable<EventQueue> {
* @see EventQueue::call_in
*/
template <typename T, typename R, typename... ArgTs>
int call_in(int ms, const T *obj, R(T::*method)(ArgTs...) const, ArgTs... args)
int call_in(int ms, const T *obj, R(T::*method)(ArgTs...) const, impl::type_identity_t<ArgTs>... args)
{
return call_in(ms, mbed::callback(obj, method), args...);
}
Expand All @@ -744,7 +755,7 @@ class EventQueue : private mbed::NonCopyable<EventQueue> {
* @see EventQueue::call_in
*/
template <typename T, typename R, typename... ArgTs>
int call_in(int ms, volatile T *obj, R(T::*method)(ArgTs...) volatile, ArgTs... args)
int call_in(int ms, volatile T *obj, R(T::*method)(ArgTs...) volatile, impl::type_identity_t<ArgTs>... args)
{
return call_in(ms, mbed::callback(obj, method), args...);
}
Expand All @@ -753,7 +764,7 @@ class EventQueue : private mbed::NonCopyable<EventQueue> {
* @see EventQueue::call_in
*/
template <typename T, typename R, typename... ArgTs>
int call_in(int ms, const volatile T *obj, R(T::*method)(ArgTs...) const volatile, ArgTs... args)
int call_in(int ms, const volatile T *obj, R(T::*method)(ArgTs...) const volatile, impl::type_identity_t<ArgTs>... args)
{
return call_in(ms, mbed::callback(obj, method), args...);
}
Expand Down Expand Up @@ -806,7 +817,7 @@ class EventQueue : private mbed::NonCopyable<EventQueue> {
* @see EventQueue::call_every
*/
template <typename T, typename R, typename... ArgTs>
int call_every(int ms, T *obj, R(T::*method)(ArgTs...), ArgTs... args)
int call_every(int ms, T *obj, R(T::*method)(ArgTs...), impl::type_identity_t<ArgTs>... args)
{
return call_every(ms, mbed::callback(obj, method), args...);
}
Expand All @@ -815,7 +826,7 @@ class EventQueue : private mbed::NonCopyable<EventQueue> {
* @see EventQueue::call_every
*/
template <typename T, typename R, typename... ArgTs>
int call_every(int ms, const T *obj, R(T::*method)(ArgTs...) const, ArgTs... args)
int call_every(int ms, const T *obj, R(T::*method)(ArgTs...) const, impl::type_identity_t<ArgTs>... args)
{
return call_every(ms, mbed::callback(obj, method), args...);
}
Expand All @@ -824,7 +835,7 @@ class EventQueue : private mbed::NonCopyable<EventQueue> {
* @see EventQueue::call_every
*/
template <typename T, typename R, typename... ArgTs>
int call_every(int ms, volatile T *obj, R(T::*method)(ArgTs...) volatile, ArgTs... args)
int call_every(int ms, volatile T *obj, R(T::*method)(ArgTs...) volatile, impl::type_identity_t<ArgTs>... args)
{
return call_every(ms, mbed::callback(obj, method), args...);
}
Expand All @@ -833,7 +844,7 @@ class EventQueue : private mbed::NonCopyable<EventQueue> {
* @see EventQueue::call_every
*/
template <typename T, typename R, typename... ArgTs>
int call_every(int ms, const volatile T *obj, R(T::*method)(ArgTs...) const volatile, ArgTs... args)
int call_every(int ms, const volatile T *obj, R(T::*method)(ArgTs...) const volatile, impl::type_identity_t<ArgTs>... args)
{
return call_every(ms, mbed::callback(obj, method), args...);
}
Expand All @@ -847,38 +858,38 @@ class EventQueue : private mbed::NonCopyable<EventQueue> {
* @param func Function to execute when the event is dispatched
* @return Event that will dispatch on the specific queue
*/
template <typename R, typename... BoundArgTs, typename... ContextArgTs, typename... ArgTs>
Event<void(ArgTs...)> event(R(*func)(BoundArgTs..., ArgTs...), ContextArgTs... context_args);
template <typename R, typename... BoundArgTs, typename... ArgTs>
Event<void(ArgTs...)> event(R(*func)(BoundArgTs..., ArgTs...), impl::type_identity_t<BoundArgTs>... context_args);

/** Creates an event bound to the event queue
* @see EventQueue::event
*/
template <typename T, typename R, typename... BoundArgTs, typename... ContextArgTs, typename... ArgTs>
Event<void(ArgTs...)> event(T *obj, R(T::*method)(BoundArgTs..., ArgTs...), ContextArgTs... context_args);
template <typename T, typename R, typename... BoundArgTs, typename... ArgTs>
Event<void(ArgTs...)> event(T *obj, R(T::*method)(BoundArgTs..., ArgTs...), impl::type_identity_t<BoundArgTs>... context_args);

/** Creates an event bound to the event queue
* @see EventQueue::event
*/
template <typename T, typename R, typename... BoundArgTs, typename... ContextArgTs, typename... ArgTs>
Event<void(ArgTs...)> event(const T *obj, R(T::*method)(BoundArgTs..., ArgTs...) const, ContextArgTs... context_args);
template <typename T, typename R, typename... BoundArgTs, typename... ArgTs>
Event<void(ArgTs...)> event(const T *obj, R(T::*method)(BoundArgTs..., ArgTs...) const, impl::type_identity_t<BoundArgTs>... context_args);

/** Creates an event bound to the event queue
* @see EventQueue::event
*/
template <typename T, typename R, typename... BoundArgTs, typename... ContextArgTs, typename... ArgTs>
Event<void(ArgTs...)> event(volatile T *obj, R(T::*method)(BoundArgTs..., ArgTs...) volatile, ContextArgTs... context_args);
template <typename T, typename R, typename... BoundArgTs, typename... ArgTs>
Event<void(ArgTs...)> event(volatile T *obj, R(T::*method)(BoundArgTs..., ArgTs...) volatile, impl::type_identity_t<BoundArgTs>... context_args);

/** Creates an event bound to the event queue
* @see EventQueue::event
*/
template <typename T, typename R, typename... BoundArgTs, typename... ContextArgTs, typename... ArgTs>
Event<void(ArgTs...)> event(const volatile T *obj, R(T::*method)(BoundArgTs..., ArgTs...) const volatile, ContextArgTs... context_args);
template <typename T, typename R, typename... BoundArgTs, typename... ArgTs>
Event<void(ArgTs...)> event(const volatile T *obj, R(T::*method)(BoundArgTs..., ArgTs...) const volatile, impl::type_identity_t<BoundArgTs>... context_args);

/** Creates an event bound to the event queue
* @see EventQueue::event
*/
template <typename R, typename... BoundArgTs, typename... ContextArgTs, typename... ArgTs>
Event<void(ArgTs...)> event(mbed::Callback<R(BoundArgTs..., ArgTs...)> cb, ContextArgTs... context_args);
template <typename R, typename... BoundArgTs, typename... ArgTs>
Event<void(ArgTs...)> event(mbed::Callback<R(BoundArgTs..., ArgTs...)> cb, impl::type_identity_t<BoundArgTs>... context_args);
#endif

protected:
Expand Down

0 comments on commit 62062ef

Please sign in to comment.