Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Constrain context argument types
Previous commit just 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 2ff14df
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 34 deletions.
32 changes: 16 additions & 16 deletions events/Event.h
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
47 changes: 29 additions & 18 deletions events/EventQueue.h
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 @@ -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 2ff14df

Please sign in to comment.