COMMS
Template library intended to help with implementation of communication protocols.
Tuple.h
Go to the documentation of this file.
1 //
2 // Copyright 2013 - 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 <utility>
15 #include <type_traits>
16 
17 #include "comms/CompileControl.h"
18 #include "comms/util/type_traits.h"
19 #include "comms/Assert.h"
20 
21 COMMS_GNU_WARNING_PUSH
22 COMMS_GNU_WARNING_DISABLE("-Wtype-limits")
23 
24 namespace comms
25 {
26 
27 namespace util
28 {
29 
33 template <typename TType>
34 struct IsTuple
35 {
38  static constexpr bool Value = false;
39 };
40 
42 template <typename... TArgs>
43 struct IsTuple<std::tuple<TArgs...> >
44 {
45  static constexpr bool Value = true;
46 };
48 
52 template <typename TType>
53 constexpr bool isTuple()
54 {
55  return IsTuple<TType>::Value;
56 }
57 
58 //----------------------------------------
59 
60 namespace details
61 {
62 
63 template <bool THasElems, typename...>
64 struct IsInTupleHelper // <true>
65 {
66  template <typename TType, typename TFirst, typename... TRest>
67  using Type =
68  typename comms::util::Conditional<
69  std::is_same<TType, TFirst>::value
70  >::template Type<
71  std::true_type,
72  typename IsInTupleHelper<(sizeof...(TRest) != 0U)>::template Type<TType, TRest...>
73  >;
74 };
75 
76 template <typename... TParams>
77 struct IsInTupleHelper<false, TParams...>
78 {
79  template <typename TType, typename...>
80  using Type = std::false_type;
81 };
82 
83 } // namespace details
84 
93 template <typename TTuple>
94 struct IsInTuple;
95 
97 
98 template <typename... TTypes>
99 struct IsInTuple<std::tuple<TTypes...> >
100 {
101  template <typename TType>
102  using Type =
103  typename details::IsInTupleHelper<(sizeof...(TTypes) != 0U)>::template Type<TType, TTypes...>;
104 };
105 
107 
108 //----------------------------------------
109 
110 namespace details
111 {
112 
113 template <bool THasElems, typename...>
114 class TupleAsAlignedUnionHelper // <true>
115 {
116  template <typename TElem>
117  using ElemAlignmentType = std::integral_constant<std::size_t, alignof(TElem)>;
118 
119  template <typename TElem>
120  using ElemSizeType = std::integral_constant<std::size_t, sizeof(TElem)>;
121 
122 public:
123  template <typename TElem, typename... TRest>
124  using AlignmentType =
125  comms::util::IntMaxBinaryOp<>::template Type<
126  ElemAlignmentType<TElem>,
127  typename TupleAsAlignedUnionHelper<(0U < sizeof...(TRest))>::template AlignmentType<TRest...>
128  >;
129 
130  template <typename TElem, typename... TRest>
131  using SizeType =
132  comms::util::IntMaxBinaryOp<>::template Type<
133  ElemSizeType<TElem>,
134  typename TupleAsAlignedUnionHelper<(0U < sizeof...(TRest))>::template SizeType<TRest...>
135  >;
136 };
137 
138 template <typename... TParams>
139 class TupleAsAlignedUnionHelper<false, TParams...>
140 {
141 public:
142  template <typename...>
143  using AlignmentType = std::integral_constant<std::size_t, 0U>;
144 
145  template <typename...>
146  using SizeType = std::integral_constant<std::size_t, 0U>;
147 };
148 
149 } // namespace details
150 
155 template <typename TTuple>
157 {
159  static_assert(IsTuple<TTuple>::Value, "TTuple must be std::tuple");
161 
165  using Type = void;
166 };
167 
169 template <typename... TTypes>
170 class TupleAsAlignedUnion<std::tuple<TTypes...> >
171 {
172  using AlignmentType =
173  typename details::TupleAsAlignedUnionHelper<(0U < sizeof...(TTypes))>::template AlignmentType<TTypes...>;
174 
175  using SizeType =
176  typename details::TupleAsAlignedUnionHelper<(0U < sizeof...(TTypes))>::template SizeType<TTypes...>;
177 public:
178  using Type =
179  typename std::aligned_storage<
180  SizeType::value,
181  AlignmentType::value
182  >::type;
183 };
185 
187 template <typename TTuple>
189 
190 //----------------------------------------
191 
192 namespace details
193 {
194 
195 template <bool THasElems>
196 struct TupleForEachHelper
197 {
198  template <std::size_t TOff, std::size_t TRem, typename TTuple, typename TFunc>
199  static void exec(TTuple&& tuple, TFunc&& func)
200  {
201  using Tuple = typename std::decay<TTuple>::type;
202  static_assert(IsTuple<Tuple>::Value, "TTuple must be std::tuple");
203  static constexpr std::size_t TupleSize = std::tuple_size<Tuple>::value;
204  static constexpr std::size_t OffsetedRem = TRem + TOff;
205  static_assert(OffsetedRem <= TupleSize, "Incorrect parameters");
206 
207  static constexpr std::size_t Idx = TupleSize - OffsetedRem;
208  static constexpr std::size_t NextRem = TRem - 1;
209  static constexpr bool HasElemsToProcess = (NextRem != 0U);
210  func(std::get<Idx>(std::forward<TTuple>(tuple)));
211  TupleForEachHelper<HasElemsToProcess>::template exec<TOff, NextRem>(
212  std::forward<TTuple>(tuple),
213  std::forward<TFunc>(func));
214  }
215 };
216 
217 template <>
218 struct TupleForEachHelper<false>
219 {
220  template <std::size_t TOff, std::size_t TRem, typename TTuple, typename TFunc>
221  static void exec(TTuple&& tuple, TFunc&& func)
222  {
223  static_cast<void>(tuple);
224  static_cast<void>(func);
225  }
226 };
227 
228 } // namespace details
229 
241 template <typename TTuple, typename TFunc>
242 void tupleForEach(TTuple&& tuple, TFunc&& func)
243 {
244  using Tuple = typename std::decay<TTuple>::type;
245  static constexpr std::size_t TupleSize = std::tuple_size<Tuple>::value;
246  static constexpr bool HasTupleElems = (TupleSize != 0U);
247 
248  details::TupleForEachHelper<HasTupleElems>::template exec<0, TupleSize>(
249  std::forward<TTuple>(tuple),
250  std::forward<TFunc>(func));
251 }
252 
262 template <std::size_t TIdx, typename TTuple, typename TFunc>
263 void tupleForEachUntil(TTuple&& tuple, TFunc&& func)
264 {
265  using Tuple = typename std::decay<TTuple>::type;
266  static constexpr std::size_t TupleSize = std::tuple_size<Tuple>::value;
267  static_assert(TIdx <= TupleSize,
268  "The index is too big.");
269 
270  static constexpr bool HasTupleElems = (TIdx != 0U);
271 
272  details::TupleForEachHelper<HasTupleElems>::template exec<TupleSize - TIdx, TIdx>(
273  std::forward<TTuple>(tuple),
274  std::forward<TFunc>(func));
275 }
276 
285 template <std::size_t TIdx, typename TTuple, typename TFunc>
286 void tupleForEachFrom(TTuple&& tuple, TFunc&& func)
287 {
288  using Tuple = typename std::decay<TTuple>::type;
289  static constexpr std::size_t TupleSize = std::tuple_size<Tuple>::value;
290  static_assert(TIdx <= TupleSize,
291  "The index is too big.");
292  static constexpr std::size_t RemCount = TupleSize - TIdx;
293  static constexpr bool HasTupleElems = (RemCount != 0U);
294 
295  details::TupleForEachHelper<HasTupleElems>::template exec<0, RemCount>(
296  std::forward<TTuple>(tuple),
297  std::forward<TFunc>(func));
298 }
299 
311 template <std::size_t TFromIdx, std::size_t TUntilIdx, typename TTuple, typename TFunc>
312 void tupleForEachFromUntil(TTuple&& tuple, TFunc&& func)
313 {
314  using Tuple = typename std::decay<TTuple>::type;
315  static constexpr std::size_t TupleSize = std::tuple_size<Tuple>::value;
316  static_assert(TFromIdx <= TupleSize,
317  "The from index is too big.");
318 
319  static_assert(TUntilIdx <= TupleSize,
320  "The until index is too big.");
321 
322  static_assert(TFromIdx <= TUntilIdx,
323  "The from index must be less than until index.");
324 
325  static constexpr std::size_t FieldsCount = TUntilIdx - TFromIdx;
326  static constexpr bool HasTupleElems = (FieldsCount != 0U);
327 
328  details::TupleForEachHelper<HasTupleElems>::template exec<TupleSize - TUntilIdx, FieldsCount>(
329  std::forward<TTuple>(tuple),
330  std::forward<TFunc>(func));
331 }
332 //----------------------------------------
333 
334 namespace details
335 {
336 
337 template <bool THasElems>
338 struct TupleForEachTypeHelper
339 {
340  template <std::size_t TRem, typename TTuple, typename TFunc>
341  static void exec(TFunc&& func)
342  {
343  using Tuple = typename std::decay<TTuple>::type;
344  static_assert(IsTuple<Tuple>::Value, "TTuple must be std::tuple");
345  static constexpr std::size_t TupleSize = std::tuple_size<Tuple>::value;
346  static_assert(TRem <= TupleSize, "Incorrect TRem");
347 
348  static constexpr std::size_t Idx = TupleSize - TRem;
349  static constexpr std::size_t NextRem = TRem - 1U;
350  static constexpr bool NextHasElems = (NextRem != 0U);
351 
352  using ElemType = typename std::tuple_element<Idx, Tuple>::type;
353 #if COMMS_IS_MSVC
354  // VS compiler
355  func.operator()<ElemType>();
356 #else // #if COMMS_IS_MSVC
357  func.template operator()<ElemType>();
358 #endif // #if COMMS_IS_MSVC
359  TupleForEachTypeHelper<NextHasElems>::template exec<NextRem, TTuple>(
360  std::forward<TFunc>(func));
361  }
362 };
363 
364 template <>
365 struct TupleForEachTypeHelper<false>
366 {
367  template <std::size_t TRem, typename TTuple, typename TFunc>
368  static void exec(TFunc&& func)
369  {
370  static_cast<void>(func);
371  }
372 };
373 
374 } // namespace details
375 
386 template <typename TTuple, typename TFunc>
387 void tupleForEachType(TFunc&& func)
388 {
389  using Tuple = typename std::decay<TTuple>::type;
390  static constexpr std::size_t TupleSize = std::tuple_size<Tuple>::value;
391  static constexpr bool HasElems = (TupleSize != 0U);
392 
393  details::TupleForEachTypeHelper<HasElems>::template exec<TupleSize, Tuple>(
394  std::forward<TFunc>(func));
395 }
396 //----------------------------------------
397 
398 
399 namespace details
400 {
401 
402 template <bool THasElems>
403 struct TupleForEachWithIdxHelper
404 {
405  template <std::size_t TRem, typename TTuple, typename TFunc>
406  static void exec(TTuple&& tuple, TFunc&& func)
407  {
408  using Tuple = typename std::decay<TTuple>::type;
409  static_assert(IsTuple<Tuple>::Value, "TTuple must be std::tuple");
410  static constexpr std::size_t TupleSize = std::tuple_size<Tuple>::value;
411  static_assert(TRem <= TupleSize, "Incorrect TRem");
412 
413  static constexpr std::size_t Idx = TupleSize - TRem;
414  static constexpr std::size_t NextRem = TRem - 1;
415  static constexpr bool NextHasElems = (NextRem != 0U);
416 
417  func(std::get<Idx>(std::forward<TTuple>(tuple)), Idx);
418  TupleForEachWithIdxHelper<NextHasElems>::template exec<NextRem>(
419  std::forward<TTuple>(tuple),
420  std::forward<TFunc>(func));
421  }
422 };
423 
424 template <>
425 struct TupleForEachWithIdxHelper<false>
426 {
427  template <std::size_t TRem, typename TTuple, typename TFunc>
428  static void exec(TTuple&& tuple, TFunc&& func)
429  {
430  static_cast<void>(tuple);
431  static_cast<void>(func);
432  }
433 };
434 
435 } // namespace details
436 
451 template <typename TTuple, typename TFunc>
452 void tupleForEachWithIdx(TTuple&& tuple, TFunc&& func)
453 {
454  using Tuple = typename std::decay<TTuple>::type;
455  static constexpr std::size_t TupleSize = std::tuple_size<Tuple>::value;
456  static constexpr bool HasElems = (TupleSize != 0U);
457 
458  details::TupleForEachWithIdxHelper<HasElems>::template exec<TupleSize>(
459  std::forward<TTuple>(tuple),
460  std::forward<TFunc>(func));
461 }
462 
463 namespace details
464 {
465 
466 template <bool THasElems>
467 struct TupleForEachWithTemplateParamIdxHelper
468 {
469  template <std::size_t TRem, typename TTuple, typename TFunc>
470  static void exec(TTuple&& tuple, TFunc&& func)
471  {
472  using Tuple = typename std::decay<TTuple>::type;
473  static_assert(IsTuple<Tuple>::Value, "TTuple must be std::tuple");
474  static constexpr std::size_t TupleSize = std::tuple_size<Tuple>::value;
475  static_assert(TRem <= TupleSize, "Incorrect TRem");
476 
477  static constexpr std::size_t Idx = TupleSize - TRem;
478  static constexpr std::size_t NextRem = TRem - 1;
479  static constexpr bool NextHasElems = (NextRem != 0U);
480 
481 #if COMMS_IS_MSVC
482  // VS compiler
483  func.operator()<Idx>(std::get<Idx>(std::forward<TTuple>(tuple)));
484 #else // #if COMMS_IS_MSVC
485  func.template operator()<Idx>(std::get<Idx>(std::forward<TTuple>(tuple)));
486 #endif // #if COMMS_IS_MSVC
487  TupleForEachWithTemplateParamIdxHelper<NextHasElems>::template exec<NextRem>(
488  std::forward<TTuple>(tuple),
489  std::forward<TFunc>(func));
490  }
491 };
492 
493 template <>
494 struct TupleForEachWithTemplateParamIdxHelper<false>
495 {
496  template <std::size_t TRem, typename TTuple, typename TFunc>
497  static void exec(TTuple&& tuple, TFunc&& func)
498  {
499  static_cast<void>(tuple);
500  static_cast<void>(func);
501  }
502 };
503 
504 } // namespace details
505 
521 
522 template <typename TTuple, typename TFunc>
523 void tupleForEachWithTemplateParamIdx(TTuple&& tuple, TFunc&& func)
524 {
525  using Tuple = typename std::decay<TTuple>::type;
526  static constexpr std::size_t TupleSize = std::tuple_size<Tuple>::value;
527  static constexpr bool HasElems = (TupleSize != 0U);
528 
529  details::TupleForEachWithTemplateParamIdxHelper<HasElems>::template exec<TupleSize>(
530  std::forward<TTuple>(tuple),
531  std::forward<TFunc>(func));
532 }
533 
534 
535 //----------------------------------------
536 
537 namespace details
538 {
539 
540 template <bool THasElems>
541 struct TupleAccumulateHelper
542 {
543  template <std::size_t TOff, std::size_t TRem, typename TTuple, typename TValue, typename TFunc>
544  static constexpr TValue exec(TTuple&& tuple, const TValue& value, TFunc&& func)
545  {
546  using Tuple = typename std::decay<TTuple>::type;
547  static_assert(IsTuple<Tuple>::Value, "TTuple must be std::tuple");
548  static_assert((TOff + TRem) <= std::tuple_size<Tuple>::value, "Incorrect params");
549 
550  return
551  TupleAccumulateHelper<(1U < TRem)>::template exec<TOff + 1, TRem - 1U>(
552  std::forward<TTuple>(tuple),
553  func(value, std::get<TOff>(std::forward<TTuple>(tuple))),
554  std::forward<TFunc>(func));
555  }
556 };
557 
558 template <>
559 struct TupleAccumulateHelper<false>
560 {
561  template <std::size_t TOff, std::size_t TRem, typename TTuple, typename TValue, typename TFunc>
562  static constexpr TValue exec(TTuple&& /* tuple */, const TValue& value, TFunc&& /* func */)
563  {
564  return value;
565  }
566 };
567 
568 } // namespace details
569 
588 template <typename TTuple, typename TValue, typename TFunc>
589 constexpr TValue tupleAccumulate(TTuple&& tuple, const TValue& value, TFunc&& func)
590 {
591  using Tuple = typename std::decay<TTuple>::type;
592 
593  return details::TupleAccumulateHelper<std::tuple_size<Tuple>::value != 0>::template exec<0, std::tuple_size<Tuple>::value>(
594  std::forward<TTuple>(tuple),
595  value,
596  std::forward<TFunc>(func));
597 }
598 
616 template <std::size_t TFrom, std::size_t TUntil, typename TTuple, typename TValue, typename TFunc>
617 constexpr TValue tupleAccumulateFromUntil(TTuple&& tuple, const TValue& value, TFunc&& func)
618 {
619  using Tuple = typename std::decay<TTuple>::type;
620 
621  static_assert(TFrom <= TUntil, "TFrom mustn't be greater that TUntil");
622  static_assert(TUntil <= std::tuple_size<Tuple>::value, "TUntil mustn't exceed size of the tuple");
623 
624  return details::TupleAccumulateHelper<(TFrom < TUntil)>::template exec<TFrom, TUntil - TFrom>(
625  std::forward<TTuple>(tuple),
626  value,
627  std::forward<TFunc>(func));
628 }
629 
630 //----------------------------------------
631 
632 namespace details
633 {
634 
635 template <bool THasElems>
636 class TupleTypeAccumulateHelper
637 {
638 
639 public:
640  template <std::size_t TOff, std::size_t TRem, typename TTuple, typename TValue, typename TFunc>
641  static constexpr TValue exec(const TValue& value, TFunc&& func)
642  {
643  using Tuple = typename std::decay<TTuple>::type;
644  static_assert(IsTuple<Tuple>::Value, "TTuple must be std::tuple");
645  static_assert((TOff + TRem) <= std::tuple_size<Tuple>::value, "Incorrect TRem");
646 
647  return TupleTypeAccumulateHelper<(1U < TRem)>::template exec<TOff + 1, TRem - 1, Tuple>(
648 #if COMMS_IS_MSVC
649  func.operator()
650 #else // #if COMMS_IS_MSVC
651  func.template operator()
652 #endif // #if COMMS_IS_MSVC
653  <typename std::tuple_element<TOff, Tuple>::type>(value),
654  std::forward<TFunc>(func));
655  }
656 
657 };
658 
659 template <>
660 class TupleTypeAccumulateHelper<false>
661 {
662 
663 public:
664  template <std::size_t TOff, std::size_t TRem, typename TTuple, typename TValue, typename TFunc>
665  static constexpr TValue exec(const TValue& value, TFunc&& /* func */)
666  {
667  return value;
668  }
669 };
670 
671 } // namespace details
672 
687 template <typename TTuple, typename TValue, typename TFunc>
688 constexpr TValue tupleTypeAccumulate(const TValue& value, TFunc&& func)
689 {
690  using Tuple = typename std::decay<TTuple>::type;
691  return
692  details::TupleTypeAccumulateHelper<
693  (0U < std::tuple_size<Tuple>::value)
694  >::template exec<0, std::tuple_size<Tuple>::value, Tuple>(
695  value,
696  std::forward<TFunc>(func));
697 }
698 
715 template <std::size_t TFrom, std::size_t TUntil, typename TTuple, typename TValue, typename TFunc>
716 constexpr TValue tupleTypeAccumulateFromUntil(const TValue& value, TFunc&& func)
717 {
718  using Tuple = typename std::decay<TTuple>::type;
719  static_assert(TFrom <= TUntil, "TFrom mustn't be greater that TUntil");
720  static_assert(TUntil <= std::tuple_size<Tuple>::value, "TUntil mustn't exceed size of the tuple");
721  return
722  details::TupleTypeAccumulateHelper<
723  (TFrom < TUntil)
724  >::template exec<TFrom, TUntil - TFrom, Tuple>(
725  value,
726  std::forward<TFunc>(func));
727 }
728 
729 
730 //----------------------------------------
731 
732 
736 template <typename TFirst, typename TSecond>
737 struct TupleCat
738 {
739  static_assert(IsTuple<TFirst>::Value, "TFirst must be tuple");
740  static_assert(IsTuple<TSecond>::Value, "TSecond must be tuple");
741 
743  using Type = typename std::decay<decltype(std::tuple_cat(std::declval<TFirst>(), std::declval<TSecond>()))>::type;
744 };
745 
748 template <typename TField, typename TTuple>
750 
751 //----------------------------------------
752 
753 namespace details
754 {
755 
756 template <bool THasElems>
757 struct TupleSelectedTypeHelper;
758 
759 template <>
760 struct TupleSelectedTypeHelper<false>
761 {
762  template <std::size_t TFromIdx, std::size_t TToIdx, std::size_t TCount, typename TTuple, typename TFunc>
763  static void exec(std::size_t idx, TFunc&& func)
764  {
765  static_assert((TFromIdx + 1) == TToIdx, "Internal error: Bad parameters");
766  static_assert(TCount == 1, "Internal error: Bad parameters");
767  static_cast<void>(idx);
768  COMMS_ASSERT(idx == TFromIdx);
769  using ElemType = typename std::tuple_element<TFromIdx, TTuple>::type;
770 #if COMMS_IS_MSVC
771  // VS compiler
772  func.operator()<TFromIdx, ElemType>();
773 #else // #if COMMS_IS_MSVC
774  func.template operator()<TFromIdx, ElemType>();
775 #endif // #if COMMS_IS_MSVC
776  }
777 };
778 
779 template <bool THasElems>
780 struct TupleSelectedTypeHelper
781 {
782  template <std::size_t TFromIdx, std::size_t TToIdx, std::size_t TCount, typename TTuple, typename TFunc>
783  static void exec(std::size_t idx, TFunc&& func)
784  {
785  static_assert(1U < TCount, "Internal error: Bad parameters");
786  static_assert(TCount == (TToIdx - TFromIdx), "Internal error: Bad parameters");
787  static_assert(TFromIdx < TToIdx, "Internal error: Bad parameters");
788 
789  using Tuple = typename std::decay<TTuple>::type;
790  static_assert(IsTuple<Tuple>::Value, "TTuple must be std::tuple");
791  static constexpr std::size_t TupleSize = std::tuple_size<Tuple>::value;
792  static_assert(TCount <= TupleSize, "Incorrect TCount");
793  static_assert(0U < TCount, "Incorrect instantiation");
794 
795  COMMS_ASSERT(TFromIdx <= idx);
796  COMMS_ASSERT(idx < TToIdx);
797  if (idx == TFromIdx) {
798  TupleSelectedTypeHelper<false>::template exec<TFromIdx, TFromIdx + 1, 1U, TTuple>(
799  idx, std::forward<TFunc>(func));
800  return;
801  }
802 
803  static constexpr std::size_t MidIdx = TFromIdx + TCount / 2;
804  static_assert(MidIdx < TToIdx, "Internal error: bad calculation");
805  static_assert(TFromIdx <= MidIdx, "Internal error: bad calculation");
806  if (MidIdx <= idx) {
807  static constexpr std::size_t NextCount = TToIdx - MidIdx;
808  static constexpr bool HasNextElems = (1U < NextCount);
809 
810  TupleSelectedTypeHelper<HasNextElems>::template exec<MidIdx, TToIdx, NextCount, TTuple>(
811  idx, std::forward<TFunc>(func));
812  return;
813  }
814 
815  static constexpr std::size_t NextCount = MidIdx - TFromIdx;
816  static constexpr bool HasNextElems = (1U < NextCount);
817 
818  TupleSelectedTypeHelper<HasNextElems>::template exec<TFromIdx, MidIdx, NextCount, TTuple>(
819  idx, std::forward<TFunc>(func));
820  }
821 };
822 
823 } // namespace details
824 
839 template <typename TTuple, typename TFunc>
840 void tupleForSelectedType(std::size_t idx, TFunc&& func)
841 {
842  using Tuple = typename std::decay<TTuple>::type;
843  static_assert(isTuple<Tuple>(), "Provided tupe must be std::tuple");
844  static constexpr std::size_t TupleSize = std::tuple_size<Tuple>::value;
845  static_assert(0U < TupleSize, "Empty tuples are not supported");
846 
847  details::TupleSelectedTypeHelper<(1U < TupleSize)>::template exec<0, TupleSize, TupleSize, Tuple>(
848  idx, std::forward<TFunc>(func));
849 }
850 //----------------------------------------
851 
852 namespace details
853 {
854 
855 template <bool THasElems>
856 struct TupleStripFirstN
857 {
858  template <std::size_t TCount, typename TFirst, typename... TElems>
859  using Type =
860  typename TupleStripFirstN<
861  (1U < TCount)
862  >::template Type<
863  TCount - 1,
864  TElems...
865  >;
866 };
867 
868 template <>
869 struct TupleStripFirstN<false>
870 {
871  template <std::size_t TCount, typename... TElems>
872  using Type = std::tuple<TElems...>;
873 };
874 
875 template <typename TTuple>
876 struct TuplePackedStripFirstN;
877 
878 template <typename... TElems>
879 struct TuplePackedStripFirstN<std::tuple<TElems...> >
880 {
881  template <std::size_t TCount>
882  using Type =
883  typename TupleStripFirstN<
884  (0 < TCount)
885  >::template Type<TCount, TElems...>;
886 };
887 
888 template <bool TMustStrip>
889 struct TupleTailCheckHelpler
890 {
891  template <std::size_t TCount, typename TElems>
892  using StrippedTail =
893  typename TuplePackedStripFirstN<TElems>::template Type<
894  TCount
895  >;
896 
897  template <typename TTail, typename TElems>
898  using Type =
899  std::integral_constant<
900  bool,
901  std::is_same<
902  TTail,
903  StrippedTail<
904  (std::tuple_size<TElems>::value - std::tuple_size<TTail>::value),
905  TElems
906  >
907  >::value
908  >;
909 };
910 
911 template <>
912 struct TupleTailCheckHelpler<false>
913 {
914  template <typename TTail, typename TElems>
915  using Type =
916  std::integral_constant<
917  bool,
918  std::is_same<TTail, TElems>::value
919  >;
920 };
921 
922 } // namespace details
923 
927 template <typename TTail, typename TTuple>
928 constexpr bool tupleIsTailOf()
929 {
930  static_assert(isTuple<TTail>(), "TTail param must be tuple");
931  static_assert(isTuple<TTuple>(), "TTuple param must be tuple");
932  return
933  details::TupleTailCheckHelpler<
934  std::tuple_size<TTail>::value < std::tuple_size<TTuple>::value
935  >::template Type<TTail, TTuple>::value;
936 }
937 
938 //----------------------------------------
939 
940 namespace details
941 {
942 
943 template <bool THasElems>
944 class TupleTypeIsAnyOfHelper
945 {
946 public:
947  template <std::size_t TRem, typename TTuple, typename TFunc>
948  static constexpr bool check(TFunc&& func)
949  {
950  using Tuple = typename std::decay<TTuple>::type;
951  static_assert(IsTuple<Tuple>::Value, "TTuple must be std::tuple");
952  static_assert(TRem <= std::tuple_size<Tuple>::value, "Incorrect TRem");
953  using ElemType = typename std::tuple_element<std::tuple_size<Tuple>::value - TRem, Tuple>::type;
954  return
955 #if COMMS_IS_MSVC
956  // VS compiler
957  func.operator()<ElemType>() ||
958 #else // #if COMMS_IS_MSVC
959  func.template operator()<ElemType>() ||
960 #endif // #if COMMS_IS_MSVC
961  TupleTypeIsAnyOfHelper<1U < TRem>::template check<TRem - 1, TTuple>(
962  std::forward<TFunc>(func));
963  }
964 };
965 
966 template <>
967 class TupleTypeIsAnyOfHelper<false>
968 {
969 
970 public:
971  template <std::size_t TRem, typename TTuple, typename TFunc>
972  static constexpr bool check(TFunc&&)
973  {
974  return false;
975  }
976 };
977 
978 }
979 
992 template <typename TTuple, typename TFunc>
993 constexpr bool tupleTypeIsAnyOf(TFunc&& func)
994 {
995  static_assert(isTuple<TTuple>(), "Tuple as argument is expected");
996  return details::TupleTypeIsAnyOfHelper<(0U < std::tuple_size<TTuple>::value)>::
997  template check<std::tuple_size<TTuple>::value, TTuple>(std::forward<TFunc>(func));
998 }
999 
1000 } // namespace util
1001 
1002 } // namespace comms
1003 
1004 COMMS_GNU_WARNING_POP
This file contains classes required for generic custom assertion functionality.
#define COMMS_ASSERT(expr)
Generic assert macro.
Definition: Assert.h:170
Contains various compiler related definitions.
constexpr TValue tupleTypeAccumulate(const TValue &value, TFunc &&func)
Performs "accumulate" algorithm on every type of the tuple.
Definition: Tuple.h:688
constexpr TValue tupleTypeAccumulateFromUntil(const TValue &value, TFunc &&func)
Performs "accumulate" algorithm on specified types inside the tuple.
Definition: Tuple.h:716
void tupleForEachFrom(TTuple &&tuple, TFunc &&func)
Invoke provided functor for every element in the tuple starting from element with specified index.
Definition: Tuple.h:286
constexpr bool tupleTypeIsAnyOf(TFunc &&func)
Compile time check of whether any type within a tuple has a certain condition.
Definition: Tuple.h:993
void tupleForEach(TTuple &&tuple, TFunc &&func)
Invoke provided functor for every element in the tuple.
Definition: Tuple.h:242
void tupleForEachFromUntil(TTuple &&tuple, TFunc &&func)
Invoke provided functor for every element in the tuple which indices are in range [TFromIdx,...
Definition: Tuple.h:312
void tupleForSelectedType(std::size_t idx, TFunc &&func)
Invoke provided functor for a selected type when element index is known only at run time.
Definition: Tuple.h:840
void tupleForEachType(TFunc &&func)
Invoke provided functor for every type in the tuple.
Definition: Tuple.h:387
void tupleForEachWithTemplateParamIdx(TTuple &&tuple, TFunc &&func)
Invoke provided functor for every element in the tuple while providing information about element inde...
Definition: Tuple.h:523
constexpr TValue tupleAccumulateFromUntil(TTuple &&tuple, const TValue &value, TFunc &&func)
Performs "accumulate" algorithm on every element of the tuple.
Definition: Tuple.h:617
constexpr bool tupleIsTailOf()
Compile time check of whether one tuple is a "tail" of another.
Definition: Tuple.h:928
void tupleForEachUntil(TTuple &&tuple, TFunc &&func)
Invoke provided functor for every element in the tuple until element with specified index is reached.
Definition: Tuple.h:263
void tupleForEachWithIdx(TTuple &&tuple, TFunc &&func)
Invoke provided functor for every element in the tuple while providing information about element inde...
Definition: Tuple.h:452
constexpr bool isTuple()
Check whether provided type is a variant of std::tuple.
Definition: Tuple.h:53
typename TupleAsAlignedUnion< TTuple >::Type TupleAsAlignedUnionT
Alias to TupleAsAlignedUnion::Type.
Definition: Tuple.h:188
constexpr TValue tupleAccumulate(TTuple &&tuple, const TValue &value, TFunc &&func)
Performs "accumulate" algorithm on every element of the tuple.
Definition: Tuple.h:589
Main namespace for all classes / functions of COMMS library.
Replacement to std::conditional.
Definition: type_traits.h:28
Check whether TType type is included in the tuple TTuple.
Definition: Tuple.h:94
Check whether provided type is a variant of std::tuple.
Definition: Tuple.h:35
Calculated "aligned union" storage type for all the types in provided tuple.
Definition: Tuple.h:157
void Type
Type definition is invalid for any type that is not std::tuple, will be specialised to proper value.
Definition: Tuple.h:165
Provides the type of std::tuple_cat operation.
Definition: Tuple.h:738
typename TupleCat< TField, TTuple >::Type TupleCatT
Alias to typename TupleCat<TField, TTuple>::Type.
Definition: Tuple.h:749
typename std::decay< decltype(std::tuple_cat(std::declval< TFirst >(), std::declval< TSecond >()))>::type Type
Result type of tuples concatenation.
Definition: Tuple.h:743
Replacement to some types from standard type_traits.