COMMS
Template library intended to help with implementation of communication protocols.
Loading...
Searching...
No Matches
DispatchMsgLinearSwitchHelper.h
1//
2// Copyright 2019 - 2025 (C). Alex Robenko. All rights reserved.
3//
4// This Source Code Form is subject to the terms of the Mozilla Public
5// License, v. 2.0. If a copy of the MPL was not distributed with this
6// file, You can obtain one at http://mozilla.org/MPL/2.0/.
7
8#pragma once
9
11#include "comms/details/DispatchMsgHelperType.h"
13#include "comms/details/tag.h"
14#include "comms/Message.h"
15#include "comms/MessageBase.h"
17
18#include <type_traits>
19#include <utility>
20
21COMMS_MSVC_WARNING_PUSH
22COMMS_MSVC_WARNING_DISABLE(4702) // Gives warning about unreachable code
23
24namespace comms
25{
26
27namespace details
28{
29
30template <DispatchMsgTypeEnum TType>
31class DispatchMsgStrongLinearSwitchHelper // <DispatchMsgTypeEnum::Multiple>
32{
33 template <typename TAllMessages, std::size_t TCount>
34 using FromElem =
35 typename std::tuple_element<
36 std::tuple_size<TAllMessages>::value - TCount,
37 TAllMessages
38 >::type;
39
40 // static_assert(messageHasStaticNumId<FromElem>(), "Message must define static ID");
41
42public:
43 template <
44 typename TAllMessages,
45 std::size_t TCount,
46 typename TMsg,
47 typename THandler>
48 static auto dispatch(typename TMsg::MsgIdParamType id, TMsg& msg, THandler& handler) ->
49 MessageInterfaceDispatchRetType<
50 typename std::decay<decltype(handler)>::type>
51 {
52 using RetType =
53 MessageInterfaceDispatchRetType<
54 typename std::decay<decltype(handler)>::type>;
55
56 using Elem = FromElem<TAllMessages, TCount>;
57
58 static constexpr typename TMsg::MsgIdParamType fromId = Elem::doGetId();
59 switch(id) {
60 case fromId: {
61 auto& castedMsg = static_cast<Elem&>(msg);
62 return static_cast<RetType>(handler.handle(castedMsg));
63 break;
64 }
65 default:
66 static constexpr std::size_t NextCount = TCount - 1U;
67 static constexpr auto HelperType = DispatchMsgHelperIntType<NextCount>::value;
68 return
69 DispatchMsgStrongLinearSwitchHelper<HelperType>::template
70 dispatch<TAllMessages, NextCount>(id, msg, handler);
71
72 };
73 // dead code (just in case), should not reach here
74 return static_cast<RetType>(handler.handle(msg));
75 }
76
77 template <
78 typename TAllMessages,
79 std::size_t TCount,
80 typename TId,
81 typename THandler>
82 static bool dispatchType(TId&& id, THandler& handler)
83 {
84 using Elem = FromElem<TAllMessages, TCount>;
85 static constexpr typename Elem::MsgIdParamType fromId = Elem::doGetId();
86 switch(id) {
87 case fromId: {
88 handler.template handle<Elem>();
89 return true;
90 break;
91 }
92 default:
93 static constexpr std::size_t NextCount = TCount - 1U;
94 static constexpr auto HelperType = DispatchMsgHelperIntType<NextCount>::value;
95 return
96 DispatchMsgStrongLinearSwitchHelper<HelperType>::template
97 dispatchType<TAllMessages, NextCount>(id, handler);
98
99 };
100 // dead code (just in case), should not reach here
101 return false;
102 }
103
104};
105
106template <>
107class DispatchMsgStrongLinearSwitchHelper<DispatchMsgTypeEnum::Single>
108{
109 // static_assert(1 <= std::tuple_size<TAllMessages>::value,
110 // "Invalid template params");
111
112 template <typename TAllMessages>
113 using FromElem =
114 typename std::tuple_element<
115 std::tuple_size<TAllMessages>::value - 1U,
116 TAllMessages
117 >::type;
118
119 // static_assert(messageHasStaticNumId<Elem>(), "Message must define static ID");
120
121public:
122 template <
123 typename TAllMessages,
124 std::size_t TCount,
125 typename TMsg,
126 typename THandler>
127 static auto dispatch(typename TMsg::MsgIdParamType id, TMsg& msg, THandler& handler) ->
128 MessageInterfaceDispatchRetType<
129 typename std::decay<decltype(handler)>::type>
130 {
131 static_assert(TCount == 1U, "Invalid invocation");
132
133 using RetType =
134 MessageInterfaceDispatchRetType<
135 typename std::decay<decltype(handler)>::type>;
136
137 using Elem = FromElem<TAllMessages>;
138 typename TMsg::MsgIdParamType elemId = Elem::doGetId();
139 if (id != elemId) {
140 return static_cast<RetType>(handler.handle(msg));
141 }
142
143 auto& castedMsg = static_cast<Elem&>(msg);
144 return static_cast<RetType>(handler.handle(castedMsg));
145 }
146
147 template <
148 typename TAllMessages,
149 std::size_t TCount,
150 typename TId,
151 typename THandler>
152 static bool dispatchType(TId&& id, THandler& handler)
153 {
154 static_assert(TCount == 1U, "Invalid invocation");
155 using Elem = FromElem<TAllMessages>;
156 typename Elem::MsgIdParamType elemId = Elem::doGetId();
157 if (id != elemId) {
158 return false;
159 }
160
161 handler.template handle<Elem>();
162 return true;
163 }
164};
165
166template <>
167class DispatchMsgStrongLinearSwitchHelper<DispatchMsgTypeEnum::None>
168{
169public:
170 template <
171 typename TAllMessages,
172 std::size_t TCount,
173 typename TMsg,
174 typename THandler>
175 static auto dispatch(typename TMsg::MsgIdParamType id, TMsg& msg, THandler& handler) ->
176 MessageInterfaceDispatchRetType<
177 typename std::decay<decltype(handler)>::type>
178 {
179 static_cast<void>(id);
180
181 using RetType =
182 MessageInterfaceDispatchRetType<
183 typename std::decay<decltype(handler)>::type>;
184 return static_cast<RetType>(handler.handle(msg));
185 }
186
187 template <typename TId, typename THandler>
188 static bool dispatchType(TId&& id, THandler& handler)
189 {
190 static_cast<void>(id);
191 static_cast<void>(handler);
192 return false;
193 }
194};
195
196template <bool THasElems>
197class DispatchMsgLinearSwitchWeakCountFinder // <true>
198{
199 template <typename TAllMessages, std::size_t TIdx>
200 using OrigMsgType = typename std::tuple_element<TIdx, TAllMessages>::type;
201
202 template <typename TAllMessages, std::size_t TIdx, std::size_t TCount>
203 using CurrMsgType =
204 typename std::tuple_element<
205 std::tuple_size<TAllMessages>::value - TCount,
206 TAllMessages
207 >::type;
208
209public:
210 template <typename TAllMessages, std::size_t TOrigIdx, std::size_t TRem>
211 using Type =
213 OrigMsgType<TAllMessages, TOrigIdx>::doGetId() == CurrMsgType<TAllMessages, TOrigIdx, TRem>::doGetId()
214 >::template Type<
215 std::integral_constant<
216 std::size_t,
217 1U + DispatchMsgLinearSwitchWeakCountFinder<(1U < TRem)>::template Type<TAllMessages, TOrigIdx, TRem - 1>::value
218 >,
219 std::integral_constant<std::size_t, 0U>
220 >;
221};
222
223template <>
224class DispatchMsgLinearSwitchWeakCountFinder<false>
225{
226public:
227 template <typename TAllMessages, std::size_t TOrigIdx, std::size_t TRem>
228 using Type = std::integral_constant<std::size_t, 0U>;
229};
230
231template <DispatchMsgTypeEnum TType>
232class DispatchMsgWeakLinearSwitchHelper // <DispatchMsgTypeEnum::Multiple>
233{
234 // static_assert(TFrom + TCount <= std::tuple_size<TAllMessages>::value,
235 // "Invalid template params");
236 // static_assert(2 <= TCount, "Invalid invocation");
237
238 template <typename TAllMessages, std::size_t TFrom>
239 using FromElem = typename std::tuple_element<TFrom, TAllMessages>::type;
240
241 // static_assert(messageHasStaticNumId<FromElem>(), "Message must define static ID");
242
243 template <typename TAllMessages, std::size_t TFrom, std::size_t TCount>
244 using SameIdsCount =
245 typename DispatchMsgLinearSwitchWeakCountFinder<
246 0 < TCount
247 >::template Type<
248 TAllMessages,
249 TFrom,
250 TCount
251 >;
252
253 // static_assert(SameIdsCount <= TCount, "Invalid template params");
254 // static_assert(0U < SameIdsCount, "Invalid template params");
255
256public:
257 template <
258 typename TAllMessages,
259 std::size_t TFrom,
260 std::size_t TCount,
261 typename TMsg,
262 typename THandler>
263 static auto dispatch(typename TMsg::MsgIdParamType id, std::size_t offset, TMsg& msg, THandler& handler) ->
264 MessageInterfaceDispatchRetType<
265 typename std::decay<decltype(handler)>::type>
266 {
267 using RetType =
268 MessageInterfaceDispatchRetType<
269 typename std::decay<decltype(handler)>::type>;
270
271 using Elem = FromElem<TAllMessages, TFrom>;
272 static constexpr typename TMsg::MsgIdParamType fromId = Elem::doGetId();
273 switch(id) {
274 case fromId:
275 {
276 static constexpr std::size_t NextCount = SameIdsCount<TAllMessages, TFrom, TCount>::value;
277 static constexpr auto HelperType = DispatchMsgHelperIntType<NextCount>::value;
278 return
279 DispatchMsgWeakLinearSwitchHelper<HelperType>::template
280 dispatchOffset<TAllMessages, TFrom, NextCount>(offset, msg, handler);
281 }
282 default:
283 {
284 static constexpr std::size_t SkipCount = SameIdsCount<TAllMessages, TFrom, TCount>::value;
285 static constexpr std::size_t NextFrom = TFrom + SkipCount;
286 static constexpr std::size_t NextCount = TCount - SkipCount;
287 static constexpr auto HelperType = DispatchMsgHelperIntType<NextCount>::value;
288
289 return
290 DispatchMsgWeakLinearSwitchHelper<HelperType>::template
291 dispatch<TAllMessages, NextFrom, NextCount>(id, offset, msg, handler);
292 }
293 };
294 // dead code (just in case), should not reach here
295 return static_cast<RetType>(handler.handle(msg));
296 }
297
298 template <
299 typename TAllMessages,
300 std::size_t TFrom,
301 std::size_t TCount,
302 typename TMsg,
303 typename THandler>
304 static auto dispatchOffset(std::size_t offset, TMsg& msg, THandler& handler) ->
305 MessageInterfaceDispatchRetType<
306 typename std::decay<decltype(handler)>::type>
307 {
308 using RetType =
309 MessageInterfaceDispatchRetType<
310 typename std::decay<decltype(handler)>::type>;
311
312 using Elem = FromElem<TAllMessages, TFrom>;
313 switch(offset) {
314 case 0:
315 {
316 auto& castedMsg = static_cast<Elem&>(msg);
317 return static_cast<RetType>(handler.handle(castedMsg));
318 }
319 default:
320 static constexpr std::size_t NextCount = TCount - 1U;
321 static constexpr auto HelperType = DispatchMsgHelperIntType<NextCount>::value;
322 return
323 DispatchMsgWeakLinearSwitchHelper<HelperType>::template
324 dispatchOffset<TAllMessages, TFrom + 1, NextCount>(offset - 1, msg, handler);
325 };
326
327 // dead code (just in case), should not reach here
328 return static_cast<RetType>(handler.handle(msg));
329 }
330
331 template <
332 typename TAllMessages,
333 std::size_t TFrom,
334 std::size_t TCount,
335 typename TId,
336 typename THandler>
337 static bool dispatchType(TId&& id, std::size_t offset, THandler& handler)
338 {
339 using Elem = FromElem<TAllMessages, TFrom>;
340 static constexpr typename Elem::MsgIdParamType fromId = Elem::doGetId();
341 switch(id) {
342 case fromId:
343 {
344 static constexpr std::size_t NextCount = SameIdsCount<TAllMessages, TFrom, TCount>::value;
345 static constexpr auto HelperType = DispatchMsgHelperIntType<NextCount>::value;
346 return
347 DispatchMsgWeakLinearSwitchHelper<HelperType>::template
348 dispatchTypeOffset<TAllMessages, TFrom, NextCount>(offset, handler);
349 }
350 default:
351 {
352 static constexpr std::size_t SkipCount = SameIdsCount<TAllMessages, TFrom, TCount>::value;
353 static constexpr std::size_t NextFrom = TFrom + SkipCount;
354 static constexpr std::size_t NextCount = TCount - SkipCount;
355 static constexpr auto HelperType = DispatchMsgHelperIntType<NextCount>::value;
356 return
357 DispatchMsgWeakLinearSwitchHelper<HelperType>::template
358 dispatchType<TAllMessages, NextFrom, NextCount>(id, offset, handler);
359 }
360 };
361 // dead code (just in case), should not reach here
362 return false;
363 }
364
365 template <
366 typename TAllMessages,
367 std::size_t TFrom,
368 std::size_t TCount,
369 typename THandler>
370 static bool dispatchTypeOffset(std::size_t offset, THandler& handler)
371 {
372 switch(offset) {
373 case 0:
374 using Elem = FromElem<TAllMessages, TFrom>;
375 handler.template handle<Elem>();
376 return true;
377 default:
378 static constexpr std::size_t NextCount = TCount - 1U;
379 static constexpr auto HelperType = DispatchMsgHelperIntType<NextCount>::value;
380 return
381 DispatchMsgWeakLinearSwitchHelper<HelperType>::template
382 dispatchTypeOffset<TAllMessages, TFrom + 1, NextCount>(offset - 1, handler);
383 };
384
385 // dead code (just in case), should not reach here
386 return false;
387 }
388};
389
390template <>
391class DispatchMsgWeakLinearSwitchHelper<DispatchMsgTypeEnum::Single>
392{
393 // static_assert(TFrom + 1 <= std::tuple_size<TAllMessages>::value,
394 // "Invalid template params");
395
396 template <typename TAllMessages, std::size_t TFrom>
397 using FromElem = typename std::tuple_element<TFrom, TAllMessages>::type;
398 // static_assert(messageHasStaticNumId<Elem>(), "Message must define static ID");
399
400public:
401 template <
402 typename TAllMessages,
403 std::size_t TFrom,
404 std::size_t TCount,
405 typename TMsg,
406 typename THandler>
407 static auto dispatch(typename TMsg::MsgIdParamType id, std::size_t offset, TMsg& msg, THandler& handler) ->
408 MessageInterfaceDispatchRetType<
409 typename std::decay<decltype(handler)>::type>
410 {
411 using RetType =
412 MessageInterfaceDispatchRetType<
413 typename std::decay<decltype(handler)>::type>;
414
415 if (offset != 0U) {
416 return static_cast<RetType>(handler.handle(msg));
417 }
418
419 using Elem = FromElem<TAllMessages, TFrom>;
420 typename TMsg::MsgIdParamType elemId = Elem::doGetId();
421 if (id != elemId) {
422 return static_cast<RetType>(handler.handle(msg));
423 }
424
425 auto& castedMsg = static_cast<Elem&>(msg);
426 return static_cast<RetType>(handler.handle(castedMsg));
427 }
428
429 template <
430 typename TAllMessages,
431 std::size_t TFrom,
432 std::size_t TCount,
433 typename TMsg,
434 typename THandler>
435 static auto dispatchOffset(std::size_t offset, TMsg& msg, THandler& handler) ->
436 MessageInterfaceDispatchRetType<
437 typename std::decay<decltype(handler)>::type>
438 {
439 using RetType =
440 MessageInterfaceDispatchRetType<
441 typename std::decay<decltype(handler)>::type>;
442
443 if (offset != 0U) {
444 return static_cast<RetType>(handler.handle(msg));
445 }
446
447 using Elem = FromElem<TAllMessages, TFrom>;
448 auto& castedMsg = static_cast<Elem&>(msg);
449 return static_cast<RetType>(handler.handle(castedMsg));
450 }
451
452 template <
453 typename TAllMessages,
454 std::size_t TFrom,
455 std::size_t TCount,
456 typename TId,
457 typename THandler>
458 static bool dispatchType(TId&& id, std::size_t offset, THandler& handler)
459 {
460 if (offset != 0U) {
461 return false;
462 }
463
464 using Elem = FromElem<TAllMessages, TFrom>;
465 typename Elem::MsgIdParamType elemId = Elem::doGetId();
466 if (id != elemId) {
467 return false;
468 }
469
470 handler.template handle<Elem>();
471 return true;
472 }
473
474 template <
475 typename TAllMessages,
476 std::size_t TFrom,
477 std::size_t TCount,
478 typename THandler>
479 static bool dispatchTypeOffset(std::size_t offset, THandler& handler)
480 {
481 if (offset != 0U) {
482 return false;
483 }
484
485 using Elem = FromElem<TAllMessages, TFrom>;
486 handler.template handle<Elem>();
487 return true;
488 }
489};
490
491template <>
492class DispatchMsgWeakLinearSwitchHelper<DispatchMsgTypeEnum::None>
493{
494public:
495 template <
496 typename TAllMessages,
497 std::size_t TFrom,
498 std::size_t TCount,
499 typename TMsg,
500 typename THandler>
501 static auto dispatch(typename TMsg::MsgIdParamType id, std::size_t offset, TMsg& msg, THandler& handler) ->
502 MessageInterfaceDispatchRetType<
503 typename std::decay<decltype(handler)>::type>
504 {
505 static_cast<void>(id);
506 static_cast<void>(offset);
507
508 using RetType =
509 MessageInterfaceDispatchRetType<
510 typename std::decay<decltype(handler)>::type>;
511 return static_cast<RetType>(handler.handle(msg));
512 }
513
514 template <
515 typename TAllMessages,
516 std::size_t TFrom,
517 std::size_t TCount,
518 typename TMsg,
519 typename THandler>
520 static auto dispatchOffset(std::size_t offset, TMsg& msg, THandler& handler) ->
521 MessageInterfaceDispatchRetType<
522 typename std::decay<decltype(handler)>::type>
523 {
524 static_cast<void>(offset);
525
526 using RetType =
527 MessageInterfaceDispatchRetType<
528 typename std::decay<decltype(handler)>::type>;
529 return static_cast<RetType>(handler.handle(msg));
530 }
531
532 template <
533 typename TAllMessages,
534 std::size_t TFrom,
535 std::size_t TCount,
536 typename TId,
537 typename THandler>
538 static bool dispatchType(TId&& id, std::size_t offset, THandler& handler)
539 {
540 static_cast<void>(id);
541 static_cast<void>(offset);
542 static_cast<void>(handler);
543 return false;
544 }
545
546 template <
547 typename TAllMessages,
548 std::size_t TFrom,
549 std::size_t TCount,
550 typename THandler>
551 static bool dispatchTypeOffset(std::size_t offset, THandler& handler)
552 {
553 static_cast<void>(offset);
554 static_cast<void>(handler);
555 return false;
556 }
557};
558
559template <typename...>
560class DispatchMsgLinearSwitchHelper
561{
562 template <typename... TParams>
563 using EmptyTag = comms::details::tag::Tag1<>;
564
565 template <typename... TParams>
566 using StrongTag = comms::details::tag::Tag2<>;
567
568 template <typename... TParams>
569 using WeakTag = comms::details::tag::Tag3<>;
570
571 template <typename TAllMessages, typename...>
572 using StrongWeakTag =
573 typename comms::util::LazyShallowConditional<
574 allMessagesAreStrongSorted<TAllMessages>()
575 >::template Type<
576 StrongTag,
577 WeakTag
578 >;
579
580 template <typename TAllMessages, typename...>
581 using BinSearchTag =
582 typename comms::util::LazyShallowConditional<
583 std::tuple_size<TAllMessages>::value == 0U
584 >::template Type<
585 EmptyTag,
586 StrongWeakTag,
587 TAllMessages
588 >;
589
590 template <typename TAllMessages, typename TMsg>
591 using AdjustedTag =
592 typename comms::util::LazyShallowConditional<
593 comms::isMessageBase<TMsg>()
594 >::template Type<
595 EmptyTag,
596 BinSearchTag,
597 TAllMessages
598 >;
599
600public:
601 template <typename TAllMessages, typename TMsg, typename THandler>
602 static auto dispatch(TMsg& msg, THandler& handler) ->
603 MessageInterfaceDispatchRetType<
604 typename std::decay<decltype(handler)>::type>
605 {
606 using MsgType = typename std::decay<decltype(msg)>::type;
607 static_assert(MsgType::hasGetId(),
608 "The used message object must provide polymorphic ID retrieval function");
609 static_assert(MsgType::hasMsgIdType(),
610 "Message interface class must define its id type");
611 return dispatchInternal<TAllMessages>(msg.getId(), msg, handler, AdjustedTag<TAllMessages, MsgType>());
612 }
613
614 template <typename TAllMessages, typename TId, typename TMsg, typename THandler>
615 static auto dispatch(TId&& id, TMsg& msg, THandler& handler) ->
616 MessageInterfaceDispatchRetType<
617 typename std::decay<decltype(handler)>::type>
618 {
619 using MsgType = typename std::decay<decltype(msg)>::type;
620 static_assert(MsgType::hasMsgIdType(),
621 "Message interface class must define its id type");
622 using MsgIdParamType = typename MsgType::MsgIdParamType;
623 return dispatchInternal<TAllMessages>(static_cast<MsgIdParamType>(id), msg, handler, AdjustedTag<TAllMessages, MsgType>());
624 }
625
626 template <typename TAllMessages, typename TId, typename TMsg, typename THandler>
627 static auto dispatch(TId&& id, std::size_t offset, TMsg& msg, THandler& handler) ->
628 MessageInterfaceDispatchRetType<
629 typename std::decay<decltype(handler)>::type>
630 {
631 using MsgType = typename std::decay<decltype(msg)>::type;
632 static_assert(MsgType::hasMsgIdType(),
633 "Message interface class must define its id type");
634 using MsgIdParamType = typename MsgType::MsgIdParamType;
635 return dispatchInternal<TAllMessages>(static_cast<MsgIdParamType>(id), offset, msg, handler, AdjustedTag<TAllMessages, MsgType>());
636 }
637
638 template <typename TAllMessages, typename TId, typename THandler>
639 static bool dispatchType(TId&& id, THandler& handler)
640 {
641 return dispatchTypeInternal<TAllMessages>(std::forward<TId>(id), handler, BinSearchTag<TAllMessages>());
642 }
643
644 template <typename TAllMessages, typename TId, typename THandler>
645 static bool dispatchType(TId&& id, std::size_t offset, THandler& handler)
646 {
647 return dispatchTypeInternal<TAllMessages>(std::forward<TId>(id), offset, handler, BinSearchTag<TAllMessages>());
648 }
649
650private:
651 template <typename TAllMessages, typename TMsg, typename THandler, typename... TParams>
652 static auto dispatchInternal(typename TMsg::MsgIdParamType id, TMsg& msg, THandler& handler, EmptyTag<TParams...>) ->
653 MessageInterfaceDispatchRetType<
654 typename std::decay<decltype(handler)>::type>
655 {
656 static_cast<void>(id);
657 return handler.handle(msg);
658 }
659
660 template <typename TAllMessages, typename TMsg, typename THandler, typename... TParams>
661 static auto dispatchInternal(typename TMsg::MsgIdParamType id, std::size_t offset, TMsg& msg, THandler& handler, EmptyTag<TParams...>) ->
662 MessageInterfaceDispatchRetType<
663 typename std::decay<decltype(handler)>::type>
664 {
665 static_cast<void>(id);
666 static_cast<void>(offset);
667 return handler.handle(msg);
668 }
669
670 template <typename TAllMessages, typename TMsg, typename THandler, typename... TParams>
671 static auto dispatchInternal(typename TMsg::MsgIdParamType id, TMsg& msg, THandler& handler, StrongTag<TParams...>) ->
672 MessageInterfaceDispatchRetType<
673 typename std::decay<decltype(handler)>::type>
674 {
675 static constexpr std::size_t Count = std::tuple_size<TAllMessages>::value;
676 static constexpr auto HelperType = DispatchMsgHelperIntType<Count>::value;
677 return
678 DispatchMsgStrongLinearSwitchHelper<HelperType>::template
679 dispatch<TAllMessages, Count>(id, msg, handler);
680 }
681
682 template <typename TAllMessages, typename TMsg, typename THandler, typename... TParams>
683 static auto dispatchInternal(typename TMsg::MsgIdParamType id, std::size_t offset, TMsg& msg, THandler& handler, StrongTag<TParams...>) ->
684 MessageInterfaceDispatchRetType<
685 typename std::decay<decltype(handler)>::type>
686 {
687 if (offset != 0U) {
688 using RetType =
689 MessageInterfaceDispatchRetType<
690 typename std::decay<decltype(handler)>::type>;
691 return static_cast<RetType>(handler.handle(msg));
692
693 }
694
695 static constexpr std::size_t Count = std::tuple_size<TAllMessages>::value;
696 static constexpr auto HelperType = DispatchMsgHelperIntType<Count>::value;
697 return
698 DispatchMsgStrongLinearSwitchHelper<HelperType>::template
699 dispatch<TAllMessages, Count>(id, msg, handler);
700
701 }
702
703 template <typename TAllMessages, typename TMsg, typename THandler, typename... TParams>
704 static auto dispatchInternal(typename TMsg::MsgIdParamType id, TMsg& msg, THandler& handler, WeakTag<TParams...>) ->
705 MessageInterfaceDispatchRetType<
706 typename std::decay<decltype(handler)>::type>
707 {
708 return dispatchInternal<TAllMessages>(id, 0U, msg, handler, WeakTag<>());
709 }
710
711 template <typename TAllMessages, typename TMsg, typename THandler, typename... TParams>
712 static auto dispatchInternal(typename TMsg::MsgIdParamType id, std::size_t offset, TMsg& msg, THandler& handler, WeakTag<TParams...>) ->
713 MessageInterfaceDispatchRetType<
714 typename std::decay<decltype(handler)>::type>
715 {
716 static constexpr std::size_t Count = std::tuple_size<TAllMessages>::value;
717 static constexpr auto HelperType = DispatchMsgHelperIntType<Count>::value;
718 return
719 DispatchMsgWeakLinearSwitchHelper<HelperType>::template
720 dispatch<TAllMessages, 0, Count>(id, offset, msg, handler);
721
722 }
723
724 template <typename TAllMessages, typename TId, typename THandler, typename... TParams>
725 static bool dispatchTypeInternal(TId&& id, THandler& handler, EmptyTag<TParams...>)
726 {
727 static_cast<void>(id);
728 static_cast<void>(handler);
729 return false;
730 }
731
732 template <typename TAllMessages, typename TId, typename THandler, typename... TParams>
733 static bool dispatchTypeInternal(TId&& id, std::size_t offset, THandler& handler, EmptyTag<TParams...>)
734 {
735 static_cast<void>(id);
736 static_cast<void>(offset);
737 static_cast<void>(handler);
738 return false;
739 }
740
741 template <typename TAllMessages, typename TId, typename THandler, typename... TParams>
742 static bool dispatchTypeInternal(TId&& id, THandler& handler, StrongTag<TParams...>)
743 {
744 using FirstMsgType = typename std::tuple_element<0, TAllMessages>::type;
745 static_assert(comms::isMessageBase<FirstMsgType>(),
746 "The type in the tuple are expected to be proper messages");
747 static_assert(FirstMsgType::hasMsgIdType(), "The messages must define their ID type");
748 using MsgIdParamType = typename FirstMsgType::MsgIdParamType;
749
750 static constexpr std::size_t Count = std::tuple_size<TAllMessages>::value;
751 static constexpr auto HelperType = DispatchMsgHelperIntType<Count>::value;
752 return
753 DispatchMsgStrongLinearSwitchHelper<HelperType>::template
754 dispatchType<TAllMessages, Count>(static_cast<MsgIdParamType>(id), handler);
755 }
756
757 template <typename TAllMessages, typename TId, typename THandler, typename... TParams>
758 static bool dispatchTypeInternal(TId&& id, std::size_t offset, THandler& handler, StrongTag<TParams...>)
759 {
760 if (offset != 0U) {
761 return false;
762 }
763
764 return dispatchTypeInternal<TAllMessages>(std::forward<TId>(id), handler, StrongTag<TParams...>());
765 }
766
767 template <typename TAllMessages, typename TId, typename THandler, typename... TParams>
768 static bool dispatchTypeInternal(TId&& id, THandler& handler, WeakTag<TParams...>)
769 {
770 return dispatchTypeInternal<TAllMessages>(std::forward<TId>(id), 0U, handler, WeakTag<>());
771 }
772
773 template <typename TAllMessages, typename TId, typename THandler, typename... TParams>
774 static bool dispatchTypeInternal(TId&& id, std::size_t offset, THandler& handler, WeakTag<TParams...>)
775 {
776 using FirstMsgType = typename std::tuple_element<0, TAllMessages>::type;
777 static_assert(comms::isMessageBase<FirstMsgType>(),
778 "The type in the tuple are expected to be proper messages");
779 static_assert(FirstMsgType::hasMsgIdType(), "The messages must define their ID type");
780 using MsgIdParamType = typename FirstMsgType::MsgIdParamType;
781
782 static constexpr std::size_t Count = std::tuple_size<TAllMessages>::value;
783 static constexpr auto HelperType = DispatchMsgHelperIntType<Count>::value;
784 return
785 DispatchMsgWeakLinearSwitchHelper<HelperType>::template
786 dispatchType<TAllMessages, 0, Count>(static_cast<MsgIdParamType>(id), offset, handler);
787 }
788
789};
790
791} // namespace details
792
793} // namespace comms
794
795COMMS_MSVC_WARNING_POP
Contains various compiler related definitions.
Provides common base class for the custom messages with default implementation.
Contains definition of Message object interface and various base classes for custom messages.
comms::option::def::MsgType< TMsg > MsgType
Same as comms::option::def::MsgType.
Definition options.h:1487
Main namespace for all classes / functions of COMMS library.
Replacement to std::conditional.
Definition type_traits.h:29
Replacement to some types from standard type_traits.