Skip to content

Commit 62062ef

Browse files
committed
Constrain context argument types
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.
1 parent 4d9148a commit 62062ef

File tree

2 files changed

+57
-46
lines changed

2 files changed

+57
-46
lines changed

events/Event.h

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -252,28 +252,28 @@ class Event<void(ArgTs...)> {
252252
* @see Event::Event
253253
*/
254254
template <typename T, typename R, typename... BoundArgTs>
255-
Event(EventQueue *q, T *obj, R(T::*method)(BoundArgTs..., ArgTs...), BoundArgTs... context_args) :
255+
Event(EventQueue *q, T *obj, R(T::*method)(BoundArgTs..., ArgTs...), impl::type_identity_t<BoundArgTs>... context_args) :
256256
Event(q, mbed::callback(obj, method), context_args...) { }
257257

258258
/** Create an event
259259
* @see Event::Event
260260
*/
261261
template <typename T, typename R, typename... BoundArgTs>
262-
Event(EventQueue *q, const T *obj, R(T::*method)(BoundArgTs..., ArgTs...) const, BoundArgTs... context_args) :
262+
Event(EventQueue *q, const T *obj, R(T::*method)(BoundArgTs..., ArgTs...) const, impl::type_identity_t<BoundArgTs>... context_args) :
263263
Event(q, mbed::callback(obj, method), context_args...) { }
264264

265265
/** Create an event
266266
* @see Event::Event
267267
*/
268268
template <typename T, typename R, typename... BoundArgTs>
269-
Event(EventQueue *q, volatile T *obj, R(T::*method)(BoundArgTs..., ArgTs...) volatile, BoundArgTs... context_args) :
269+
Event(EventQueue *q, volatile T *obj, R(T::*method)(BoundArgTs..., ArgTs...) volatile, impl::type_identity_t<BoundArgTs>... context_args) :
270270
Event(q, mbed::callback(obj, method), context_args...) { }
271271

272272
/** Create an event
273273
* @see Event::Event
274274
*/
275275
template <typename T, typename R, typename... BoundArgTs>
276-
Event(EventQueue *q, const volatile T *obj, R(T::*method)(BoundArgTs..., ArgTs...) const volatile, BoundArgTs... context_args) :
276+
Event(EventQueue *q, const volatile T *obj, R(T::*method)(BoundArgTs..., ArgTs...) const volatile, impl::type_identity_t<BoundArgTs>... context_args) :
277277
Event(q, mbed::callback(obj, method), context_args...) { }
278278
};
279279

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

284284
// Convenience functions declared here to avoid cyclic
285285
// dependency between Event and EventQueue
286-
template <typename R, typename... BoundArgTs, typename... ContextArgTs, typename... ArgTs>
287-
Event<void(ArgTs...)> EventQueue::event(R(*func)(BoundArgTs..., ArgTs...), ContextArgTs... context_args)
286+
template <typename R, typename... BoundArgTs, typename... ArgTs>
287+
Event<void(ArgTs...)> EventQueue::event(R(*func)(BoundArgTs..., ArgTs...), impl::type_identity_t<BoundArgTs>... context_args)
288288
{
289289
return Event<void(ArgTs...)>(this, func, context_args...);
290290
}
291291

292-
template <typename T, typename R, typename... BoundArgTs, typename... ContextArgTs, typename... ArgTs>
293-
Event<void(ArgTs...)> EventQueue::event(T *obj, R(T::*method)(BoundArgTs..., ArgTs...), ContextArgTs... context_args)
292+
template <typename T, typename R, typename... BoundArgTs, typename... ArgTs>
293+
Event<void(ArgTs...)> EventQueue::event(T *obj, R(T::*method)(BoundArgTs..., ArgTs...), impl::type_identity_t<BoundArgTs>... context_args)
294294
{
295295
return Event<void(ArgTs...)>(this, mbed::callback(obj, method), context_args...);
296296
}
297297

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

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

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

316-
template <typename R, typename... BoundArgTs, typename... ContextArgTs, typename... ArgTs>
317-
Event<void(ArgTs...)> EventQueue::event(mbed::Callback<R(BoundArgTs..., ArgTs...)> cb, ContextArgTs... context_args)
316+
template <typename R, typename... BoundArgTs, typename... ArgTs>
317+
Event<void(ArgTs...)> EventQueue::event(mbed::Callback<R(BoundArgTs..., ArgTs...)> cb, impl::type_identity_t<BoundArgTs>... context_args)
318318
{
319319
return Event<void(ArgTs...)>(this, cb, context_args...);
320320
}

