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