fork download
  1. #include <utility>
  2. #include <cassert>
  3. #include <cstddef>
  4. #include <tuple>
  5.  
  6. template <class ... Types>
  7. class type_list {};
  8.  
  9. template <std::size_t idx, class... Types>
  10. class extract
  11. {
  12. static_assert(idx < sizeof...(Types), "index out of bounds");
  13.  
  14. template <std::size_t i, std::size_t n, class... Rest>
  15. struct extract_impl;
  16.  
  17. template <std::size_t i, std::size_t n, class T, class... Rest>
  18. struct extract_impl<i, n, T, Rest...>
  19. {
  20. using type = typename extract_impl<i + 1, n, Rest...>::type;
  21. };
  22.  
  23. template <std::size_t n, class T, class... Rest>
  24. struct extract_impl<n, n, T, Rest...>
  25. {
  26. using type = T;
  27. };
  28. public:
  29. using type = typename extract_impl<0, idx, Types...>::type;
  30. };
  31.  
  32. template <std::size_t idx, class TypeList>
  33. struct type_list_extract;
  34.  
  35. template <std::size_t idx, template <class...> class TypeList, class... Types>
  36. struct type_list_extract<idx, TypeList<Types...>>
  37. {
  38. using type = typename extract<idx, Types...>::type;
  39. };
  40.  
  41. template <std::size_t idx, class TypeList>
  42. using type_list_extract_t = typename type_list_extract<idx, TypeList>::type;
  43.  
  44. template <class FirstTypeList, class SecondTypeList>
  45. struct type_list_concat;
  46.  
  47. template <template <class ...> class TypeList, class ... FirstTypesPack, class ... SecondTypesPack>
  48. struct type_list_concat<TypeList<FirstTypesPack...>, TypeList<SecondTypesPack...> >
  49. {
  50. using type = TypeList<FirstTypesPack..., SecondTypesPack...>;
  51. };
  52.  
  53. template <class FirstTypeList, class SecondTypeList>
  54. using type_list_concat_t = typename type_list_concat<FirstTypeList, SecondTypeList>::type;
  55.  
  56. template <class TypeList, size_t ... indexes>
  57. struct type_list_expand
  58. {
  59. using type = std::tuple<typename type_list_extract<indexes, TypeList>::type...>;
  60. };
  61.  
  62. template < template <class...> class TypeList, class ... Types>
  63. struct type_list_expand< TypeList<Types...>>
  64. {
  65. using type = std::tuple<Types...>;
  66. };
  67.  
  68. template <class TypeList, size_t ... indexes>
  69. using type_list_expand_t = typename type_list_expand<TypeList, indexes...>::type;
  70.  
  71. template <std::size_t ... indexes>
  72. struct first_index_holder;
  73.  
  74. template <std::size_t head, std::size_t ... remainder>
  75. struct first_index_holder<head, remainder...>
  76. {
  77. static const std::size_t value = head;
  78. };
  79.  
  80. template <class IndexInterval>
  81. class reverse_index_interval;
  82.  
  83. template <template <typename T, T ...> class IndexInterval, std::size_t ... indexes>
  84. class reverse_index_interval < IndexInterval<std::size_t, indexes...>>
  85. {
  86. static const std::size_t size = sizeof...(indexes)-1;
  87. static const std::size_t head = first_index_holder<indexes...>::value;
  88. public:
  89. using type = IndexInterval<std::size_t, (size + head - indexes + head)... >;
  90. };
  91.  
  92. template <class TypeList>
  93. class type_list_reverse;
  94.  
  95. template <template <class ... > class TypeList, class ... Types>
  96. class type_list_reverse<TypeList<Types...> >
  97. {
  98. template <class integer_sequence, class TList>
  99. struct typelist_reverse_impl;
  100.  
  101. template <template <typename T, T ...> class Sequence, std::size_t ... indexes, template<class ...> class TList, class ... Ts>
  102. struct typelist_reverse_impl<Sequence<std::size_t, indexes...>, TList<Ts...>>
  103. {
  104. using type = TList<type_list_extract_t<indexes, TList<Ts...>>...>;
  105. };
  106. public:
  107. using type = typename typelist_reverse_impl<typename reverse_index_interval<std::make_index_sequence<sizeof...(Types)> >::type, TypeList<Types...>>::type;
  108. };
  109.  
  110. template <class TypeList>
  111. using type_list_reverse_t = typename type_list_reverse<TypeList>::type;
  112.  
  113. #include <utility>
  114. #include <cassert>
  115.  
  116.  
  117. //just to populate with some types
  118. struct String;
  119. struct Condition;
  120. struct Opinion;
  121.  
  122. int main()
  123. {
  124. using MyList = type_list<int, char, bool>;
  125. using First = type_list_extract_t<0, MyList>;
  126. static_assert(std::is_same<First, int>::value, "!");
  127.  
  128. using SecondList = type_list<String, Condition, Opinion>;
  129. using Concat = type_list_concat_t<MyList, SecondList>;
  130. static_assert(std::is_same<type_list<int, char, bool, String, Condition, Opinion>, Concat>::value, "!");
  131.  
  132. using Expansion = type_list_expand_t<MyList>;
  133. static_assert(std::is_same<std::tuple<int, char, bool>, Expansion>::value, "!");
  134.  
  135. using PartialExpansion = type_list_expand_t<MyList, 0, 2>; //int, bool
  136. static_assert(std::is_same<std::tuple<int, bool>, PartialExpansion>::value, "!");
  137.  
  138. constexpr std::size_t sz = first_index_holder<2, 3, 4>::value;
  139. static_assert(sz == 2, "!");
  140.  
  141. using Seq = std::index_sequence<2, 3, 4>;
  142. using ReversedSeq = reverse_index_interval<Seq>::type;
  143. static_assert(std::is_same<ReversedSeq, std::index_sequence<4, 3, 2> >::value, "!");
  144.  
  145. using Rev = type_list_reverse_t<MyList>;
  146. static_assert(std::is_same<type_list<bool, char, int>, Rev>::value, "!");
  147.  
  148.  
  149. }
Success #stdin #stdout 0s 3408KB
stdin
Standard input is empty
stdout
Standard output is empty