COMMS
Template library intended to help with implementation of communication protocols.
Loading...
Searching...
No Matches
dispatch.h
Go to the documentation of this file.
1//
2// Copyright 2019 - 2025 (C). Alex Robenko. All rights reserved.
3//
4
7
8#pragma once
9
11#include "comms/details/dispatch_impl.h"
12#include "comms/details/tag.h"
13#include "comms/Message.h"
15
16#include <type_traits>
17#include <utility>
18
19COMMS_MSVC_WARNING_PUSH
20COMMS_MSVC_WARNING_DISABLE(4100) // Disable warning about unreferenced parameters
21
22namespace comms
23{
24
36template <
37 typename TAllMessages,
38 typename TId,
39 typename TMsg,
40 typename THandler>
41auto dispatchMsgPolymorphic(TId&& id, TMsg& msg, THandler& handler) ->
42 details::MessageInterfaceDispatchRetType<
43 typename std::decay<decltype(handler)>::type>
44{
45 using MsgType = typename std::decay<decltype(msg)>::type;
46 static_assert(comms::isMessage<MsgType>(), "msg param must be a valid message");
47 return
48 details::DispatchMsgPolymorphicHelper<>::template
49 dispatch<TAllMessages>(std::forward<TId>(id), msg, handler);
50}
51
64template <
65 typename TAllMessages,
66 typename TId,
67 typename TMsg,
68 typename THandler>
69auto dispatchMsgPolymorphic(TId&& id, std::size_t index, TMsg& msg, THandler& handler) ->
70 details::MessageInterfaceDispatchRetType<
71 typename std::decay<decltype(handler)>::type>
72{
73 using MsgType = typename std::decay<decltype(msg)>::type;
74 static_assert(comms::isMessage<MsgType>(), "msg param must be a valid message");
75 return
76 details::DispatchMsgPolymorphicHelper<>::template
77 dispatch<TAllMessages>(std::forward<TId>(id), index, msg, handler);
78}
79
90template <
91 typename TAllMessages,
92 typename TMsg,
93 typename THandler>
94auto dispatchMsgPolymorphic(TMsg& msg, THandler& handler) ->
95 details::MessageInterfaceDispatchRetType<
96 typename std::decay<decltype(handler)>::type>
97{
98 using MsgType = typename std::decay<decltype(msg)>::type;
99 static_assert(comms::isMessage<MsgType>(), "msg param must be a valid message");
100 return
101 details::DispatchMsgPolymorphicHelper<>::template
102 dispatch<TAllMessages>(msg, handler);
103}
104
116template <
117 typename TAllMessages,
118 typename TId,
119 typename THandler>
120bool dispatchMsgTypePolymorphic(TId&& id, THandler& handler)
121{
122 return
123 details::DispatchMsgTypePolymorphicHelper<>::template
124 dispatch<TAllMessages>(std::forward<TId>(id), handler);
125}
126
139template <
140 typename TAllMessages,
141 typename TId,
142 typename THandler>
143bool dispatchMsgTypePolymorphic(TId&& id, std::size_t index, THandler& handler)
144{
145 return
146 details::DispatchMsgTypePolymorphicHelper<>::template
147 dispatch<TAllMessages>(std::forward<TId>(id), index, handler);
148}
149
162template <
163 typename TAllMessages,
164 typename TId,
165 typename TMsg,
166 typename THandler>
167auto dispatchMsgStaticBinSearch(TId&& id, std::size_t index, TMsg& msg, THandler& handler) ->
168 details::MessageInterfaceDispatchRetType<
169 typename std::decay<decltype(handler)>::type>
170{
171 static_assert(details::allMessagesHaveStaticNumId<TAllMessages>(),
172 "All messages in the provided tuple must statically define their numeric ID");
173
174 return
175 details::DispatchMsgStaticBinSearchHelper<>::template dispatch<TAllMessages>(
176 std::forward<TId>(id),
177 index,
178 msg,
179 handler);
180}
181
193template <
194 typename TAllMessages,
195 typename TId,
196 typename TMsg,
197 typename THandler>
198auto dispatchMsgStaticBinSearch(TId&& id, TMsg& msg, THandler& handler) ->
199 details::MessageInterfaceDispatchRetType<
200 typename std::decay<decltype(handler)>::type>
201{
202 static_assert(details::allMessagesHaveStaticNumId<TAllMessages>(),
203 "All messages in the provided tuple must statically define their numeric ID");
204
205 return
206 details::DispatchMsgStaticBinSearchHelper<>::template dispatch<TAllMessages>(
207 std::forward<TId>(id),
208 msg,
209 handler);
210}
211
222template <
223 typename TAllMessages,
224 typename TMsg,
225 typename THandler>
226auto dispatchMsgStaticBinSearch(TMsg& msg, THandler& handler) ->
227 details::MessageInterfaceDispatchRetType<
228 typename std::decay<decltype(handler)>::type>
229{
230 static_assert(details::allMessagesHaveStaticNumId<TAllMessages>(),
231 "All messages in the provided tuple must statically define their numeric ID");
232 using MsgType = typename std::decay<decltype(msg)>::type;
233 static_assert(MsgType::hasGetId(),
234 "The used message object must provide polymorphic ID retrieval function");
235
236 return
237 details::DispatchMsgStaticBinSearchHelper<>::template dispatch<TAllMessages>(
238 msg,
239 handler);
240}
241
253template <
254 typename TAllMessages,
255 typename TId,
256 typename THandler>
257bool dispatchMsgTypeStaticBinSearch(TId&& id, THandler& handler)
258{
259 static_assert(details::allMessagesHaveStaticNumId<TAllMessages>(),
260 "All messages in the provided tuple must statically define their numeric ID");
261
262 return
263 details::DispatchMsgStaticBinSearchHelper<>::template
264 dispatchType<TAllMessages>(std::forward<TId>(id), handler);
265}
266
279template <
280 typename TAllMessages,
281 typename TId,
282 typename THandler>
283bool dispatchMsgTypeStaticBinSearch(TId&& id, std::size_t index, THandler& handler)
284{
285 static_assert(details::allMessagesHaveStaticNumId<TAllMessages>(),
286 "All messages in the provided tuple must statically define their numeric ID");
287
288 return
289 details::DispatchMsgStaticBinSearchHelper<>::template
290 dispatchType<TAllMessages>(std::forward<TId>(id), index, handler);
291}
292
299template <typename TAllMessages, typename TId>
301{
302 static_assert(details::allMessagesHaveStaticNumId<TAllMessages>(),
303 "All messages in the provided tuple must statically define their numeric ID");
304
305 return
306 details::DispatchMsgStaticBinSearchHelper<>::template
307 dispatchTypeCount<TAllMessages>(std::forward<TId>(id));
308}
309
321template <
322 typename TAllMessages,
323 typename TId,
324 typename TMsg,
325 typename THandler>
326auto dispatchMsgLinearSwitch(TId&& id, TMsg& msg, THandler& handler) ->
327 details::MessageInterfaceDispatchRetType<
328 typename std::decay<decltype(handler)>::type>
329{
330 static_assert(details::allMessagesHaveStaticNumId<TAllMessages>(),
331 "All messages in the provided tuple must statically define their numeric ID");
332
333 return
334 details::DispatchMsgLinearSwitchHelper<>::template dispatch<TAllMessages>(
335 std::forward<TId>(id),
336 msg,
337 handler);
338}
339
352template <
353 typename TAllMessages,
354 typename TId,
355 typename TMsg,
356 typename THandler>
357auto dispatchMsgLinearSwitch(TId&& id, std::size_t index, TMsg& msg, THandler& handler) ->
358 details::MessageInterfaceDispatchRetType<
359 typename std::decay<decltype(handler)>::type>
360{
361 static_assert(details::allMessagesHaveStaticNumId<TAllMessages>(),
362 "All messages in the provided tuple must statically define their numeric ID");
363
364 return
365 details::DispatchMsgLinearSwitchHelper<>::template dispatch<TAllMessages>(
366 std::forward<TId>(id),
367 index,
368 msg,
369 handler);
370}
371
382template <
383 typename TAllMessages,
384 typename TMsg,
385 typename THandler>
386auto dispatchMsgLinearSwitch(TMsg& msg, THandler& handler) ->
387 details::MessageInterfaceDispatchRetType<
388 typename std::decay<decltype(handler)>::type>
389{
390 static_assert(details::allMessagesHaveStaticNumId<TAllMessages>(),
391 "All messages in the provided tuple must statically define their numeric ID");
392 using MsgType = typename std::decay<decltype(msg)>::type;
393 static_assert(MsgType::hasGetId(),
394 "The used message object must provide polymorphic ID retrieval function");
395
396 return
397 details::DispatchMsgLinearSwitchHelper<>::template dispatch<TAllMessages>(
398 msg,
399 handler);
400}
401
413template <
414 typename TAllMessages,
415 typename TId,
416 typename THandler>
417bool dispatchMsgTypeLinearSwitch(TId&& id, THandler& handler)
418{
419 static_assert(details::allMessagesHaveStaticNumId<TAllMessages>(),
420 "All messages in the provided tuple must statically define their numeric ID");
421
422 return
423 details::DispatchMsgLinearSwitchHelper<>::template
424 dispatchType<TAllMessages>(std::forward<TId>(id), handler);
425}
426
439template <
440 typename TAllMessages,
441 typename TId,
442 typename THandler>
443bool dispatchMsgTypeLinearSwitch(TId&& id, std::size_t index, THandler& handler)
444{
445 static_assert(details::allMessagesHaveStaticNumId<TAllMessages>(),
446 "All messages in the provided tuple must statically define their numeric ID");
447
448 return
449 details::DispatchMsgLinearSwitchHelper<>::template
450 dispatchType<TAllMessages>(std::forward<TId>(id), index, handler);
451}
452
459template <typename TMsg, typename THandler>
460constexpr bool dispatchMsgIsDirect()
461{
462 return details::dispatchMsgPolymorphicIsCompatibleHandler<typename std::decay<TMsg>::type, typename std::decay<THandler>::type>();
463}
464
472template <typename TMsg, typename THandler>
473constexpr bool dispatchMsgIsDirect(TMsg&& msg, THandler&& handler)
474{
475 return dispatchMsgIsDirect<typename std::decay<decltype(msg)>::type, typename std::decay<decltype(handler)>::type>();
476}
477
478namespace details
479{
480template <typename TAllMessages>
481class DispatchMsgHelper
482{
483public:
484 template <typename TMsg, typename THandler>
485 static auto dispatchMsg(TMsg& msg, THandler& handler) ->
486 MessageInterfaceDispatchRetType<
487 typename std::decay<decltype(handler)>::type>
488 {
489 return dispatchMsgInternal(msg, handler, HandlerAdjustedTag<TMsg, THandler>());
490 }
491
492 template <typename TId, typename TMsg, typename THandler>
493 static auto dispatchMsg(TId&& id, TMsg& msg, THandler& handler) ->
494 MessageInterfaceDispatchRetType<
495 typename std::decay<decltype(handler)>::type>
496 {
497 return dispatchMsgInternal(std::forward<TId>(id), msg, handler, HandlerAdjustedTag<TMsg, THandler>());
498 }
499
500 template <typename TId, typename TMsg, typename THandler>
501 static auto dispatchMsg(TId&& id, std::size_t index, TMsg& msg, THandler& handler) ->
502 MessageInterfaceDispatchRetType<
503 typename std::decay<decltype(handler)>::type>
504 {
505 return dispatchMsgInternal(std::forward<TId>(id), index, msg, handler, HandlerAdjustedTag<TMsg, THandler>());
506 }
507
508 template <typename TId, typename THandler>
509 static bool dispatchMsgType(TId&& id, THandler& handler)
510 {
511 return dispatchMsgTypeInternal(std::forward<TId>(id), handler, Tag<>());
512 }
513
514 template <typename TId, typename THandler>
515 static bool dispatchMsgType(TId&& id, std::size_t index, THandler& handler)
516 {
517 return dispatchMsgTypeInternal(std::forward<TId>(id), index, handler, Tag<>());
518 }
519
520 static constexpr bool isPolymorphic()
521 {
522 return std::is_same<Tag<>, PolymorphicTag<> >::value;
523 }
524
525 static constexpr bool isStaticBinSearch()
526 {
527 return std::is_same<Tag<>, StaticBinSearchTag<> >::value;
528 }
529
530 template <typename TMsg, typename THandler>
531 static constexpr bool isDirect()
532 {
533 return dispatchMsgIsDirect<TMsg, THandler>();
534 }
535
536 template <typename TMsg, typename THandler>
537 static constexpr bool isDirect(TMsg&& msg, THandler&& handler)
538 {
539 return isDirect<typename std::decay<decltype(msg)>::type, typename std::decay<decltype(handler)>::type>();
540 }
541
542private:
543 template <typename... TParams>
544 using PolymorphicTag = comms::details::tag::Tag1<>;
545
546 template <typename... TParams>
547 using StaticBinSearchTag = comms::details::tag::Tag2<>;
548
549 template <typename...>
550 using Tag =
551 typename comms::util::LazyShallowConditional<
552 dispatchMsgPolymorphicIsDirectSuitable<TAllMessages>() || (!allMessagesHaveStaticNumId<TAllMessages>())
553 >::template Type<
554 PolymorphicTag,
555 StaticBinSearchTag
556 >;
557
558 template <typename TMsgBase, typename THandler>
559 using HandlerAdjustedTag =
560 typename comms::util::LazyShallowConditional<
561 dispatchMsgIsDirect<TMsgBase, THandler>()
562 >::template Type<
563 PolymorphicTag,
564 Tag
565 >;
566
567 template <typename TMsg, typename THandler, typename... TParams>
568 static auto dispatchMsgInternal(TMsg& msg, THandler& handler, PolymorphicTag<TParams...>) ->
569 MessageInterfaceDispatchRetType<
570 typename std::decay<decltype(handler)>::type>
571 {
572 return comms::dispatchMsgPolymorphic<TAllMessages>(msg, handler);
573 }
574
575 template <typename TMsg, typename THandler, typename... TParams>
576 static auto dispatchMsgInternal(TMsg& msg, THandler& handler, StaticBinSearchTag<TParams...>) ->
577 MessageInterfaceDispatchRetType<
578 typename std::decay<decltype(handler)>::type>
579 {
580 return comms::dispatchMsgStaticBinSearch<TAllMessages>(msg, handler);
581 }
582
583 template <typename TId, typename TMsg, typename THandler, typename... TParams>
584 static auto dispatchMsgInternal(TId&& id, TMsg& msg, THandler& handler, PolymorphicTag<TParams...>) ->
585 MessageInterfaceDispatchRetType<
586 typename std::decay<decltype(handler)>::type>
587 {
588 return comms::dispatchMsgPolymorphic<TAllMessages>(std::forward<TId>(id), msg, handler);
589 }
590
591 template <typename TId, typename TMsg, typename THandler, typename... TParams>
592 static auto dispatchMsgInternal(TId&& id, TMsg& msg, THandler& handler, StaticBinSearchTag<TParams...>) ->
593 MessageInterfaceDispatchRetType<
594 typename std::decay<decltype(handler)>::type>
595 {
596 return comms::dispatchMsgStaticBinSearch<TAllMessages>(std::forward<TId>(id), msg, handler);
597 }
598
599 template <typename TId, typename TMsg, typename THandler, typename... TParams>
600 static auto dispatchMsgInternal(TId&& id, std::size_t index, TMsg& msg, THandler& handler, PolymorphicTag<TParams...>) ->
601 MessageInterfaceDispatchRetType<
602 typename std::decay<decltype(handler)>::type>
603 {
604 return comms::dispatchMsgPolymorphic<TAllMessages>(std::forward<TId>(id), index, msg, handler);
605 }
606
607 template <typename TId, typename TMsg, typename THandler, typename... TParams>
608 static auto dispatchMsgInternal(TId&& id, std::size_t index, TMsg& msg, THandler& handler, StaticBinSearchTag<TParams...>) ->
609 MessageInterfaceDispatchRetType<
610 typename std::decay<decltype(handler)>::type>
611 {
612 return comms::dispatchMsgStaticBinSearch<TAllMessages>(std::forward<TId>(id), index, msg, handler);
613 }
614
615 template <typename TId, typename THandler, typename... TParams>
616 static bool dispatchMsgTypeInternal(TId&& id, THandler& handler, PolymorphicTag<TParams...>)
617 {
618 return comms::dispatchMsgTypePolymorphic<TAllMessages>(std::forward<TId>(id), handler);
619 }
620
621 template <typename TId, typename THandler, typename... TParams>
622 static bool dispatchMsgTypeInternal(TId&& id, THandler& handler, StaticBinSearchTag<TParams...>)
623 {
624 return comms::dispatchMsgTypeStaticBinSearch<TAllMessages>(std::forward<TId>(id), handler);
625 }
626
627 template <typename TId, typename THandler, typename... TParams>
628 static bool dispatchMsgTypeInternal(TId&& id, std::size_t index, THandler& handler, PolymorphicTag<TParams...>)
629 {
630 return comms::dispatchMsgTypePolymorphic<TAllMessages>(std::forward<TId>(id), index, handler);
631 }
632
633 template <typename TId, typename THandler, typename... TParams>
634 static bool dispatchMsgTypeInternal(TId&& id, std::size_t index, THandler& handler, StaticBinSearchTag<TParams...>)
635 {
636 return comms::dispatchMsgTypeStaticBinSearch<TAllMessages>(std::forward<TId>(id), index, handler);
637 }
638};
639
640} // namespace details
641
659template <
660 typename TAllMessages,
661 typename TId,
662 typename TMsg,
663 typename THandler>
664auto dispatchMsg(TId&& id, TMsg& msg, THandler& handler) ->
665 details::MessageInterfaceDispatchRetType<
666 typename std::decay<decltype(handler)>::type>
667{
668 return details::DispatchMsgHelper<TAllMessages>::dispatchMsg(std::forward<TId>(id), msg, handler);
669}
670
689template <
690 typename TAllMessages,
691 typename TId,
692 typename TMsg,
693 typename THandler>
694auto dispatchMsg(TId&& id, std::size_t index, TMsg& msg, THandler& handler) ->
695 details::MessageInterfaceDispatchRetType<
696 typename std::decay<decltype(handler)>::type>
697{
698 return details::DispatchMsgHelper<TAllMessages>::dispatchMsg(std::forward<TId>(id), index, msg, handler);
699}
700
717template <
718 typename TAllMessages,
719 typename TMsg,
720 typename THandler>
721auto dispatchMsg(TMsg& msg, THandler& handler) ->
722 details::MessageInterfaceDispatchRetType<
723 typename std::decay<decltype(handler)>::type>
724{
725 return details::DispatchMsgHelper<TAllMessages>::dispatchMsg(msg, handler);
726}
727
744template <typename TAllMessages, typename TId, typename THandler>
745bool dispatchMsgType(TId&& id, THandler& handler)
746{
747 return details::DispatchMsgHelper<TAllMessages>::dispatchMsgType(std::forward<TId>(id), handler);
748}
749
767template <typename TAllMessages, typename TId, typename THandler>
768bool dispatchMsgType(TId&& id, std::size_t index, THandler& handler)
769{
770 return details::DispatchMsgHelper<TAllMessages>::dispatchMsgType(std::forward<TId>(id), index, handler);
771}
772
779template <typename TAllMessages>
781{
782 return details::DispatchMsgHelper<TAllMessages>::isPolymorphic();
783}
784
794template <typename TAllMessages, typename TMsg, typename THandler>
796{
797 return dispatchMsgIsDirect<TMsg, THandler>() || dispatchMsgTypeIsPolymorphic<TAllMessages>();
798}
799
807template <typename TAllMessages, typename TMsg, typename THandler>
808constexpr bool dispatchMsgIsPolymorphic(TMsg&& msg, THandler&& handler)
809{
810 return dispatchMsgIsPolymorphic<TAllMessages, typename std::decay<decltype(msg)>::type, typename std::decay<decltype(handler)>::type>();
811}
812
819template <typename TAllMessages>
821{
822 return details::DispatchMsgHelper<TAllMessages>::isStaticBinSearch();
823}
824
834template <typename TAllMessages, typename TMsg, typename THandler>
836{
837 return (!dispatchMsgIsDirect<TMsg, THandler>()) &&
838 dispatchMsgTypeIsStaticBinSearch<TAllMessages>();
839}
840
848template <typename TAllMessages, typename TMsg, typename THandler>
849constexpr bool dispatchMsgIsStaticBinSearch(TMsg&& msg, THandler&& handler)
850{
851 return dispatchMsgIsStaticBinSearch<TAllMessages, typename std::decay<decltype(msg)>::type, typename std::decay<decltype(handler)>::type>();
852}
853
854} // namespace comms
855
856COMMS_MSVC_WARNING_POP
Contains various compiler related definitions.
Contains definition of Message object interface and various base classes for custom messages.
Main namespace for all classes / functions of COMMS library.
constexpr bool dispatchMsgIsPolymorphic()
Compile time check whether the dispatchMsg() will use "polymorphic" (including "direct") dispatch for...
Definition dispatch.h:795
constexpr bool dispatchMsgIsDirect()
Compile time check whether the message object can use its own polymorphic dispatch() (see Polymorphic...
Definition dispatch.h:460
auto dispatchMsg(TId &&id, TMsg &msg, THandler &handler) -> details::MessageInterfaceDispatchRetType< typename std::decay< decltype(handler)>::type >
Dispatch message object into appropriate handle() function in the provided handler using either "poly...
Definition dispatch.h:664
auto dispatchMsgStaticBinSearch(TId &&id, std::size_t index, TMsg &msg, THandler &handler) -> details::MessageInterfaceDispatchRetType< typename std::decay< decltype(handler)>::type >
Dispatch message object into appropriate handle() function in the provided handler using static binar...
Definition dispatch.h:167
bool dispatchMsgTypePolymorphic(TId &&id, THandler &handler)
Dispatch message id into appropriate handle() function in the provided handler using polymorphic beha...
Definition dispatch.h:120
std::size_t dispatchMsgTypeCountStaticBinSearch(TId &&id)
Count number of message types in the provided tuple that have the requested numeric ID.
Definition dispatch.h:300
bool dispatchMsgTypeLinearSwitch(TId &&id, THandler &handler)
Dispatch message id into appropriate handle() function in the provided handler using linear switch be...
Definition dispatch.h:417
constexpr bool dispatchMsgIsStaticBinSearch()
Compile time check whether the dispatchMsg() will use "static binary search" dispatch for provided tu...
Definition dispatch.h:835
constexpr bool dispatchMsgTypeIsPolymorphic()
Compile time check whether the dispatchMsgType() will use "polymorphic" dispatch for provided tuple o...
Definition dispatch.h:780
constexpr bool dispatchMsgTypeIsStaticBinSearch()
Compile time check whether the dispatchMsgType() or dispatchMsgType() will use "static binary search"...
Definition dispatch.h:820
auto dispatchMsgPolymorphic(TId &&id, TMsg &msg, THandler &handler) -> details::MessageInterfaceDispatchRetType< typename std::decay< decltype(handler)>::type >
Dispatch message object into appropriate handle() function in the provided handler using polymorphic ...
Definition dispatch.h:41
auto dispatchMsgLinearSwitch(TId &&id, TMsg &msg, THandler &handler) -> details::MessageInterfaceDispatchRetType< typename std::decay< decltype(handler)>::type >
Dispatch message object into appropriate handle() function in the provided handler using linear switc...
Definition dispatch.h:326
bool dispatchMsgType(TId &&id, THandler &handler)
Dispatch message id into appropriate handle() function in the provided handler using either "polymorp...
Definition dispatch.h:745
bool dispatchMsgTypeStaticBinSearch(TId &&id, THandler &handler)
Dispatch message id into appropriate handle() function in the provided handler using static binary se...
Definition dispatch.h:257
Replacement to some types from standard type_traits.