COMMS
Template library intended to help with implementation of communication protocols.
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
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
395
396namespace details
397{
398
399template <bool THasElems>
400struct TupleForEachWithIdxHelper
401{
402 template <std::size_t TRem, typename TTuple, typename TFunc>
403 static void exec(TTuple&& tuple, TFunc&& func)
404 {
405 using Tuple = typename std::decay<TTuple>::type;
406 static_assert(IsTuple<Tuple>::Value, "TTuple must be std::tuple");
407 static constexpr std::size_t TupleSize = std::tuple_size<Tuple>::value;
408 static_assert(TRem <= TupleSize, "Incorrect TRem");
409
410 static constexpr std::size_t Idx = TupleSize - TRem;
411 static constexpr std::size_t NextRem = TRem - 1;
412 static constexpr bool NextHasElems = (NextRem != 0U);
413
414 func(std::get<Idx>(std::forward<TTuple>(tuple)), Idx);
415 TupleForEachWithIdxHelper<NextHasElems>::template exec<NextRem>(
416 std::forward<TTuple>(tuple),
417 std::forward<TFunc>(func));
418 }
419};
420
421template <>
422struct TupleForEachWithIdxHelper<false>
423{
424 template <std::size_t TRem, typename TTuple, typename TFunc>
425 static void exec(TTuple&& tuple, TFunc&& func)
426 {
427 static_cast<void>(tuple);
428 static_cast<void>(func);
429 }
430};
431
432} // namespace details
433
448template <typename TTuple, typename TFunc>
449void tupleForEachWithIdx(TTuple&& tuple, TFunc&& func)
450{
451 using Tuple = typename std::decay<TTuple>::type;
452 static constexpr std::size_t TupleSize = std::tuple_size<Tuple>::value;
453 static constexpr bool HasElems = (TupleSize != 0U);
454
455 details::TupleForEachWithIdxHelper<HasElems>::template exec<TupleSize>(
456 std::forward<TTuple>(tuple),
457 std::forward<TFunc>(func));
458}
459
460namespace details
461{
462
463template <bool THasElems>
464struct TupleForEachWithTemplateParamIdxHelper
465{
466 template <std::size_t TRem, typename TTuple, typename TFunc>
467 static void exec(TTuple&& tuple, TFunc&& func)
468 {
469 using Tuple = typename std::decay<TTuple>::type;
470 static_assert(IsTuple<Tuple>::Value, "TTuple must be std::tuple");
471 static constexpr std::size_t TupleSize = std::tuple_size<Tuple>::value;
472 static_assert(TRem <= TupleSize, "Incorrect TRem");
473
474 static constexpr std::size_t Idx = TupleSize - TRem;
475 static constexpr std::size_t NextRem = TRem - 1;
476 static constexpr bool NextHasElems = (NextRem != 0U);
477
478#if COMMS_IS_MSVC
479 // VS compiler
480 func.operator()<Idx>(std::get<Idx>(std::forward<TTuple>(tuple)));
481#else // #if COMMS_IS_MSVC
482 func.template operator()<Idx>(std::get<Idx>(std::forward<TTuple>(tuple)));
483#endif // #if COMMS_IS_MSVC
484 TupleForEachWithTemplateParamIdxHelper<NextHasElems>::template exec<NextRem>(
485 std::forward<TTuple>(tuple),
486 std::forward<TFunc>(func));
487 }
488};
489
490template <>
491struct TupleForEachWithTemplateParamIdxHelper<false>
492{
493 template <std::size_t TRem, typename TTuple, typename TFunc>
494 static void exec(TTuple&& tuple, TFunc&& func)
495 {
496 static_cast<void>(tuple);
497 static_cast<void>(func);
498 }
499};
500
501} // namespace details
502
518
519template <typename TTuple, typename TFunc>
520void tupleForEachWithTemplateParamIdx(TTuple&& tuple, TFunc&& func)
521{
522 using Tuple = typename std::decay<TTuple>::type;
523 static constexpr std::size_t TupleSize = std::tuple_size<Tuple>::value;
524 static constexpr bool HasElems = (TupleSize != 0U);
525
526 details::TupleForEachWithTemplateParamIdxHelper<HasElems>::template exec<TupleSize>(
527 std::forward<TTuple>(tuple),
528 std::forward<TFunc>(func));
529}
530
531
532//----------------------------------------
533
534namespace details
535{
536
537template <bool THasElems>
538struct TupleAccumulateHelper
539{
540 template <std::size_t TOff, std::size_t TRem, typename TTuple, typename TValue, typename TFunc>
541 static constexpr TValue exec(TTuple&& tuple, const TValue& value, TFunc&& func)
542 {
543 using Tuple = typename std::decay<TTuple>::type;
544 static_assert(IsTuple<Tuple>::Value, "TTuple must be std::tuple");
545 static_assert((TOff + TRem) <= std::tuple_size<Tuple>::value, "Incorrect params");
546
547 return
548 TupleAccumulateHelper<(1U < TRem)>::template exec<TOff + 1, TRem - 1U>(
549 std::forward<TTuple>(tuple),
550 func(value, std::get<TOff>(std::forward<TTuple>(tuple))),
551 std::forward<TFunc>(func));
552 }
553};
554
555template <>
556struct TupleAccumulateHelper<false>
557{
558 template <std::size_t TOff, std::size_t TRem, typename TTuple, typename TValue, typename TFunc>
559 static constexpr TValue exec(TTuple&& /* tuple */, const TValue& value, TFunc&& /* func */)
560 {
561 return value;
562 }
563};
564
565} // namespace details
566
585template <typename TTuple, typename TValue, typename TFunc>
586constexpr TValue tupleAccumulate(TTuple&& tuple, const TValue& value, TFunc&& func)
587{
588 using Tuple = typename std::decay<TTuple>::type;
589
590 return details::TupleAccumulateHelper<std::tuple_size<Tuple>::value != 0>::template exec<0, std::tuple_size<Tuple>::value>(
591 std::forward<TTuple>(tuple),
592 value,
593 std::forward<TFunc>(func));
594}
595
613template <std::size_t TFrom, std::size_t TUntil, typename TTuple, typename TValue, typename TFunc>
614constexpr TValue tupleAccumulateFromUntil(TTuple&& tuple, const TValue& value, TFunc&& func)
615{
616 using Tuple = typename std::decay<TTuple>::type;
617
618 static_assert(TFrom <= TUntil, "TFrom mustn't be greater that TUntil");
619 static_assert(TUntil <= std::tuple_size<Tuple>::value, "TUntil mustn't exceed size of the tuple");
620
621 return details::TupleAccumulateHelper<(TFrom < TUntil)>::template exec<TFrom, TUntil - TFrom>(
622 std::forward<TTuple>(tuple),
623 value,
624 std::forward<TFunc>(func));
625}
626
627//----------------------------------------
628
629namespace details
630{
631
632template <bool THasElems>
633class TupleTypeAccumulateHelper
634{
635
636public:
637 template <std::size_t TOff, std::size_t TRem, typename TTuple, typename TValue, typename TFunc>
638 static constexpr TValue exec(const TValue& value, TFunc&& func)
639 {
640 using Tuple = typename std::decay<TTuple>::type;
641 static_assert(IsTuple<Tuple>::Value, "TTuple must be std::tuple");
642 static_assert((TOff + TRem) <= std::tuple_size<Tuple>::value, "Incorrect TRem");
643
644 return TupleTypeAccumulateHelper<(1U < TRem)>::template exec<TOff + 1, TRem - 1, Tuple>(
645#if COMMS_IS_MSVC
646 func.operator()
647#else // #if COMMS_IS_MSVC
648 func.template operator()
649#endif // #if COMMS_IS_MSVC
650 <typename std::tuple_element<TOff, Tuple>::type>(value),
651 std::forward<TFunc>(func));
652 }
653
654};
655
656template <>
657class TupleTypeAccumulateHelper<false>
658{
659
660public:
661 template <std::size_t TOff, std::size_t TRem, typename TTuple, typename TValue, typename TFunc>
662 static constexpr TValue exec(const TValue& value, TFunc&& /* func */)
663 {
664 return value;
665 }
666};
667
668} // namespace details
669
684template <typename TTuple, typename TValue, typename TFunc>
685constexpr TValue tupleTypeAccumulate(const TValue& value, TFunc&& func)
686{
687 using Tuple = typename std::decay<TTuple>::type;
688 return
689 details::TupleTypeAccumulateHelper<
690 (0U < std::tuple_size<Tuple>::value)
691 >::template exec<0, std::tuple_size<Tuple>::value, Tuple>(
692 value,
693 std::forward<TFunc>(func));
694}
695
712template <std::size_t TFrom, std::size_t TUntil, typename TTuple, typename TValue, typename TFunc>
713constexpr TValue tupleTypeAccumulateFromUntil(const TValue& value, TFunc&& func)
714{
715 using Tuple = typename std::decay<TTuple>::type;
716 static_assert(TFrom <= TUntil, "TFrom mustn't be greater that TUntil");
717 static_assert(TUntil <= std::tuple_size<Tuple>::value, "TUntil mustn't exceed size of the tuple");
718 return
719 details::TupleTypeAccumulateHelper<
720 (TFrom < TUntil)
721 >::template exec<TFrom, TUntil - TFrom, Tuple>(
722 value,
723 std::forward<TFunc>(func));
724}
725
726
727//----------------------------------------
728
729
733template <typename TFirst, typename TSecond>
735{
736 static_assert(IsTuple<TFirst>::Value, "TFirst must be tuple");
737 static_assert(IsTuple<TSecond>::Value, "TSecond must be tuple");
738
740 using Type = typename std::decay<decltype(std::tuple_cat(std::declval<TFirst>(), std::declval<TSecond>()))>::type;
741};
742
745template <typename TField, typename TTuple>
747
748//----------------------------------------
749
750namespace details
751{
752
753template <bool THasElems>
754struct TupleSelectedTypeHelper;
755
756template <>
757struct TupleSelectedTypeHelper<false>
758{
759 template <std::size_t TFromIdx, std::size_t TToIdx, std::size_t TCount, typename TTuple, typename TFunc>
760 static void exec(std::size_t idx, TFunc&& func)
761 {
762 static_assert((TFromIdx + 1) == TToIdx, "Internal error: Bad parameters");
763 static_assert(TCount == 1, "Internal error: Bad parameters");
764 static_cast<void>(idx);
765 COMMS_ASSERT(idx == TFromIdx);
766 using ElemType = typename std::tuple_element<TFromIdx, TTuple>::type;
767#if COMMS_IS_MSVC
768 // VS compiler
769 func.operator()<TFromIdx, ElemType>();
770#else // #if COMMS_IS_MSVC
771 func.template operator()<TFromIdx, ElemType>();
772#endif // #if COMMS_IS_MSVC
773 }
774};
775
776template <bool THasElems>
777struct TupleSelectedTypeHelper
778{
779 template <std::size_t TFromIdx, std::size_t TToIdx, std::size_t TCount, typename TTuple, typename TFunc>
780 static void exec(std::size_t idx, TFunc&& func)
781 {
782 static_assert(1U < TCount, "Internal error: Bad parameters");
783 static_assert(TCount == (TToIdx - TFromIdx), "Internal error: Bad parameters");
784 static_assert(TFromIdx < TToIdx, "Internal error: Bad parameters");
785
786 using Tuple = typename std::decay<TTuple>::type;
787 static_assert(IsTuple<Tuple>::Value, "TTuple must be std::tuple");
788 static constexpr std::size_t TupleSize = std::tuple_size<Tuple>::value;
789 static_assert(TCount <= TupleSize, "Incorrect TCount");
790 static_assert(0U < TCount, "Incorrect instantiation");
791
792 COMMS_ASSERT(TFromIdx <= idx);
793 COMMS_ASSERT(idx < TToIdx);
794 if (idx == TFromIdx) {
795 TupleSelectedTypeHelper<false>::template exec<TFromIdx, TFromIdx + 1, 1U, TTuple>(
796 idx, std::forward<TFunc>(func));
797 return;
798 }
799
800 static constexpr std::size_t MidIdx = TFromIdx + TCount / 2;
801 static_assert(MidIdx < TToIdx, "Internal error: bad calculation");
802 static_assert(TFromIdx <= MidIdx, "Internal error: bad calculation");
803 if (MidIdx <= idx) {
804 static constexpr std::size_t NextCount = TToIdx - MidIdx;
805 static constexpr bool HasNextElems = (1U < NextCount);
806
807 TupleSelectedTypeHelper<HasNextElems>::template exec<MidIdx, TToIdx, NextCount, TTuple>(
808 idx, std::forward<TFunc>(func));
809 return;
810 }
811
812 static constexpr std::size_t NextCount = MidIdx - TFromIdx;
813 static constexpr bool HasNextElems = (1U < NextCount);
814
815 TupleSelectedTypeHelper<HasNextElems>::template exec<TFromIdx, MidIdx, NextCount, TTuple>(
816 idx, std::forward<TFunc>(func));
817 }
818};
819
820} // namespace details
821
836template <typename TTuple, typename TFunc>
837void tupleForSelectedType(std::size_t idx, TFunc&& func)
838{
839 using Tuple = typename std::decay<TTuple>::type;
840 static_assert(isTuple<Tuple>(), "Provided tupe must be std::tuple");
841 static constexpr std::size_t TupleSize = std::tuple_size<Tuple>::value;
842 static_assert(0U < TupleSize, "Empty tuples are not supported");
843
844 details::TupleSelectedTypeHelper<(1U < TupleSize)>::template exec<0, TupleSize, TupleSize, Tuple>(
845 idx, std::forward<TFunc>(func));
846}
847//----------------------------------------
848
849namespace details
850{
851
852template <bool THasElems>
853struct TupleStripFirstN
854{
855 template <std::size_t TCount, typename TFirst, typename... TElems>
856 using Type =
857 typename TupleStripFirstN<
858 (1U < TCount)
859 >::template Type<
860 TCount - 1,
861 TElems...
862 >;
863};
864
865template <>
866struct TupleStripFirstN<false>
867{
868 template <std::size_t TCount, typename... TElems>
869 using Type = std::tuple<TElems...>;
870};
871
872template <typename TTuple>
873struct TuplePackedStripFirstN;
874
875template <typename... TElems>
876struct TuplePackedStripFirstN<std::tuple<TElems...> >
877{
878 template <std::size_t TCount>
879 using Type =
880 typename TupleStripFirstN<
881 (0 < TCount)
882 >::template Type<TCount, TElems...>;
883};
884
885template <bool TMustStrip>
886struct TupleTailCheckHelpler
887{
888 template <std::size_t TCount, typename TElems>
889 using StrippedTail =
890 typename TuplePackedStripFirstN<TElems>::template Type<
891 TCount
892 >;
893
894 template <typename TTail, typename TElems>
895 using Type =
896 std::integral_constant<
897 bool,
898 std::is_same<
899 TTail,
900 StrippedTail<
901 (std::tuple_size<TElems>::value - std::tuple_size<TTail>::value),
902 TElems
903 >
904 >::value
905 >;
906};
907
908template <>
909struct TupleTailCheckHelpler<false>
910{
911 template <typename TTail, typename TElems>
912 using Type =
913 std::integral_constant<
914 bool,
915 std::is_same<TTail, TElems>::value
916 >;
917};
918
919} // namespace details
920
924template <typename TTail, typename TTuple>
925constexpr bool tupleIsTailOf()
926{
927 static_assert(isTuple<TTail>(), "TTail param must be tuple");
928 static_assert(isTuple<TTuple>(), "TTuple param must be tuple");
929 return
930 details::TupleTailCheckHelpler<
931 std::tuple_size<TTail>::value < std::tuple_size<TTuple>::value
932 >::template Type<TTail, TTuple>::value;
933}
934
935//----------------------------------------
936
937namespace details
938{
939
940template <bool THasElems>
941class TupleTypeIsAnyOfHelper
942{
943public:
944 template <std::size_t TRem, typename TTuple, typename TFunc>
945 static constexpr bool check(TFunc&& func)
946 {
947 using Tuple = typename std::decay<TTuple>::type;
948 static_assert(IsTuple<Tuple>::Value, "TTuple must be std::tuple");
949 static_assert(TRem <= std::tuple_size<Tuple>::value, "Incorrect TRem");
950 using ElemType = typename std::tuple_element<std::tuple_size<Tuple>::value - TRem, Tuple>::type;
951 return
952#if COMMS_IS_MSVC
953 // VS compiler
954 func.operator()<ElemType>() ||
955#else // #if COMMS_IS_MSVC
956 func.template operator()<ElemType>() ||
957#endif // #if COMMS_IS_MSVC
958 TupleTypeIsAnyOfHelper<1U < TRem>::template check<TRem - 1, TTuple>(
959 std::forward<TFunc>(func));
960 }
961};
962
963template <>
964class TupleTypeIsAnyOfHelper<false>
965{
966
967public:
968 template <std::size_t TRem, typename TTuple, typename TFunc>
969 static constexpr bool check(TFunc&&)
970 {
971 return false;
972 }
973};
974
975}
976
989template <typename TTuple, typename TFunc>
990constexpr bool tupleTypeIsAnyOf(TFunc&& func)
991{
992 static_assert(isTuple<TTuple>(), "Tuple as argument is expected");
993 return details::TupleTypeIsAnyOfHelper<(0U < std::tuple_size<TTuple>::value)>::
994 template check<std::tuple_size<TTuple>::value, TTuple>(std::forward<TFunc>(func));
995}
996
997} // namespace util
998
999} // namespace comms
1000
1001COMMS_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: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:685
constexpr TValue tupleTypeAccumulateFromUntil(const TValue &value, TFunc &&func)
Performs "accumulate" algorithm on specified types inside the tuple.
Definition Tuple.h:713
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:990
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:837
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:520
constexpr TValue tupleAccumulateFromUntil(TTuple &&tuple, const TValue &value, TFunc &&func)
Performs "accumulate" algorithm on every element of the tuple.
Definition Tuple.h:614
constexpr bool tupleIsTailOf()
Compile time check of whether one tuple is a "tail" of another.
Definition Tuple.h:925
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:449
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:586
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:735
typename TupleCat< TField, TTuple >::Type TupleCatT
Alias to typename TupleCat<TField, TTuple>::Type.
Definition Tuple.h:746
typename std::decay< decltype(std::tuple_cat(std::declval< TFirst >(), std::declval< TSecond >()))>::type Type
Result type of tuples concatenation.
Definition Tuple.h:740
Replacement to some types from standard type_traits.