events/EventQueue.h

Lines changed: 41 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,17 @@ namespace events {
3939
*/
4040
#define EVENTS_QUEUE_SIZE (32*EVENTS_EVENT_SIZE)
4141

42+
namespace impl {
43+
/* C++20 type identity */
44+
template<typename T>
45+
struct type_identity {
46+
using type = T;
47+
};
48+
49+
template <typename T>
50+
using type_identity_t = typename type_identity<T>::type;
51+
}
52+
4253
// Predeclared classes
4354
template <typename F>
4455
class Event;
@@ -498,8 +509,8 @@ class EventQueue : private mbed::NonCopyable<EventQueue> {
498509
*/
499510
// AStyle ignore, not handling correctly below
500511
// *INDENT-OFF*
501-
template <typename R, typename ...BoundArgs, typename ...ContextArgs, typename ...Args>
502-
Event<void(Args...)> event(R (*func)(BoundArgs..., Args...), ContextArgs ...context_args);
512+
template <typename R, typename ...BoundArgs, typename ...Args>
513+
Event<void(Args...)> event(R (*func)(BoundArgs..., Args...), BoundArgs ...context_args);
503514
// *INDENT-ON*
504515

505516
/** Creates an event bound to the event queue
@@ -546,8 +557,8 @@ class EventQueue : private mbed::NonCopyable<EventQueue> {
546557
*/
547558
// AStyle ignore, not handling correctly below
548559
// *INDENT-OFF*
549-
template <typename T, typename R, typename ...BoundArgs, typename ...ContextArgs, typename ...Args>
550-
Event<void(Args...)> event(T *obj, R (T::*method)(BoundArgs..., Args...), ContextArgs ...context_args);
560+
template <typename T, typename R, typename ...BoundArgs, typename ...Args>
561+
Event<void(Args...)> event(T *obj, R (T::*method)(BoundArgs..., Args...), BoundArgs ...context_args);
551562
// *INDENT-ON*
552563

553564
/** Creates an event bound to the event queue
@@ -585,8 +596,8 @@ class EventQueue : private mbed::NonCopyable<EventQueue> {
585596
* }
586597
* @endcode
587598
*/
588-
template <typename R, typename ...BoundArgs, typename ...ContextArgs, typename ...Args>
589-
Event<void(Args...)> event(mbed::Callback<R(BoundArgs..., Args...)> cb, ContextArgs ...context_args);
599+
template <typename R, typename ...BoundArgs, typename ...Args>
600+
Event<void(Args...)> event(mbed::Callback<R(BoundArgs..., Args...)> cb, BoundArgs ...context_args);
590601

591602
#else
592603

@@ -650,7 +661,7 @@ class EventQueue : private mbed::NonCopyable<EventQueue> {
650661
* @see EventQueue::call
651662
*/
652663
template <typename T, typename R, typename... ArgTs>
653-
int call(T *obj, R(T::*method)(ArgTs...), ArgTs... args)
664+
int call(T *obj, R(T::*method)(ArgTs...), impl::type_identity_t<ArgTs>... args)
654665
{
655666
return call(mbed::callback(obj, method), args...);
656667
}
@@ -659,7 +670,7 @@ class EventQueue : private mbed::NonCopyable<EventQueue> {
659670
* @see EventQueue::call
660671
*/
661672
template <typename T, typename R, typename... ArgTs>
662-
int call(const T *obj, R(T::*method)(ArgTs...) const, ArgTs... args)
673+
int call(const T *obj, R(T::*method)(ArgTs...) const, impl::type_identity_t<ArgTs>... args)
663674
{
664675
return call(mbed::callback(obj, method), args...);
665676
}
@@ -668,7 +679,7 @@ class EventQueue : private mbed::NonCopyable<EventQueue> {
668679
* @see EventQueue::call
669680
*/
670681
template <typename T, typename R, typename... ArgTs>
671-
int call(volatile T *obj, R(T::*method)(ArgTs...) volatile, ArgTs... args)
682+
int call(volatile T *obj, R(T::*method)(ArgTs...) volatile, impl::type_identity_t<ArgTs>... args)
672683
{
673684
return call(mbed::callback(obj, method), args...);
674685
}
@@ -677,7 +688,7 @@ class EventQueue : private mbed::NonCopyable<EventQueue> {
677688
* @see EventQueue::call
678689
*/
679690
template <typename T, typename R, typename... ArgTs>
680-
int call(const volatile T *obj, R(T::*method)(ArgTs...) const volatile, ArgTs... args)
691+
int call(const volatile T *obj, R(T::*method)(ArgTs...) const volatile, impl::type_identity_t<ArgTs>... args)
681692
{
682693
return call(mbed::callback(obj, method), args...);
683694
}
@@ -726,7 +737,7 @@ class EventQueue : private mbed::NonCopyable<EventQueue> {
726737
* @see EventQueue::call_in
727738
*/
728739
template <typename T, typename R, typename... ArgTs>
729-
int call_in(int ms, T *obj, R(T::*method)(ArgTs...), ArgTs... args)
740+
int call_in(int ms, T *obj, R(T::*method)(ArgTs...), impl::type_identity_t<ArgTs>... args)
730741
{
731742
return call_in(ms, mbed::callback(obj, method), args...);
732743
}
@@ -735,7 +746,7 @@ class EventQueue : private mbed::NonCopyable<EventQueue> {
735746
* @see EventQueue::call_in
736747
*/
737748
template <typename T, typename R, typename... ArgTs>
738-
int call_in(int ms, const T *obj, R(T::*method)(ArgTs...) const, ArgTs... args)
749+
int call_in(int ms, const T *obj, R(T::*method)(ArgTs...) const, impl::type_identity_t<ArgTs>... args)
739750
{
740751
return call_in(ms, mbed::callback(obj, method), args...);
741752
}
@@ -744,7 +755,7 @@ class EventQueue : private mbed::NonCopyable<EventQueue> {
744755
* @see EventQueue::call_in
745756
*/
746757
template <typename T, typename R, typename... ArgTs>
747-
int call_in(int ms, volatile T *obj, R(T::*method)(ArgTs...) volatile, ArgTs... args)
758+
int call_in(int ms, volatile T *obj, R(T::*method)(ArgTs...) volatile, impl::type_identity_t<ArgTs>... args)
748759
{
749760
return call_in(ms, mbed::callback(obj, method), args...);
750761
}
@@ -753,7 +764,7 @@ class EventQueue : private mbed::NonCopyable<EventQueue> {
753764
* @see EventQueue::call_in
754765
*/
755766
template <typename T, typename R, typename... ArgTs>
756-
int call_in(int ms, const volatile T *obj, R(T::*method)(ArgTs...) const volatile, ArgTs... args)
767+
int call_in(int ms, const volatile T *obj, R(T::*method)(ArgTs...) const volatile, impl::type_identity_t<ArgTs>... args)
757768
{
758769
return call_in(ms, mbed::callback(obj, method), args...);
759770
}
@@ -806,7 +817,7 @@ class EventQueue : private mbed::NonCopyable<EventQueue> {
806817
* @see EventQueue::call_every
807818
*/
808819
template <typename T, typename R, typename... ArgTs>
809-
int call_every(int ms, T *obj, R(T::*method)(ArgTs...), ArgTs... args)
820+
int call_every(int ms, T *obj, R(T::*method)(ArgTs...), impl::type_identity_t<ArgTs>... args)
810821
{
811822
return call_every(ms, mbed::callback(obj, method), args...);
812823
}
@@ -815,7 +826,7 @@ class EventQueue : private mbed::NonCopyable<EventQueue> {
815826
* @see EventQueue::call_every
816827
*/
817828
template <typename T, typename R, typename... ArgTs>
818-
int call_every(int ms, const T *obj, R(T::*method)(ArgTs...) const, ArgTs... args)
829+
int call_every(int ms, const T *obj, R(T::*method)(ArgTs...) const, impl::type_identity_t<ArgTs>... args)
819830
{
820831
return call_every(ms, mbed::callback(obj, method), args...);
821832
}
@@ -824,7 +835,7 @@ class EventQueue : private mbed::NonCopyable<EventQueue> {
824835
* @see EventQueue::call_every
825836
*/
826837
template <typename T, typename R, typename... ArgTs>
827-
int call_every(int ms, volatile T *obj, R(T::*method)(ArgTs...) volatile, ArgTs... args)
838+
int call_every(int ms, volatile T *obj, R(T::*method)(ArgTs...) volatile, impl::type_identity_t<ArgTs>... args)
828839
{
829840
return call_every(ms, mbed::callback(obj, method), args...);
830841
}
@@ -833,7 +844,7 @@ class EventQueue : private mbed::NonCopyable<EventQueue> {
833844
* @see EventQueue::call_every
834845
*/
835846
template <typename T, typename R, typename... ArgTs>
836-
int call_every(int ms, const volatile T *obj, R(T::*method)(ArgTs...) const volatile, ArgTs... args)
847+
int call_every(int ms, const volatile T *obj, R(T::*method)(ArgTs...) const volatile, impl::type_identity_t<ArgTs>... args)
837848
{
838849
return call_every(ms, mbed::callback(obj, method), args...);
839850
}
@@ -847,38 +858,38 @@ class EventQueue : private mbed::NonCopyable<EventQueue> {
847858
* @param func Function to execute when the event is dispatched
848859
* @return Event that will dispatch on the specific queue
849860
*/
850-
template <typename R, typename... BoundArgTs, typename... ContextArgTs, typename... ArgTs>
851-
Event<void(ArgTs...)> event(R(*func)(BoundArgTs..., ArgTs...), ContextArgTs... context_args);
861+
template <typename R, typename... BoundArgTs, typename... ArgTs>
862+
Event<void(ArgTs...)> event(R(*func)(BoundArgTs..., ArgTs...), impl::type_identity_t<BoundArgTs>... context_args);
852863

853864
/** Creates an event bound to the event queue
854865
* @see EventQueue::event
855866
*/
856-
template <typename T, typename R, typename... BoundArgTs, typename... ContextArgTs, typename... ArgTs>
857-
Event<void(ArgTs...)> event(T *obj, R(T::*method)(BoundArgTs..., ArgTs...), ContextArgTs... context_args);
867+
template <typename T, typename R, typename... BoundArgTs, typename... ArgTs>
868+
Event<void(ArgTs...)> event(T *obj, R(T::*method)(BoundArgTs..., ArgTs...), impl::type_identity_t<BoundArgTs>... context_args);
858869

859870
/** Creates an event bound to the event queue
860871
* @see EventQueue::event
861872
*/
862-
template <typename T, typename R, typename... BoundArgTs, typename... ContextArgTs, typename... ArgTs>
863-
Event<void(ArgTs...)> event(const T *obj, R(T::*method)(BoundArgTs..., ArgTs...) const, ContextArgTs... context_args);
873+
template <typename T, typename R, typename... BoundArgTs, typename... ArgTs>
874+
Event<void(ArgTs...)> event(const T *obj, R(T::*method)(BoundArgTs..., ArgTs...) const, impl::type_identity_t<BoundArgTs>... context_args);
864875

865876
/** Creates an event bound to the event queue
866877
* @see EventQueue::event
867878
*/
868-
template <typename T, typename R, typename... BoundArgTs, typename... ContextArgTs, typename... ArgTs>
869-
Event<void(ArgTs...)> event(volatile T *obj, R(T::*method)(BoundArgTs..., ArgTs...) volatile, ContextArgTs... context_args);
879+
template <typename T, typename R, typename... BoundArgTs, typename... ArgTs>
880+
Event<void(ArgTs...)> event(volatile T *obj, R(T::*method)(BoundArgTs..., ArgTs...) volatile, impl::type_identity_t<BoundArgTs>... context_args);
870881

871882
/** Creates an event bound to the event queue
872883
* @see EventQueue::event
873884
*/
874-
template <typename T, typename R, typename... BoundArgTs, typename... ContextArgTs, typename... ArgTs>
875-
Event<void(ArgTs...)> event(const volatile T *obj, R(T::*method)(BoundArgTs..., ArgTs...) const volatile, ContextArgTs... context_args);
885+
template <typename T, typename R, typename... BoundArgTs, typename... ArgTs>
886+
Event<void(ArgTs...)> event(const volatile T *obj, R(T::*method)(BoundArgTs..., ArgTs...) const volatile, impl::type_identity_t<BoundArgTs>... context_args);
876887

877888
/** Creates an event bound to the event queue
878889
* @see EventQueue::event
879890
*/
880-
template <typename R, typename... BoundArgTs, typename... ContextArgTs, typename... ArgTs>
881-
Event<void(ArgTs...)> event(mbed::Callback<R(BoundArgTs..., ArgTs...)> cb, ContextArgTs... context_args);
891+
template <typename R, typename... BoundArgTs, typename... ArgTs>
892+
Event<void(ArgTs...)> event(mbed::Callback<R(BoundArgTs..., ArgTs...)> cb, impl::type_identity_t<BoundArgTs>... context_args);
882893
#endif
883894

884895
protected:

0 commit comments

Comments
 (0)