23COMMS_GNU_WARNING_DISABLE(
"-Wtype-limits")
34template <
typename TType>
39 static constexpr bool Value =
false;
43template <
typename... TArgs>
46 static constexpr bool Value =
true;
53template <
typename TType>
64template <
bool THasElems,
typename...>
67 template <
typename TType,
typename TFirst,
typename... TRest>
70 std::is_same<TType, TFirst>::value
73 typename IsInTupleHelper<(
sizeof...(TRest) != 0U)>::template Type<TType, TRest...>
77template <
typename... TParams>
78struct IsInTupleHelper<false, TParams...>
80 template <
typename TType,
typename...>
81 using Type = std::false_type;
94template <
typename TTuple>
99template <
typename... TTypes>
102 template <
typename TType>
104 typename details::IsInTupleHelper<(
sizeof...(TTypes) != 0U)>::template Type<TType, TTypes...>;
114template <
bool THasElems,
typename...>
115class TupleAsAlignedUnionHelper
117 template <
typename TElem>
118 using ElemAlignmentType = std::integral_constant<std::size_t,
alignof(TElem)>;
120 template <
typename TElem>
121 using ElemSizeType = std::integral_constant<std::size_t,
sizeof(TElem)>;
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...>
131 template <
typename TElem,
typename... TRest>
133 comms::util::IntMaxBinaryOp<>::template Type<
135 typename TupleAsAlignedUnionHelper<(0U <
sizeof...(TRest))>::template SizeType<TRest...>
139template <
typename... TParams>
140class TupleAsAlignedUnionHelper<false, TParams...>
143 template <
typename...>
144 using AlignmentType = std::integral_constant<std::size_t, 0U>;
146 template <
typename...>
147 using SizeType = std::integral_constant<std::size_t, 0U>;
156template <
typename TTuple>
170template <
typename... TTypes>
173 using AlignmentType =
174 typename details::TupleAsAlignedUnionHelper<(0U <
sizeof...(TTypes))>::template AlignmentType<TTypes...>;
177 typename details::TupleAsAlignedUnionHelper<(0U <
sizeof...(TTypes))>::template SizeType<TTypes...>;
179 using Type = comms::util::AlignedStorage<SizeType::value, AlignmentType::value>;
184template <
typename TTuple>
192template <
bool THasElems>
193struct TupleForEachHelper
195 template <std::
size_t TOff, std::
size_t TRem,
typename TTuple,
typename TFunc>
196 static void exec(TTuple&& tuple, TFunc&& func)
198 using Tuple =
typename std::decay<TTuple>::type;
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");
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));
215struct TupleForEachHelper<false>
217 template <std::
size_t TOff, std::
size_t TRem,
typename TTuple,
typename TFunc>
218 static void exec(TTuple&& tuple, TFunc&& func)
220 static_cast<void>(tuple);
221 static_cast<void>(func);
238template <
typename TTuple,
typename TFunc>
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);
245 details::TupleForEachHelper<HasTupleElems>::template exec<0, TupleSize>(
246 std::forward<TTuple>(tuple),
247 std::forward<TFunc>(func));
259template <std::
size_t TIdx,
typename TTuple,
typename TFunc>
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.");
267 static constexpr bool HasTupleElems = (TIdx != 0U);
269 details::TupleForEachHelper<HasTupleElems>::template exec<TupleSize - TIdx, TIdx>(
270 std::forward<TTuple>(tuple),
271 std::forward<TFunc>(func));
282template <std::
size_t TIdx,
typename TTuple,
typename TFunc>
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);
292 details::TupleForEachHelper<HasTupleElems>::template exec<0, RemCount>(
293 std::forward<TTuple>(tuple),
294 std::forward<TFunc>(func));
308template <std::
size_t TFromIdx, std::
size_t TUntilIdx,
typename TTuple,
typename TFunc>
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.");
316 static_assert(TUntilIdx <= TupleSize,
317 "The until index is too big.");
319 static_assert(TFromIdx <= TUntilIdx,
320 "The from index must be less than until index.");
322 static constexpr std::size_t FieldsCount = TUntilIdx - TFromIdx;
323 static constexpr bool HasTupleElems = (FieldsCount != 0U);
325 details::TupleForEachHelper<HasTupleElems>::template exec<TupleSize - TUntilIdx, FieldsCount>(
326 std::forward<TTuple>(tuple),
327 std::forward<TFunc>(func));
334template <
bool THasElems>
335struct TupleForEachTypeHelper
337 template <std::
size_t TRem,
typename TTuple,
typename TFunc>
338 static void exec(TFunc&& func)
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");
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);
349 using ElemType =
typename std::tuple_element<Idx, Tuple>::type;
352 func.operator()<ElemType>();
354 func.template operator()<ElemType>();
356 TupleForEachTypeHelper<NextHasElems>::template exec<NextRem, TTuple>(
357 std::forward<TFunc>(func));
362struct TupleForEachTypeHelper<false>
364 template <std::
size_t TRem,
typename TTuple,
typename TFunc>
365 static void exec(TFunc&& func)
367 static_cast<void>(func);
383template <
typename TTuple,
typename TFunc>
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);
390 details::TupleForEachTypeHelper<HasElems>::template exec<TupleSize, Tuple>(
391 std::forward<TFunc>(func));
399template <
bool THasElems>
400struct TupleForEachWithIdxHelper
402 template <std::
size_t TRem,
typename TTuple,
typename TFunc>
403 static void exec(TTuple&& tuple, TFunc&& func)
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");
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);
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));
422struct TupleForEachWithIdxHelper<false>
424 template <std::
size_t TRem,
typename TTuple,
typename TFunc>
425 static void exec(TTuple&& tuple, TFunc&& func)
427 static_cast<void>(tuple);
428 static_cast<void>(func);
448template <
typename TTuple,
typename TFunc>
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);
455 details::TupleForEachWithIdxHelper<HasElems>::template exec<TupleSize>(
456 std::forward<TTuple>(tuple),
457 std::forward<TFunc>(func));
463template <
bool THasElems>
464struct TupleForEachWithTemplateParamIdxHelper
466 template <std::
size_t TRem,
typename TTuple,
typename TFunc>
467 static void exec(TTuple&& tuple, TFunc&& func)
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");
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);
480 func.operator()<Idx>(std::get<Idx>(std::forward<TTuple>(tuple)));
482 func.template operator()<Idx>(std::get<Idx>(std::forward<TTuple>(tuple)));
484 TupleForEachWithTemplateParamIdxHelper<NextHasElems>::template exec<NextRem>(
485 std::forward<TTuple>(tuple),
486 std::forward<TFunc>(func));
491struct TupleForEachWithTemplateParamIdxHelper<false>
493 template <std::
size_t TRem,
typename TTuple,
typename TFunc>
494 static void exec(TTuple&& tuple, TFunc&& func)
496 static_cast<void>(tuple);
497 static_cast<void>(func);
519template <
typename TTuple,
typename TFunc>
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);
526 details::TupleForEachWithTemplateParamIdxHelper<HasElems>::template exec<TupleSize>(
527 std::forward<TTuple>(tuple),
528 std::forward<TFunc>(func));
537template <
bool THasElems>
538struct TupleAccumulateHelper
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)
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");
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));
556struct TupleAccumulateHelper<false>
558 template <std::
size_t TOff, std::
size_t TRem,
typename TTuple,
typename TValue,
typename TFunc>
559 static constexpr TValue exec(TTuple&& ,
const TValue& value, TFunc&& )
585template <
typename TTuple,
typename TValue,
typename TFunc>
588 using Tuple =
typename std::decay<TTuple>::type;
590 return details::TupleAccumulateHelper<std::tuple_size<Tuple>::value != 0>::template exec<0, std::tuple_size<Tuple>::value>(
591 std::forward<TTuple>(tuple),
593 std::forward<TFunc>(func));
613template <std::
size_t TFrom, std::
size_t TUntil,
typename TTuple,
typename TValue,
typename TFunc>
616 using Tuple =
typename std::decay<TTuple>::type;
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");
621 return details::TupleAccumulateHelper<(TFrom < TUntil)>::template exec<TFrom, TUntil - TFrom>(
622 std::forward<TTuple>(tuple),
624 std::forward<TFunc>(func));
632template <
bool THasElems>
633class TupleTypeAccumulateHelper
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)
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");
644 return TupleTypeAccumulateHelper<(1U < TRem)>::template exec<TOff + 1, TRem - 1, Tuple>(
648 func.template operator()
650 <
typename std::tuple_element<TOff, Tuple>::type>(value),
651 std::forward<TFunc>(func));
657class TupleTypeAccumulateHelper<false>
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&& )
684template <
typename TTuple,
typename TValue,
typename TFunc>
687 using Tuple =
typename std::decay<TTuple>::type;
689 details::TupleTypeAccumulateHelper<
690 (0U < std::tuple_size<Tuple>::value)
691 >::template exec<0, std::tuple_size<Tuple>::value, Tuple>(
693 std::forward<TFunc>(func));
712template <std::
size_t TFrom, std::
size_t TUntil,
typename TTuple,
typename TValue,
typename TFunc>
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");
719 details::TupleTypeAccumulateHelper<
721 >::template exec<TFrom, TUntil - TFrom, Tuple>(
723 std::forward<TFunc>(func));
733template <
typename TFirst,
typename TSecond>
740 using Type =
typename std::decay<decltype(std::tuple_cat(std::declval<TFirst>(), std::declval<TSecond>()))>::type;
745template <
typename TField,
typename TTuple>
753template <
bool THasElems>
754struct TupleSelectedTypeHelper;
757struct TupleSelectedTypeHelper<false>
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)
762 static_assert((TFromIdx + 1) == TToIdx,
"Internal error: Bad parameters");
763 static_assert(TCount == 1,
"Internal error: Bad parameters");
764 static_cast<void>(idx);
766 using ElemType =
typename std::tuple_element<TFromIdx, TTuple>::type;
769 func.operator()<TFromIdx, ElemType>();
771 func.template operator()<TFromIdx, ElemType>();
776template <
bool THasElems>
777struct TupleSelectedTypeHelper
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)
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");
786 using Tuple =
typename std::decay<TTuple>::type;
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");
794 if (idx == TFromIdx) {
795 TupleSelectedTypeHelper<false>::template exec<TFromIdx, TFromIdx + 1, 1U, TTuple>(
796 idx, std::forward<TFunc>(func));
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");
804 static constexpr std::size_t NextCount = TToIdx - MidIdx;
805 static constexpr bool HasNextElems = (1U < NextCount);
807 TupleSelectedTypeHelper<HasNextElems>::template exec<MidIdx, TToIdx, NextCount, TTuple>(
808 idx, std::forward<TFunc>(func));
812 static constexpr std::size_t NextCount = MidIdx - TFromIdx;
813 static constexpr bool HasNextElems = (1U < NextCount);
815 TupleSelectedTypeHelper<HasNextElems>::template exec<TFromIdx, MidIdx, NextCount, TTuple>(
816 idx, std::forward<TFunc>(func));
836template <
typename TTuple,
typename TFunc>
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");
844 details::TupleSelectedTypeHelper<(1U < TupleSize)>::template exec<0, TupleSize, TupleSize, Tuple>(
845 idx, std::forward<TFunc>(func));
852template <
bool THasElems>
853struct TupleStripFirstN
855 template <std::size_t TCount,
typename TFirst,
typename... TElems>
857 typename TupleStripFirstN<
866struct TupleStripFirstN<false>
868 template <std::size_t TCount,
typename... TElems>
869 using Type = std::tuple<TElems...>;
872template <
typename TTuple>
873struct TuplePackedStripFirstN;
875template <
typename... TElems>
876struct TuplePackedStripFirstN<
std::tuple<TElems...> >
878 template <std::
size_t TCount>
880 typename TupleStripFirstN<
882 >::template Type<TCount, TElems...>;
885template <
bool TMustStrip>
886struct TupleTailCheckHelpler
888 template <std::
size_t TCount,
typename TElems>
890 typename TuplePackedStripFirstN<TElems>::template Type<
894 template <
typename TTail,
typename TElems>
896 std::integral_constant<
901 (std::tuple_size<TElems>::value - std::tuple_size<TTail>::value),
909struct TupleTailCheckHelpler<false>
911 template <
typename TTail,
typename TElems>
913 std::integral_constant<
915 std::is_same<TTail, TElems>::value
924template <
typename TTail,
typename TTuple>
927 static_assert(isTuple<TTail>(),
"TTail param must be tuple");
928 static_assert(isTuple<TTuple>(),
"TTuple param must be tuple");
930 details::TupleTailCheckHelpler<
931 std::tuple_size<TTail>::value < std::tuple_size<TTuple>::value
932 >::template Type<TTail, TTuple>::value;
940template <
bool THasElems>
941class TupleTypeIsAnyOfHelper
944 template <std::
size_t TRem,
typename TTuple,
typename TFunc>
945 static constexpr bool check(TFunc&& func)
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;
954 func.operator()<ElemType>() ||
956 func.template
operator()<ElemType>() ||
958 TupleTypeIsAnyOfHelper<1U < TRem>::template check<TRem - 1, TTuple>(
959 std::forward<TFunc>(func));
964class TupleTypeIsAnyOfHelper<false>
968 template <std::
size_t TRem,
typename TTuple,
typename TFunc>
969 static constexpr bool check(TFunc&&)
989template <
typename TTuple,
typename TFunc>
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));
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.
Replacement to std::conditional.
Definition type_traits.h:28
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.