COMMS
Template library intended to help with implementation of communication protocols.
Loading...
Searching...
No Matches
GenericHandler.h
Go to the documentation of this file.
1//
2// Copyright 2014 - 2026 (C). Alex Robenko. All rights reserved.
3//
4// SPDX-License-Identifier: MPL-2.0
5//
6// This Source Code Form is subject to the terms of the Mozilla Public
7// License, v. 2.0. If a copy of the MPL was not distributed with this
8// file, You can obtain one at http://mozilla.org/MPL/2.0/.
9
12
13#pragma once
14
15#include "comms/details/tag.h"
16#include "comms/util/Tuple.h"
18
19#include <tuple>
20#include <type_traits>
21
22namespace comms
23{
24
50template <typename TDefault, typename TAll, typename TRetType = void>
52{
53 static_assert(util::IsTuple<TAll>::Value,
54 "TAll must be std::tuple");
55
56#ifdef FOR_DOXYGEN_DOC_ONLY
57public:
59 using RetType = TRetType;
60
63 virtual TRetType handle(TDefault& msg);
64
65protected:
72 ~GenericHandler() noexcept = default;
73#endif
74};
75
77template <
78 typename TDefault,
79 typename T1,
80 typename T2,
81 typename T3,
82 typename T4,
83 typename T5,
84 typename T6,
85 typename T7,
86 typename T8,
87 typename T9,
88 typename T10,
89 typename... TRest,
90 typename TRetType>
91class GenericHandler<TDefault, std::tuple<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, TRest...>, TRetType>
92 : public GenericHandler<TDefault, std::tuple<TRest...>, TRetType>
93{
94 using BaseImpl = GenericHandler<TDefault, std::tuple<TRest...>, TRetType>;
95public:
96
97 using BaseImpl::handle;
98 virtual TRetType handle(T1& msg)
99 {
100 static_assert(std::is_base_of<TDefault, T1>::value,
101 "TDefault must be base class for every element in TAll");
102
103 return this->handle(static_cast<TDefault&>(msg));
104 }
105
106 virtual TRetType handle(T2& msg)
107 {
108 static_assert(std::is_base_of<TDefault, T2>::value,
109 "TDefault must be base class for every element in TAll");
110
111 return this->handle(static_cast<TDefault&>(msg));
112 }
113
114 virtual TRetType handle(T3& msg)
115 {
116 static_assert(std::is_base_of<TDefault, T3>::value,
117 "TDefault must be base class for every element in TAll");
118
119 return this->handle(static_cast<TDefault&>(msg));
120 }
121
122 virtual TRetType handle(T4& msg)
123 {
124 static_assert(std::is_base_of<TDefault, T4>::value,
125 "TDefault must be base class for every element in TAll");
126
127 return this->handle(static_cast<TDefault&>(msg));
128 }
129
130 virtual TRetType handle(T5& msg)
131 {
132 static_assert(std::is_base_of<TDefault, T5>::value,
133 "TDefault must be base class for every element in TAll");
134
135 return this->handle(static_cast<TDefault&>(msg));
136 }
137
138 virtual TRetType handle(T6& msg)
139 {
140 static_assert(std::is_base_of<TDefault, T6>::value,
141 "TDefault must be base class for every element in TAll");
142
143 return this->handle(static_cast<TDefault&>(msg));
144 }
145
146 virtual TRetType handle(T7& msg)
147 {
148 static_assert(std::is_base_of<TDefault, T7>::value,
149 "TDefault must be base class for every element in TAll");
150
151 return this->handle(static_cast<TDefault&>(msg));
152 }
153
154 virtual TRetType handle(T8& msg)
155 {
156 static_assert(std::is_base_of<TDefault, T8>::value,
157 "TDefault must be base class for every element in TAll");
158
159 return this->handle(static_cast<TDefault&>(msg));
160 }
161
162 virtual TRetType handle(T9& msg)
163 {
164 static_assert(std::is_base_of<TDefault, T9>::value,
165 "TDefault must be base class for every element in TAll");
166
167 return this->handle(static_cast<TDefault&>(msg));
168 }
169
170 virtual TRetType handle(T10& msg)
171 {
172 static_assert(std::is_base_of<TDefault, T10>::value,
173 "TDefault must be base class for every element in TAll");
174
175 return this->handle(static_cast<TDefault&>(msg));
176 }
177
178protected:
179 ~GenericHandler() noexcept = default;
180};
181
182namespace details
183{
184
185template <typename TDefault, typename TRetType>
186class GenericHandlerBase
187{
188public:
189 using RetType = TRetType;
190
191 virtual TRetType handle(TDefault& msg)
192 {
193 // Nothing to do
194 static_cast<void>(msg);
195
196 using Tag =
197 typename comms::util::LazyShallowConditional<
198 std::is_void<TRetType>::value
199 >::template Type<
200 VoidReturnTag,
201 RetValueShallowCondWrap
202 >;
203
204 return defaultHandle(Tag());
205 }
206
207private:
208 template <typename... TParams>
209 using VoidReturnTag = comms::details::tag::Tag1<>;
210
211 template <typename... TParams>
212 using ReferenceReturnTag = comms::details::tag::Tag2<>;
213
214 template <typename... TParams>
215 using ValueReturnTag = comms::details::tag::Tag3<>;
216
217 template <typename... TParams>
218 using RetValueShallowCondWrap =
219 typename comms::util::LazyShallowConditional<
220 std::is_lvalue_reference<TRetType>::value
221 >::template Type<
222 ReferenceReturnTag,
223 ValueReturnTag,
224 TParams...
225 >;
226
227 template <typename... TParams>
228 void defaultHandle(VoidReturnTag<TParams...>)
229 {
230 }
231
232 template <typename... TParams>
233 TRetType defaultHandle(ReferenceReturnTag<TParams...>)
234 {
235 static typename std::decay<TRetType>::type Value;
236 return Value;
237 }
238
239 template <typename... TParams>
240 TRetType defaultHandle(ValueReturnTag<TParams...>)
241 {
242 return typename std::decay<TRetType>::type();
243 }
244
245};
246
247} // namespace details
248
249template <
250 typename TDefault,
251 typename T1,
252 typename T2,
253 typename T3,
254 typename T4,
255 typename T5,
256 typename T6,
257 typename T7,
258 typename T8,
259 typename T9,
260 typename TRetType>
261class GenericHandler<TDefault, std::tuple<T1, T2, T3, T4, T5, T6, T7, T8, T9>, TRetType> : public
262 details::GenericHandlerBase<TDefault, TRetType>
263{
264 using BaseImpl = details::GenericHandlerBase<TDefault, TRetType>;
265public:
266
267 using BaseImpl::handle;
268 virtual TRetType handle(T1& msg)
269 {
270 static_assert(std::is_base_of<TDefault, T1>::value,
271 "TDefault must be base class for every element in TAll");
272
273 return this->handle(static_cast<TDefault&>(msg));
274 }
275
276 virtual TRetType handle(T2& msg)
277 {
278 static_assert(std::is_base_of<TDefault, T2>::value,
279 "TDefault must be base class for every element in TAll");
280
281 return this->handle(static_cast<TDefault&>(msg));
282 }
283
284 virtual TRetType handle(T3& msg)
285 {
286 static_assert(std::is_base_of<TDefault, T3>::value,
287 "TDefault must be base class for every element in TAll");
288
289 return this->handle(static_cast<TDefault&>(msg));
290 }
291
292 virtual TRetType handle(T4& msg)
293 {
294 static_assert(std::is_base_of<TDefault, T4>::value,
295 "TDefault must be base class for every element in TAll");
296
297 return this->handle(static_cast<TDefault&>(msg));
298 }
299
300 virtual TRetType handle(T5& msg)
301 {
302 static_assert(std::is_base_of<TDefault, T5>::value,
303 "TDefault must be base class for every element in TAll");
304
305 return this->handle(static_cast<TDefault&>(msg));
306 }
307
308 virtual TRetType handle(T6& msg)
309 {
310 static_assert(std::is_base_of<TDefault, T6>::value,
311 "TDefault must be base class for every element in TAll");
312
313 return this->handle(static_cast<TDefault&>(msg));
314 }
315
316 virtual TRetType handle(T7& msg)
317 {
318 static_assert(std::is_base_of<TDefault, T7>::value,
319 "TDefault must be base class for every element in TAll");
320
321 return this->handle(static_cast<TDefault&>(msg));
322 }
323
324 virtual TRetType handle(T8& msg)
325 {
326 static_assert(std::is_base_of<TDefault, T8>::value,
327 "TDefault must be base class for every element in TAll");
328
329 return this->handle(static_cast<TDefault&>(msg));
330 }
331
332 virtual TRetType handle(T9& msg)
333 {
334 static_assert(std::is_base_of<TDefault, T9>::value,
335 "TDefault must be base class for every element in TAll");
336
337 return this->handle(static_cast<TDefault&>(msg));
338 }
339
340protected:
341 ~GenericHandler() noexcept = default;
342};
343
344template <
345 typename TDefault,
346 typename T1,
347 typename T2,
348 typename T3,
349 typename T4,
350 typename T5,
351 typename T6,
352 typename T7,
353 typename T8,
354 typename TRetType>
355class GenericHandler<TDefault, std::tuple<T1, T2, T3, T4, T5, T6, T7, T8>, TRetType> : public
356 details::GenericHandlerBase<TDefault, TRetType>
357{
358 using BaseImpl = details::GenericHandlerBase<TDefault, TRetType>;
359public:
360
361 using BaseImpl::handle;
362 virtual TRetType handle(T1& msg)
363 {
364 static_assert(std::is_base_of<TDefault, T1>::value,
365 "TDefault must be base class for every element in TAll");
366
367 return this->handle(static_cast<TDefault&>(msg));
368 }
369
370 virtual TRetType handle(T2& msg)
371 {
372 static_assert(std::is_base_of<TDefault, T2>::value,
373 "TDefault must be base class for every element in TAll");
374
375 return this->handle(static_cast<TDefault&>(msg));
376 }
377
378 virtual TRetType handle(T3& msg)
379 {
380 static_assert(std::is_base_of<TDefault, T3>::value,
381 "TDefault must be base class for every element in TAll");
382
383 return this->handle(static_cast<TDefault&>(msg));
384 }
385
386 virtual TRetType handle(T4& msg)
387 {
388 static_assert(std::is_base_of<TDefault, T4>::value,
389 "TDefault must be base class for every element in TAll");
390
391 return this->handle(static_cast<TDefault&>(msg));
392 }
393
394 virtual TRetType handle(T5& msg)
395 {
396 static_assert(std::is_base_of<TDefault, T5>::value,
397 "TDefault must be base class for every element in TAll");
398
399 return this->handle(static_cast<TDefault&>(msg));
400 }
401
402 virtual TRetType handle(T6& msg)
403 {
404 static_assert(std::is_base_of<TDefault, T6>::value,
405 "TDefault must be base class for every element in TAll");
406
407 return this->handle(static_cast<TDefault&>(msg));
408 }
409
410 virtual TRetType handle(T7& msg)
411 {
412 static_assert(std::is_base_of<TDefault, T7>::value,
413 "TDefault must be base class for every element in TAll");
414
415 return this->handle(static_cast<TDefault&>(msg));
416 }
417
418 virtual TRetType handle(T8& msg)
419 {
420 static_assert(std::is_base_of<TDefault, T8>::value,
421 "TDefault must be base class for every element in TAll");
422
423 return this->handle(static_cast<TDefault&>(msg));
424 }
425
426protected:
427 ~GenericHandler() noexcept = default;
428};
429
430template <
431 typename TDefault,
432 typename T1,
433 typename T2,
434 typename T3,
435 typename T4,
436 typename T5,
437 typename T6,
438 typename T7,
439 typename TRetType>
440class GenericHandler<TDefault, std::tuple<T1, T2, T3, T4, T5, T6, T7>, TRetType> : public
441 details::GenericHandlerBase<TDefault, TRetType>
442{
443 using BaseImpl = details::GenericHandlerBase<TDefault, TRetType>;
444public:
445
446 using BaseImpl::handle;
447 virtual TRetType handle(T1& msg)
448 {
449 static_assert(std::is_base_of<TDefault, T1>::value,
450 "TDefault must be base class for every element in TAll");
451
452 return this->handle(static_cast<TDefault&>(msg));
453 }
454
455 virtual TRetType handle(T2& msg)
456 {
457 static_assert(std::is_base_of<TDefault, T2>::value,
458 "TDefault must be base class for every element in TAll");
459
460 return this->handle(static_cast<TDefault&>(msg));
461 }
462
463 virtual TRetType handle(T3& msg)
464 {
465 static_assert(std::is_base_of<TDefault, T3>::value,
466 "TDefault must be base class for every element in TAll");
467
468 return this->handle(static_cast<TDefault&>(msg));
469 }
470
471 virtual TRetType handle(T4& msg)
472 {
473 static_assert(std::is_base_of<TDefault, T4>::value,
474 "TDefault must be base class for every element in TAll");
475
476 return this->handle(static_cast<TDefault&>(msg));
477 }
478
479 virtual TRetType handle(T5& msg)
480 {
481 static_assert(std::is_base_of<TDefault, T5>::value,
482 "TDefault must be base class for every element in TAll");
483
484 return this->handle(static_cast<TDefault&>(msg));
485 }
486
487 virtual TRetType handle(T6& msg)
488 {
489 static_assert(std::is_base_of<TDefault, T6>::value,
490 "TDefault must be base class for every element in TAll");
491
492 return this->handle(static_cast<TDefault&>(msg));
493 }
494
495 virtual TRetType handle(T7& msg)
496 {
497 static_assert(std::is_base_of<TDefault, T7>::value,
498 "TDefault must be base class for every element in TAll");
499
500 return this->handle(static_cast<TDefault&>(msg));
501 }
502
503protected:
504 ~GenericHandler() noexcept = default;
505};
506
507template <
508 typename TDefault,
509 typename T1,
510 typename T2,
511 typename T3,
512 typename T4,
513 typename T5,
514 typename T6,
515 typename TRetType>
516class GenericHandler<TDefault, std::tuple<T1, T2, T3, T4, T5, T6>, TRetType> : public
517 details::GenericHandlerBase<TDefault, TRetType>
518{
519 using BaseImpl = details::GenericHandlerBase<TDefault, TRetType>;
520public:
521
522 using BaseImpl::handle;
523 virtual TRetType handle(T1& msg)
524 {
525 static_assert(std::is_base_of<TDefault, T1>::value,
526 "TDefault must be base class for every element in TAll");
527
528 return this->handle(static_cast<TDefault&>(msg));
529 }
530
531 virtual TRetType handle(T2& msg)
532 {
533 static_assert(std::is_base_of<TDefault, T2>::value,
534 "TDefault must be base class for every element in TAll");
535
536 return this->handle(static_cast<TDefault&>(msg));
537 }
538
539 virtual TRetType handle(T3& msg)
540 {
541 static_assert(std::is_base_of<TDefault, T3>::value,
542 "TDefault must be base class for every element in TAll");
543
544 return this->handle(static_cast<TDefault&>(msg));
545 }
546
547 virtual TRetType handle(T4& msg)
548 {
549 static_assert(std::is_base_of<TDefault, T4>::value,
550 "TDefault must be base class for every element in TAll");
551
552 return this->handle(static_cast<TDefault&>(msg));
553 }
554
555 virtual TRetType handle(T5& msg)
556 {
557 static_assert(std::is_base_of<TDefault, T5>::value,
558 "TDefault must be base class for every element in TAll");
559
560 return this->handle(static_cast<TDefault&>(msg));
561 }
562
563 virtual TRetType handle(T6& msg)
564 {
565 static_assert(std::is_base_of<TDefault, T6>::value,
566 "TDefault must be base class for every element in TAll");
567
568 return this->handle(static_cast<TDefault&>(msg));
569 }
570
571protected:
572 ~GenericHandler() noexcept = default;
573};
574
575template <
576 typename TDefault,
577 typename T1,
578 typename T2,
579 typename T3,
580 typename T4,
581 typename T5,
582 typename TRetType>
583class GenericHandler<TDefault, std::tuple<T1, T2, T3, T4, T5>, TRetType> : public
584 details::GenericHandlerBase<TDefault, TRetType>
585{
586 using BaseImpl = details::GenericHandlerBase<TDefault, TRetType>;
587public:
588
589 using BaseImpl::handle;
590 virtual TRetType handle(T1& msg)
591 {
592 static_assert(std::is_base_of<TDefault, T1>::value,
593 "TDefault must be base class for every element in TAll");
594
595 return this->handle(static_cast<TDefault&>(msg));
596 }
597
598 virtual TRetType handle(T2& msg)
599 {
600 static_assert(std::is_base_of<TDefault, T2>::value,
601 "TDefault must be base class for every element in TAll");
602
603 return this->handle(static_cast<TDefault&>(msg));
604 }
605
606 virtual TRetType handle(T3& msg)
607 {
608 static_assert(std::is_base_of<TDefault, T3>::value,
609 "TDefault must be base class for every element in TAll");
610
611 return this->handle(static_cast<TDefault&>(msg));
612 }
613
614 virtual TRetType handle(T4& msg)
615 {
616 static_assert(std::is_base_of<TDefault, T4>::value,
617 "TDefault must be base class for every element in TAll");
618
619 return this->handle(static_cast<TDefault&>(msg));
620 }
621
622 virtual TRetType handle(T5& msg)
623 {
624 static_assert(std::is_base_of<TDefault, T5>::value,
625 "TDefault must be base class for every element in TAll");
626
627 return this->handle(static_cast<TDefault&>(msg));
628 }
629
630protected:
631 ~GenericHandler() noexcept = default;
632};
633
634template <
635 typename TDefault,
636 typename T1,
637 typename T2,
638 typename T3,
639 typename T4,
640 typename TRetType>
641class GenericHandler<TDefault, std::tuple<T1, T2, T3, T4>, TRetType> : public
642 details::GenericHandlerBase<TDefault, TRetType>
643{
644 using BaseImpl = details::GenericHandlerBase<TDefault, TRetType>;
645public:
646
647 using BaseImpl::handle;
648 virtual TRetType handle(T1& msg)
649 {
650 static_assert(std::is_base_of<TDefault, T1>::value,
651 "TDefault must be base class for every element in TAll");
652
653 return this->handle(static_cast<TDefault&>(msg));
654 }
655
656 virtual TRetType handle(T2& msg)
657 {
658 static_assert(std::is_base_of<TDefault, T2>::value,
659 "TDefault must be base class for every element in TAll");
660
661 return this->handle(static_cast<TDefault&>(msg));
662 }
663
664 virtual TRetType handle(T3& msg)
665 {
666 static_assert(std::is_base_of<TDefault, T3>::value,
667 "TDefault must be base class for every element in TAll");
668
669 return this->handle(static_cast<TDefault&>(msg));
670 }
671
672 virtual TRetType handle(T4& msg)
673 {
674 static_assert(std::is_base_of<TDefault, T4>::value,
675 "TDefault must be base class for every element in TAll");
676
677 return this->handle(static_cast<TDefault&>(msg));
678 }
679
680protected:
681 ~GenericHandler() noexcept = default;
682};
683
684template <typename TDefault, typename T1, typename T2, typename T3, typename TRetType>
685class GenericHandler<TDefault, std::tuple<T1, T2, T3>, TRetType> : public
686 details::GenericHandlerBase<TDefault, TRetType>
687{
688 using BaseImpl = details::GenericHandlerBase<TDefault, TRetType>;
689public:
690
691 using BaseImpl::handle;
692 virtual TRetType handle(T1& msg)
693 {
694 static_assert(std::is_base_of<TDefault, T1>::value,
695 "TDefault must be base class for every element in TAll");
696
697 return this->handle(static_cast<TDefault&>(msg));
698 }
699
700 virtual TRetType handle(T2& msg)
701 {
702 static_assert(std::is_base_of<TDefault, T2>::value,
703 "TDefault must be base class for every element in TAll");
704
705 return this->handle(static_cast<TDefault&>(msg));
706 }
707
708 virtual TRetType handle(T3& msg)
709 {
710 static_assert(std::is_base_of<TDefault, T3>::value,
711 "TDefault must be base class for every element in TAll");
712
713 return this->handle(static_cast<TDefault&>(msg));
714 }
715
716protected:
717 ~GenericHandler() noexcept = default;
718};
719
720template <typename TDefault, typename T1, typename T2, typename TRetType>
721class GenericHandler<TDefault, std::tuple<T1, T2>, TRetType> : public
722 details::GenericHandlerBase<TDefault, TRetType>
723{
724 using BaseImpl = details::GenericHandlerBase<TDefault, TRetType>;
725public:
726
727 using BaseImpl::handle;
728 virtual TRetType handle(T1& msg)
729 {
730 static_assert(std::is_base_of<TDefault, T1>::value,
731 "TDefault must be base class for every element in TAll");
732
733 return this->handle(static_cast<TDefault&>(msg));
734 }
735
736 virtual TRetType handle(T2& msg)
737 {
738 static_assert(std::is_base_of<TDefault, T2>::value,
739 "TDefault must be base class for every element in TAll");
740
741 return this->handle(static_cast<TDefault&>(msg));
742 }
743
744protected:
745 ~GenericHandler() noexcept = default;
746};
747
748template <typename TDefault, typename T1, typename TRetType>
749class GenericHandler<TDefault, std::tuple<T1>, TRetType> : public
750 details::GenericHandlerBase<TDefault, TRetType>
751{
752 using BaseImpl = details::GenericHandlerBase<TDefault, TRetType>;
753public:
754
755 using BaseImpl::handle;
756 virtual TRetType handle(T1& msg)
757 {
758 static_assert(std::is_base_of<TDefault, T1>::value,
759 "TDefault must be base class for every element in TAll");
760
761 return this->handle(static_cast<TDefault&>(msg));
762 }
763
764protected:
765 ~GenericHandler() noexcept = default;
766};
767
768template <typename TDefault, typename TRetType>
769class GenericHandler<TDefault, std::tuple<>, TRetType> : public
770 details::GenericHandlerBase<TDefault, TRetType>
771{
772 using BaseImpl = details::GenericHandlerBase<TDefault, TRetType>;
773public:
774 using BaseImpl::handle;
775protected:
776 ~GenericHandler() noexcept = default;
777};
778
780
781} // namespace comms
782
Contains various tuple type manipulation classes and functions.
Generic common message handler.
Definition GenericHandler.h:52
~GenericHandler() noexcept=default
Destructor.
virtual TRetType handle(TDefault &msg)
Handle message object.
TRetType RetType
Return type of every handle() member function.
Definition GenericHandler.h:59
Main namespace for all classes / functions of COMMS library.
STL namespace.
Check whether provided type is a variant of std::tuple.
Definition Tuple.h:39
Replacement to some types from standard type_traits.