26COMMS_GNU_WARNING_DISABLE(
"-Wtype-limits")
37template <
typename TType>
42 static constexpr bool Value =
false;
46template <
typename... TArgs>
49 static constexpr bool Value =
true;
56template <
typename TType>
67template <
bool THasElems,
typename...>
70 template <
typename TType,
typename TFirst,
typename... TRest>
73 std::is_same<TType, TFirst>::value
76 typename IsInTupleHelper<(
sizeof...(TRest) != 0U)>::template Type<TType, TRest...>
80template <
typename... TParams>
81struct IsInTupleHelper<false, TParams...>
83 template <
typename TType,
typename...>
84 using Type = std::false_type;
97template <
typename TTuple>
102template <
typename... TTypes>
105 template <
typename TType>
107 typename details::IsInTupleHelper<(
sizeof...(TTypes) != 0U)>::template Type<TType, TTypes...>;
117template <
bool THasElems,
typename...>
118class TupleAsAlignedUnionHelper
120 template <
typename TElem>
121 using ElemAlignmentType = std::integral_constant<std::size_t,
alignof(TElem)>;
123 template <
typename TElem>
124 using ElemSizeType = std::integral_constant<std::size_t,
sizeof(TElem)>;
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...>
134 template <
typename TElem,
typename... TRest>
136 comms::util::IntMaxBinaryOp<>::template Type<
138 typename TupleAsAlignedUnionHelper<(0U <
sizeof...(TRest))>::template SizeType<TRest...>
142template <
typename... TParams>
143class TupleAsAlignedUnionHelper<false, TParams...>
146 template <
typename...>
147 using AlignmentType = std::integral_constant<std::size_t, 0U>;
149 template <
typename...>
150 using SizeType = std::integral_constant<std::size_t, 0U>;
159template <
typename TTuple>
173template <
typename... TTypes>
176 using AlignmentType =
177 typename details::TupleAsAlignedUnionHelper<(0U <
sizeof...(TTypes))>::template AlignmentType<TTypes...>;
180 typename details::TupleAsAlignedUnionHelper<(0U <
sizeof...(TTypes))>::template SizeType<TTypes...>;
182 using Type = comms::util::AlignedStorage<SizeType::value, AlignmentType::value>;
187template <
typename TTuple>
195template <
bool THasElems>
196struct TupleForEachHelper
198 template <std::
size_t TOff, std::
size_t TRem,
typename TTuple,
typename TFunc>
199 static void exec(TTuple&& tuple, TFunc&& func)
201 using Tuple =
typename std::decay<TTuple>::type;
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");
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));
218struct TupleForEachHelper<false>
220 template <std::
size_t TOff, std::
size_t TRem,
typename TTuple,
typename TFunc>
221 static void exec(TTuple&& tuple, TFunc&& func)
223 static_cast<void>(tuple);
224 static_cast<void>(func);
241template <
typename TTuple,
typename TFunc>
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);
248 details::TupleForEachHelper<HasTupleElems>::template exec<0, TupleSize>(
249 std::forward<TTuple>(tuple),
250 std::forward<TFunc>(func));
262template <std::
size_t TIdx,
typename TTuple,
typename TFunc>
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.");
270 static constexpr bool HasTupleElems = (TIdx != 0U);
272 details::TupleForEachHelper<HasTupleElems>::template exec<TupleSize - TIdx, TIdx>(
273 std::forward<TTuple>(tuple),
274 std::forward<TFunc>(func));
285template <std::
size_t TIdx,
typename TTuple,
typename TFunc>
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);
295 details::TupleForEachHelper<HasTupleElems>::template exec<0, RemCount>(
296 std::forward<TTuple>(tuple),
297 std::forward<TFunc>(func));
311template <std::
size_t TFromIdx, std::
size_t TUntilIdx,
typename TTuple,
typename TFunc>
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.");
319 static_assert(TUntilIdx <= TupleSize,
320 "The until index is too big.");
322 static_assert(TFromIdx <= TUntilIdx,
323 "The from index must be less than until index.");
325 static constexpr std::size_t FieldsCount = TUntilIdx - TFromIdx;
326 static constexpr bool HasTupleElems = (FieldsCount != 0U);
328 details::TupleForEachHelper<HasTupleElems>::template exec<TupleSize - TUntilIdx, FieldsCount>(
329 std::forward<TTuple>(tuple),
330 std::forward<TFunc>(func));
337template <
bool THasElems>
338struct TupleForEachTypeHelper
340 template <std::
size_t TRem,
typename TTuple,
typename TFunc>
341 static void exec(TFunc&& func)
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");
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);
352 using ElemType =
typename std::tuple_element<Idx, Tuple>::type;
355 func.operator()<ElemType>();
357 func.template operator()<ElemType>();
359 TupleForEachTypeHelper<NextHasElems>::template exec<NextRem, TTuple>(
360 std::forward<TFunc>(func));
365struct TupleForEachTypeHelper<false>
367 template <std::
size_t TRem,
typename TTuple,
typename TFunc>
368 static void exec(TFunc&& func)
370 static_cast<void>(func);
386template <
typename TTuple,
typename TFunc>
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);
393 details::TupleForEachTypeHelper<HasElems>::template exec<TupleSize, Tuple>(
394 std::forward<TFunc>(func));
401template <
bool THasElems>
402struct TupleForEachWithIdxHelper
404 template <std::
size_t TRem,
typename TTuple,
typename TFunc>
405 static void exec(TTuple&& tuple, TFunc&& func)
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");
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);
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));
424struct TupleForEachWithIdxHelper<false>
426 template <std::
size_t TRem,
typename TTuple,
typename TFunc>
427 static void exec(TTuple&& tuple, TFunc&& func)
429 static_cast<void>(tuple);
430 static_cast<void>(func);
450template <
typename TTuple,
typename TFunc>
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);
457 details::TupleForEachWithIdxHelper<HasElems>::template exec<TupleSize>(
458 std::forward<TTuple>(tuple),
459 std::forward<TFunc>(func));
465template <
bool THasElems>
466struct TupleForEachWithTemplateParamIdxHelper
468 template <std::
size_t TRem,
typename TTuple,
typename TFunc>
469 static void exec(TTuple&& tuple, TFunc&& func)
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");
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);
482 func.operator()<Idx>(std::get<Idx>(std::forward<TTuple>(tuple)));
484 func.template operator()<Idx>(std::get<Idx>(std::forward<TTuple>(tuple)));
486 TupleForEachWithTemplateParamIdxHelper<NextHasElems>::template exec<NextRem>(
487 std::forward<TTuple>(tuple),
488 std::forward<TFunc>(func));
493struct TupleForEachWithTemplateParamIdxHelper<false>
495 template <std::
size_t TRem,
typename TTuple,
typename TFunc>
496 static void exec(TTuple&& tuple, TFunc&& func)
498 static_cast<void>(tuple);
499 static_cast<void>(func);
521template <
typename TTuple,
typename TFunc>
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);
528 details::TupleForEachWithTemplateParamIdxHelper<HasElems>::template exec<TupleSize>(
529 std::forward<TTuple>(tuple),
530 std::forward<TFunc>(func));
538template <
bool THasElems>
539struct TupleAccumulateHelper
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)
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");
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));
557struct TupleAccumulateHelper<false>
559 template <std::
size_t TOff, std::
size_t TRem,
typename TTuple,
typename TValue,
typename TFunc>
560 static constexpr TValue exec(TTuple&& ,
const TValue& value, TFunc&& )
586template <
typename TTuple,
typename TValue,
typename TFunc>
589 using Tuple =
typename std::decay<TTuple>::type;
591 return details::TupleAccumulateHelper<std::tuple_size<Tuple>::value != 0>::template exec<0, std::tuple_size<Tuple>::value>(
592 std::forward<TTuple>(tuple),
594 std::forward<TFunc>(func));
614template <std::
size_t TFrom, std::
size_t TUntil,
typename TTuple,
typename TValue,
typename TFunc>
617 using Tuple =
typename std::decay<TTuple>::type;
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");
622 return details::TupleAccumulateHelper<(TFrom < TUntil)>::template exec<TFrom, TUntil - TFrom>(
623 std::forward<TTuple>(tuple),
625 std::forward<TFunc>(func));
633template <
bool THasElems>
634class TupleTypeAccumulateHelper
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)
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");
645 return TupleTypeAccumulateHelper<(1U < TRem)>::template exec<TOff + 1, TRem - 1, Tuple>(
649 func.template operator()
651 <
typename std::tuple_element<TOff, Tuple>::type>(value),
652 std::forward<TFunc>(func));
658class TupleTypeAccumulateHelper<false>
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&& )
685template <
typename TTuple,
typename TValue,
typename TFunc>
688 using Tuple =
typename std::decay<TTuple>::type;
690 details::TupleTypeAccumulateHelper<
691 (0U < std::tuple_size<Tuple>::value)
692 >::template exec<0, std::tuple_size<Tuple>::value, Tuple>(
694 std::forward<TFunc>(func));
713template <std::
size_t TFrom, std::
size_t TUntil,
typename TTuple,
typename TValue,
typename TFunc>
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");
720 details::TupleTypeAccumulateHelper<
722 >::template exec<TFrom, TUntil - TFrom, Tuple>(
724 std::forward<TFunc>(func));
732template <
typename TFirst,
typename TSecond>
739 using Type =
typename std::decay<decltype(std::tuple_cat(std::declval<TFirst>(), std::declval<TSecond>()))>::type;
744template <
typename TField,
typename TTuple>
752template <
bool THasElems>
753struct TupleSelectedTypeHelper;
756struct TupleSelectedTypeHelper<false>
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)
761 static_assert((TFromIdx + 1) == TToIdx,
"Internal error: Bad parameters");
762 static_assert(TCount == 1,
"Internal error: Bad parameters");
763 static_cast<void>(idx);
765 using ElemType =
typename std::tuple_element<TFromIdx, TTuple>::type;
768 func.operator()<TFromIdx, ElemType>();
770 func.template operator()<TFromIdx, ElemType>();
775template <
bool THasElems>
776struct TupleSelectedTypeHelper
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)
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");
785 using Tuple =
typename std::decay<TTuple>::type;
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");
793 if (idx == TFromIdx) {
794 TupleSelectedTypeHelper<false>::template exec<TFromIdx, TFromIdx + 1, 1U, TTuple>(
795 idx, std::forward<TFunc>(func));
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");
803 static constexpr std::size_t NextCount = TToIdx - MidIdx;
804 static constexpr bool HasNextElems = (1U < NextCount);
806 TupleSelectedTypeHelper<HasNextElems>::template exec<MidIdx, TToIdx, NextCount, TTuple>(
807 idx, std::forward<TFunc>(func));
811 static constexpr std::size_t NextCount = MidIdx - TFromIdx;
812 static constexpr bool HasNextElems = (1U < NextCount);
814 TupleSelectedTypeHelper<HasNextElems>::template exec<TFromIdx, MidIdx, NextCount, TTuple>(
815 idx, std::forward<TFunc>(func));
835template <
typename TTuple,
typename TFunc>
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");
843 details::TupleSelectedTypeHelper<(1U < TupleSize)>::template exec<0, TupleSize, TupleSize, Tuple>(
844 idx, std::forward<TFunc>(func));
851template <
bool THasElems>
852struct TupleStripFirstN
854 template <std::size_t TCount,
typename TFirst,
typename... TElems>
856 typename TupleStripFirstN<
865struct TupleStripFirstN<false>
867 template <std::size_t TCount,
typename... TElems>
868 using Type = std::tuple<TElems...>;
871template <
typename TTuple>
872struct TuplePackedStripFirstN;
874template <
typename... TElems>
875struct TuplePackedStripFirstN<
std::tuple<TElems...> >
877 template <std::
size_t TCount>
879 typename TupleStripFirstN<
881 >::template Type<TCount, TElems...>;
884template <
bool TMustStrip>
885struct TupleTailCheckHelpler
887 template <std::
size_t TCount,
typename TElems>
889 typename TuplePackedStripFirstN<TElems>::template Type<
893 template <
typename TTail,
typename TElems>
895 std::integral_constant<
900 (std::tuple_size<TElems>::value - std::tuple_size<TTail>::value),
908struct TupleTailCheckHelpler<false>
910 template <
typename TTail,
typename TElems>
912 std::integral_constant<
914 std::is_same<TTail, TElems>::value
923template <
typename TTail,
typename TTuple>
926 static_assert(isTuple<TTail>(),
"TTail param must be tuple");
927 static_assert(isTuple<TTuple>(),
"TTuple param must be tuple");
929 details::TupleTailCheckHelpler<
930 std::tuple_size<TTail>::value < std::tuple_size<TTuple>::value
931 >::template Type<TTail, TTuple>::value;
939template <
bool THasElems>
940class TupleTypeIsAnyOfHelper
943 template <std::
size_t TRem,
typename TTuple,
typename TFunc>
944 static constexpr bool check(TFunc&& func)
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;
953 func.operator()<ElemType>() ||
955 func.template
operator()<ElemType>() ||
957 TupleTypeIsAnyOfHelper<1U < TRem>::template check<TRem - 1, TTuple>(
958 std::forward<TFunc>(func));
963class TupleTypeIsAnyOfHelper<false>
967 template <std::
size_t TRem,
typename TTuple,
typename TFunc>
968 static constexpr bool check(TFunc&&)
988template <
typename TTuple,
typename TFunc>
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));
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.
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.