fork download
  1. #include <iostream>
  2. #include <tuple>
  3. #include <type_traits>
  4.  
  5. template <typename T> struct Identity { using type = T; };
  6.  
  7. // Merging packs of types.
  8. template <typename...> struct MergePacks;
  9.  
  10. template <typename Pack>
  11. struct MergePacks<Pack> : Identity<Pack> {};
  12.  
  13. template <template <typename...> class P, typename... Types1, typename... Types2, typename... Packs>
  14. struct MergePacks<P<Types1...>, P<Types2...>, Packs...> : MergePacks<P<Types1..., Types2...>, Packs...> {};
  15.  
  16. // Appending a type to a pack.
  17. template <typename Pack, typename T> struct AppendType;
  18.  
  19. template <template <typename...> class P, typename... Ts, typename T>
  20. struct AppendType <P<Ts...>, T> {
  21. using type = P<Ts..., T>;
  22. };
  23.  
  24. // ExpandPackWithTuple takes a pack, and creates N packs that each end with the tuple's elements, N is the size of the tuple.
  25. template <template <typename...> class P, typename Pack, typename Tuple, typename Indices> struct ExpandPackWithTupleHelper;
  26.  
  27. template <template <typename...> class P, typename Pack, typename Tuple, std::size_t... Is>
  28. struct ExpandPackWithTupleHelper<P, Pack, Tuple, std::index_sequence<Is...>> {
  29. using type = P<typename AppendType<Pack, typename std::tuple_element<Is, Tuple>::type>::type...>;
  30. };
  31.  
  32. template <template <typename...> class P, typename Pack, typename Tuple>
  33. using ExpandPackWithTuple = typename ExpandPackWithTupleHelper<P, Pack, Tuple, std::make_index_sequence<std::tuple_size<Tuple>::value>>::type;
  34.  
  35. // Now, for TupleTree itself.
  36. template <template <typename...> class P, typename OutputPack, typename... Tuples> struct TupleTreeHelper;
  37.  
  38. template <template <typename...> class P, typename... Ts, typename First, typename... Rest>
  39. struct TupleTreeHelper<P, P<Ts...>, First, Rest...> : TupleTreeHelper<P, typename MergePacks<ExpandPackWithTuple<P, Ts, First>...>::type, Rest...> {};
  40.  
  41. template <template <typename...> class P, typename OutputPack>
  42. struct TupleTreeHelper<P, OutputPack> {
  43. using type = OutputPack;
  44. };
  45.  
  46. template <template <typename...> class P, typename... Tuples>
  47. using TupleTree = typename TupleTreeHelper<P, P<P<>>, Tuples...>::type;
  48.  
  49. // Testing
  50. template <typename...> struct Pack;
  51. using T1 = std::tuple<int, char, double>;
  52. using T2 = std::tuple<bool, double, int, char>;
  53.  
  54. int main() {
  55. std::cout << std::boolalpha << std::is_same<
  56. TupleTree<Pack, T1, T2>,
  57. Pack<
  58. Pack<int, bool>, Pack<int, double>, Pack<int, int>, Pack<int, char>,
  59. Pack<char, bool>, Pack<char, double>, Pack<char, int>, Pack<char, char>,
  60. Pack<double, bool>, Pack<double, double>, Pack<double, int>, Pack<double, char>
  61. >
  62. >::value << '\n'; // true
  63. }
  64.  
Success #stdin #stdout 0s 3456KB
stdin
Standard input is empty
stdout
true