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 - 2026 (C). Alex Robenko. All rights reserved.
3//
4// SPDX-License-Identifier: MPL-2.0
5//
6// This Source Code Form is subject to the terms of the Mozilla Public
7// License, v. 2.0. If a copy of the MPL was not distributed with this
8// file, You can obtain one at http://mozilla.org/MPL/2.0/.
9
12
13#pragma once
14
15#include "comms/Assert.h"
19
20#include <cstddef>
21#include <tuple>
22#include <type_traits>
23#include <utility>
24
25COMMS_GNU_WARNING_PUSH
26COMMS_GNU_WARNING_DISABLE("-Wtype-limits")
27
28namespace comms
29{
30
31namespace util
32{
33
37template <typename TType>
38struct IsTuple
39{
42 static constexpr bool Value = false;
43};
44
46template <typename... TArgs>
47struct IsTuple<std::tuple<TArgs...> >
48{
49 static constexpr bool Value = true;
50};
52
56template <typename TType>
57constexpr bool isTuple()
58{
60}
61
62//----------------------------------------
63
64namespace details
65{
66
67template <bool THasElems, typename...>
68struct IsInTupleHelper // <true>
69{
70 template <typename TType, typename TFirst, typename... TRest>
71 using Type =
73 std::is_same<TType, TFirst>::value
74 >::template Type<
75 std::true_type,
76 typename IsInTupleHelper<(sizeof...(TRest) != 0U)>::template Type<TType, TRest...>
77 >;
78};
79
80template <typename... TParams>
81struct IsInTupleHelper<false, TParams...>
82{
83 template <typename TType, typename...>
84 using Type = std::false_type;
85};
86
87} // namespace details
88
97template <typename TTuple>
98struct IsInTuple;
99
101
102template <typename... TTypes>
103struct IsInTuple<std::tuple<TTypes...> >
104{
105 template <typename TType>
106 using Type =
107 typename details::IsInTupleHelper<(sizeof...(TTypes) != 0U)>::template Type<TType, TTypes...>;
108};
109
111
112//----------------------------------------
113
114namespace details
115{
116
117template <bool THasElems, typename...>
118class TupleAsAlignedUnionHelper // <true>
119{
120 template <typename TElem>
121 using ElemAlignmentType = std::integral_constant<std::size_t, alignof(TElem)>;
122
123 template <typename TElem>
124 using ElemSizeType = std::integral_constant<std::size_t, sizeof(TElem)>;
125
126public:
127 template <typename TElem, typename... TRest>
128 using AlignmentType =
129 comms::util::IntMaxBinaryOp<>::template Type<
130 ElemAlignmentType<TElem>,
131 typename TupleAsAlignedUnionHelper<(0U < sizeof...(TRest))>::template AlignmentType<TRest...>
132 >;
133
134 template <typename TElem, typename... TRest>
135 using SizeType =
136 comms::util::IntMaxBinaryOp<>::template Type<
137 ElemSizeType<TElem>,
138 typename TupleAsAlignedUnionHelper<(0U < sizeof...(TRest))>::template SizeType<TRest...>
139 >;
140};
141
142template <typename... TParams>
143class TupleAsAlignedUnionHelper<false, TParams...>
144{
145public:
146 template <typename...>
147 using AlignmentType = std::integral_constant<std::size_t, 0U>;
148
149 template <typename...>
150 using SizeType = std::integral_constant<std::size_t, 0U>;
151};
152
153} // namespace details
154
159template <typename TTuple>
161{
163 static_assert(IsTuple<TTuple>::Value, "TTuple must be std::tuple");
165
169 using Type = void;
170};
171
173template <typename... TTypes>
174class TupleAsAlignedUnion<std::tuple<TTypes...> >
175{
176 using AlignmentType =
177 typename details::TupleAsAlignedUnionHelper<(0U < sizeof...(TTypes))>::template AlignmentType<TTypes...>;
178
179 using SizeType =
180 typename details::TupleAsAlignedUnionHelper<(0U < sizeof...(TTypes))>::template SizeType<TTypes...>;
181public:
182 using Type = comms::util::AlignedStorage<SizeType::value, AlignmentType::value>;
183};
185
187template <typename TTuple>
189
190//----------------------------------------
191
192namespace details
193{
194
195template <bool THasElems>
196struct 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
217template <>
218struct 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
241template <typename TTuple, typename TFunc>
242void 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
262template <std::size_t TIdx, typename TTuple, typename TFunc>
263void 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
285template <std::size_t TIdx, typename TTuple, typename TFunc>
286void 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
311template <std::size_t TFromIdx, std::size_t TUntilIdx, typename TTuple, typename TFunc>
312void 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
334namespace details
335{
336
337template <bool THasElems>
338struct 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
364template <>
365struct 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
386template <typename TTuple, typename TFunc>
387void 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
398namespace details
399{
400
401template <bool THasElems>
402struct TupleForEachWithIdxHelper
403{
404 template <std::size_t TRem, typename TTuple, typename TFunc>
405 static void exec(TTuple&& tuple, TFunc&& func)
406 {
407 using Tuple = typename std::decay<TTuple>::type;
408 static_assert(IsTuple<Tuple>::Value, "TTuple must be std::tuple");
409 static constexpr std::size_t TupleSize = std::tuple_size<Tuple>::value;
410 static_assert(TRem <= TupleSize, "Incorrect TRem");
411
412 static constexpr std::size_t Idx = TupleSize - TRem;
413 static constexpr std::size_t NextRem = TRem - 1;
414 static constexpr bool NextHasElems = (NextRem != 0U);
415
416 func(std::get<Idx>(std::forward<TTuple>(tuple)), Idx);
417 TupleForEachWithIdxHelper<NextHasElems>::template exec<NextRem>(
418 std::forward<TTuple>(tuple),
419 std::forward<TFunc>(func));
420 }
421};
422
423template <>
424struct TupleForEachWithIdxHelper<false>
425{
426 template <std::size_t TRem, typename TTuple, typename TFunc>
427 static void exec(TTuple&& tuple, TFunc&& func)
428 {
429 static_cast<void>(tuple);
430 static_cast<void>(func);
431 }
432};
433
434} // namespace details
435
450template <typename TTuple, typename TFunc>
451void tupleForEachWithIdx(TTuple&& tuple, TFunc&& func)
452{
453 using Tuple = typename std::decay<TTuple>::type;
454 static constexpr std::size_t TupleSize = std::tuple_size<Tuple>::value;
455 static constexpr bool HasElems = (TupleSize != 0U);
456
457 details::TupleForEachWithIdxHelper<HasElems>::template exec<TupleSize>(
458 std::forward<TTuple>(tuple),
459 std::forward<TFunc>(func));
460}
461
462namespace details
463{
464
465template <bool THasElems>
466struct TupleForEachWithTemplateParamIdxHelper
467{
468 template <std::size_t TRem, typename TTuple, typename TFunc>
469 static void exec(TTuple&& tuple, TFunc&& func)
470 {
471 using Tuple = typename std::decay<TTuple>::type;
472 static_assert(IsTuple<Tuple>::Value, "TTuple must be std::tuple");
473 static constexpr std::size_t TupleSize = std::tuple_size<Tuple>::value;
474 static_assert(TRem <= TupleSize, "Incorrect TRem");
475
476 static constexpr std::size_t Idx = TupleSize - TRem;
477 static constexpr std::size_t NextRem = TRem - 1;
478 static constexpr bool NextHasElems = (NextRem != 0U);
479
480#if COMMS_IS_MSVC
481 // VS compiler
482 func.operator()<Idx>(std::get<Idx>(std::forward<TTuple>(tuple)));
483#else // #if COMMS_IS_MSVC
484 func.template operator()<Idx>(std::get<Idx>(std::forward<TTuple>(tuple)));
485#endif // #if COMMS_IS_MSVC
486 TupleForEachWithTemplateParamIdxHelper<NextHasElems>::template exec<NextRem>(
487 std::forward<TTuple>(tuple),
488 std::forward<TFunc>(func));
489 }
490};
491
492template <>
493struct TupleForEachWithTemplateParamIdxHelper<false>
494{
495 template <std::size_t TRem, typename TTuple, typename TFunc>
496 static void exec(TTuple&& tuple, TFunc&& func)
497 {
498 static_cast<void>(tuple);
499 static_cast<void>(func);
500 }
501};
502
503} // namespace details
504
520
521template <typename TTuple, typename TFunc>
522void tupleForEachWithTemplateParamIdx(TTuple&& tuple, TFunc&& func)
523{
524 using Tuple = typename std::decay<TTuple>::type;
525 static constexpr std::size_t TupleSize = std::tuple_size<Tuple>::value;
526 static constexpr bool HasElems = (TupleSize != 0U);
527
528 details::TupleForEachWithTemplateParamIdxHelper<HasElems>::template exec<TupleSize>(
529 std::forward<TTuple>(tuple),
530 std::forward<TFunc>(func));
531}
532
533//----------------------------------------
534
535namespace details
536{
537
538template <bool THasElems>
539struct TupleAccumulateHelper
540{
541 template <std::size_t TOff, std::size_t TRem, typename TTuple, typename TValue, typename TFunc>
542 static constexpr TValue exec(TTuple&& tuple, const TValue& value, TFunc&& func)
543 {
544 using Tuple = typename std::decay<TTuple>::type;
545 static_assert(IsTuple<Tuple>::Value, "TTuple must be std::tuple");
546 static_assert((TOff + TRem) <= std::tuple_size<Tuple>::value, "Incorrect params");
547
548 return
549 TupleAccumulateHelper<(1U < TRem)>::template exec<TOff + 1, TRem - 1U>(
550 std::forward<TTuple>(tuple),
551 func(value, std::get<TOff>(std::forward<TTuple>(tuple))),
552 std::forward<TFunc>(func));
553 }
554};
555
556template <>
557struct TupleAccumulateHelper<false>
558{
559 template <std::size_t TOff, std::size_t TRem, typename TTuple, typename TValue, typename TFunc>
560 static constexpr TValue exec(TTuple&& /* tuple */, const TValue& value, TFunc&& /* func */)
561 {
562 return value;
563 }
564};
565
566} // namespace details
567
586template <typename TTuple, typename TValue, typename TFunc>
587constexpr TValue tupleAccumulate(TTuple&& tuple, const TValue& value, TFunc&& func)
588{
589 using Tuple = typename std::decay<TTuple>::type;
590
591 return details::TupleAccumulateHelper<std::tuple_size<Tuple>::value != 0>::template exec<0, std::tuple_size<Tuple>::value>(
592 std::forward<TTuple>(tuple),
593 value,
594 std::forward<TFunc>(func));
595}
596
614template <std::size_t TFrom, std::size_t TUntil, typename TTuple, typename TValue, typename TFunc>
615constexpr TValue tupleAccumulateFromUntil(TTuple&& tuple, const TValue& value, TFunc&& func)
616{
617 using Tuple = typename std::decay<TTuple>::type;
618
619 static_assert(TFrom <= TUntil, "TFrom mustn't be greater that TUntil");
620 static_assert(TUntil <= std::tuple_size<Tuple>::value, "TUntil mustn't exceed size of the tuple");
621
622 return details::TupleAccumulateHelper<(TFrom < TUntil)>::template exec<TFrom, TUntil - TFrom>(
623 std::forward<TTuple>(tuple),
624 value,
625 std::forward<TFunc>(func));
626}
627
628//----------------------------------------
629
630namespace details
631{
632
633template <bool THasElems>
634class TupleTypeAccumulateHelper
635{
636
637public:
638 template <std::size_t TOff, std::size_t TRem, typename TTuple, typename TValue, typename TFunc>
639 static constexpr TValue exec(const TValue& value, TFunc&& func)
640 {
641 using Tuple = typename std::decay<TTuple>::type;
642 static_assert(IsTuple<Tuple>::Value, "TTuple must be std::tuple");
643 static_assert((TOff + TRem) <= std::tuple_size<Tuple>::value, "Incorrect TRem");
644
645 return TupleTypeAccumulateHelper<(1U < TRem)>::template exec<TOff + 1, TRem - 1, Tuple>(
646#if COMMS_IS_MSVC
647 func.operator()
648#else // #if COMMS_IS_MSVC
649 func.template operator()
650#endif // #if COMMS_IS_MSVC
651 <typename std::tuple_element<TOff, Tuple>::type>(value),
652 std::forward<TFunc>(func));
653 }
654
655};
656
657template <>
658class TupleTypeAccumulateHelper<false>
659{
660
661public:
662 template <std::size_t TOff, std::size_t TRem, typename TTuple, typename TValue, typename TFunc>
663 static constexpr TValue exec(const TValue& value, TFunc&& /* func */)
664 {
665 return value;
666 }
667};
668
669} // namespace details
670
685template <typename TTuple, typename TValue, typename TFunc>
686constexpr TValue tupleTypeAccumulate(const TValue& value, TFunc&& func)
687{
688 using Tuple = typename std::decay<TTuple>::type;
689 return
690 details::TupleTypeAccumulateHelper<
691 (0U < std::tuple_size<Tuple>::value)
692 >::template exec<0, std::tuple_size<Tuple>::value, Tuple>(
693 value,
694 std::forward<TFunc>(func));
695}
696
713template <std::size_t TFrom, std::size_t TUntil, typename TTuple, typename TValue, typename TFunc>
714constexpr TValue tupleTypeAccumulateFromUntil(const TValue& value, TFunc&& func)
715{
716 using Tuple = typename std::decay<TTuple>::type;
717 static_assert(TFrom <= TUntil, "TFrom mustn't be greater that TUntil");
718 static_assert(TUntil <= std::tuple_size<Tuple>::value, "TUntil mustn't exceed size of the tuple");
719 return
720 details::TupleTypeAccumulateHelper<
721 (TFrom < TUntil)
722 >::template exec<TFrom, TUntil - TFrom, Tuple>(
723 value,
724 std::forward<TFunc>(func));
725}
726
727//----------------------------------------
728
732template <typename TFirst, typename TSecond>
734{
735 static_assert(IsTuple<TFirst>::Value, "TFirst must be tuple");
736 static_assert(IsTuple<TSecond>::Value, "TSecond must be tuple");
737
739 using Type = typename std::decay<decltype(std::tuple_cat(std::declval<TFirst>(), std::declval<TSecond>()))>::type;
740};
741
744template <typename TField, typename TTuple>
746
747//----------------------------------------
748
749namespace details
750{
751
752template <bool THasElems>
753struct TupleSelectedTypeHelper;
754
755template <>
756struct TupleSelectedTypeHelper<false>
757{
758 template <std::size_t TFromIdx, std::size_t TToIdx, std::size_t TCount, typename TTuple, typename TFunc>
759 static void exec(std::size_t idx, TFunc&& func)
760 {
761 static_assert((TFromIdx + 1) == TToIdx, "Internal error: Bad parameters");
762 static_assert(TCount == 1, "Internal error: Bad parameters");
763 static_cast<void>(idx);
764 COMMS_ASSERT(idx == TFromIdx);
765 using ElemType = typename std::tuple_element<TFromIdx, TTuple>::type;
766#if COMMS_IS_MSVC
767 // VS compiler
768 func.operator()<TFromIdx, ElemType>();
769#else // #if COMMS_IS_MSVC
770 func.template operator()<TFromIdx, ElemType>();
771#endif // #if COMMS_IS_MSVC
772 }
773};
774
775template <bool THasElems>
776struct TupleSelectedTypeHelper
777{
778 template <std::size_t TFromIdx, std::size_t TToIdx, std::size_t TCount, typename TTuple, typename TFunc>
779 static void exec(std::size_t idx, TFunc&& func)
780 {
781 static_assert(1U < TCount, "Internal error: Bad parameters");
782 static_assert(TCount == (TToIdx - TFromIdx), "Internal error: Bad parameters");
783 static_assert(TFromIdx < TToIdx, "Internal error: Bad parameters");
784
785 using Tuple = typename std::decay<TTuple>::type;
786 static_assert(IsTuple<Tuple>::Value, "TTuple must be std::tuple");
787 static constexpr std::size_t TupleSize = std::tuple_size<Tuple>::value;
788 static_assert(TCount <= TupleSize, "Incorrect TCount");
789 static_assert(0U < TCount, "Incorrect instantiation");
790
791 COMMS_ASSERT(TFromIdx <= idx);
792 COMMS_ASSERT(idx < TToIdx);
793 if (idx == TFromIdx) {
794 TupleSelectedTypeHelper<false>::template exec<TFromIdx, TFromIdx + 1, 1U, TTuple>(
795 idx, std::forward<TFunc>(func));
796 return;
797 }
798
799 static constexpr std::size_t MidIdx = TFromIdx + TCount / 2;
800 static_assert(MidIdx < TToIdx, "Internal error: bad calculation");
801 static_assert(TFromIdx <= MidIdx, "Internal error: bad calculation");
802 if (MidIdx <= idx) {
803 static constexpr std::size_t NextCount = TToIdx - MidIdx;
804 static constexpr bool HasNextElems = (1U < NextCount);
805
806 TupleSelectedTypeHelper<HasNextElems>::template exec<MidIdx, TToIdx, NextCount, TTuple>(
807 idx, std::forward<TFunc>(func));
808 return;
809 }
810
811 static constexpr std::size_t NextCount = MidIdx - TFromIdx;
812 static constexpr bool HasNextElems = (1U < NextCount);
813
814 TupleSelectedTypeHelper<HasNextElems>::template exec<TFromIdx, MidIdx, NextCount, TTuple>(
815 idx, std::forward<TFunc>(func));
816 }
817};
818
819} // namespace details
820
835template <typename TTuple, typename TFunc>
836void tupleForSelectedType(std::size_t idx, TFunc&& func)
837{
838 using Tuple = typename std::decay<TTuple>::type;
839 static_assert(isTuple<Tuple>(), "Provided tupe must be std::tuple");
840 static constexpr std::size_t TupleSize = std::tuple_size<Tuple>::value;
841 static_assert(0U < TupleSize, "Empty tuples are not supported");
842
843 details::TupleSelectedTypeHelper<(1U < TupleSize)>::template exec<0, TupleSize, TupleSize, Tuple>(
844 idx, std::forward<TFunc>(func));
845}
846//----------------------------------------
847
848namespace details
849{
850
851template <bool THasElems>
852struct TupleStripFirstN
853{
854 template <std::size_t TCount, typename TFirst, typename... TElems>
855 using Type =
856 typename TupleStripFirstN<
857 (1U < TCount)
858 >::template Type<
859 TCount - 1,
860 TElems...
861 >;
862};
863
864template <>
865struct TupleStripFirstN<false>
866{
867 template <std::size_t TCount, typename... TElems>
868 using Type = std::tuple<TElems...>;
869};
870
871template <typename TTuple>
872struct TuplePackedStripFirstN;
873
874template <typename... TElems>
875struct TuplePackedStripFirstN<std::tuple<TElems...> >
876{
877 template <std::size_t TCount>
878 using Type =
879 typename TupleStripFirstN<
880 (0 < TCount)
881 >::template Type<TCount, TElems...>;
882};
883
884template <bool TMustStrip>
885struct TupleTailCheckHelpler
886{
887 template <std::size_t TCount, typename TElems>
888 using StrippedTail =
889 typename TuplePackedStripFirstN<TElems>::template Type<
890 TCount
891 >;
892
893 template <typename TTail, typename TElems>
894 using Type =
895 std::integral_constant<
896 bool,
897 std::is_same<
898 TTail,
899 StrippedTail<
900 (std::tuple_size<TElems>::value - std::tuple_size<TTail>::value),
901 TElems
902 >
903 >::value
904 >;
905};
906
907template <>
908struct TupleTailCheckHelpler<false>
909{
910 template <typename TTail, typename TElems>
911 using Type =
912 std::integral_constant<
913 bool,
914 std::is_same<TTail, TElems>::value
915 >;
916};
917
918} // namespace details
919
923template <typename TTail, typename TTuple>
924constexpr bool tupleIsTailOf()
925{
926 static_assert(isTuple<TTail>(), "TTail param must be tuple");
927 static_assert(isTuple<TTuple>(), "TTuple param must be tuple");
928 return
929 details::TupleTailCheckHelpler<
930 std::tuple_size<TTail>::value < std::tuple_size<TTuple>::value
931 >::template Type<TTail, TTuple>::value;
932}
933
934//----------------------------------------
935
936namespace details
937{
938
939template <bool THasElems>
940class TupleTypeIsAnyOfHelper
941{
942public:
943 template <std::size_t TRem, typename TTuple, typename TFunc>
944 static constexpr bool check(TFunc&& func)
945 {
946 using Tuple = typename std::decay<TTuple>::type;
947 static_assert(IsTuple<Tuple>::Value, "TTuple must be std::tuple");
948 static_assert(TRem <= std::tuple_size<Tuple>::value, "Incorrect TRem");
949 using ElemType = typename std::tuple_element<std::tuple_size<Tuple>::value - TRem, Tuple>::type;
950 return
951#if COMMS_IS_MSVC
952 // VS compiler
953 func.operator()<ElemType>() ||
954#else // #if COMMS_IS_MSVC
955 func.template operator()<ElemType>() ||
956#endif // #if COMMS_IS_MSVC
957 TupleTypeIsAnyOfHelper<1U < TRem>::template check<TRem - 1, TTuple>(
958 std::forward<TFunc>(func));
959 }
960};
961
962template <>
963class TupleTypeIsAnyOfHelper<false>
964{
965
966public:
967 template <std::size_t TRem, typename TTuple, typename TFunc>
968 static constexpr bool check(TFunc&&)
969 {
970 return false;
971 }
972};
973
974}
975
988template <typename TTuple, typename TFunc>
989constexpr bool tupleTypeIsAnyOf(TFunc&& func)
990{
991 static_assert(isTuple<TTuple>(), "Tuple as argument is expected");
992 return details::TupleTypeIsAnyOfHelper<(0U < std::tuple_size<TTuple>::value)>::
993 template check<std::tuple_size<TTuple>::value, TTuple>(std::forward<TFunc>(func));
994}
995
996} // namespace util
997
998} // namespace comms
999
1000COMMS_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:686
constexpr TValue tupleTypeAccumulateFromUntil(const TValue &value, TFunc &&func)
Performs "accumulate" algorithm on specified types inside the tuple.
Definition Tuple.h:714
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:989
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:836
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:522
constexpr TValue tupleAccumulateFromUntil(TTuple &&tuple, const TValue &value, TFunc &&func)
Performs "accumulate" algorithm on every element of the tuple.
Definition Tuple.h:615
constexpr bool tupleIsTailOf()
Compile time check of whether one tuple is a "tail" of another.
Definition Tuple.h:924
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:451
constexpr bool isTuple()
Check whether provided type is a variant of std::tuple.
Definition Tuple.h:57
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:587
Main namespace for all classes / functions of COMMS library.
STL namespace.
Replacement to std::conditional.
Definition type_traits.h:32
Check whether TType type is included in the tuple TTuple.
Definition Tuple.h:98
Check whether provided type is a variant of std::tuple.
Definition Tuple.h:39
Calculated "aligned union" storage type for all the types in provided tuple.
Definition Tuple.h:161
void Type
Type definition is invalid for any type that is not std::tuple, will be specialised to proper value.
Definition Tuple.h:169
Provides the type of std::tuple_cat operation.
Definition Tuple.h:734
typename TupleCat< TField, TTuple >::Type TupleCatT
Alias to typename TupleCat<TField, TTuple>::Type.
Definition Tuple.h:745
typename std::decay< decltype(std::tuple_cat(std::declval< TFirst >(), std::declval< TSecond >()))>::type Type
Result type of tuples concatenation.
Definition Tuple.h:739
Replacement to some types from standard type_traits.