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