1 | #pragma once |
2 | |
3 | #include <cstddef> |
4 | #include <utility> |
5 | #include <Core/Defines.h> |
6 | |
7 | namespace DB |
8 | { |
9 | |
10 | template <typename... TTail> |
11 | struct TypeList |
12 | { |
13 | static constexpr size_t size = 0; |
14 | |
15 | template <size_t I> |
16 | using At = std::nullptr_t; |
17 | |
18 | template <typename Func, size_t index = 0> |
19 | static void forEach(Func && /*func*/) |
20 | { |
21 | } |
22 | }; |
23 | |
24 | |
25 | template <typename THead, typename... TTail> |
26 | struct TypeList<THead, TTail...> |
27 | { |
28 | using Head = THead; |
29 | using Tail = TypeList<TTail...>; |
30 | |
31 | static constexpr size_t size = 1 + sizeof...(TTail); |
32 | |
33 | template <size_t I> |
34 | using At = typename std::template conditional_t<I == 0, Head, typename Tail::template At<I - 1>>; |
35 | |
36 | template <typename Func, size_t index = 0> |
37 | static void ALWAYS_INLINE forEach(Func && func) |
38 | { |
39 | func.template operator()<Head, index>(); |
40 | Tail::template forEach<Func, index + 1>(std::forward<Func>(func)); |
41 | } |
42 | }; |
43 | |
44 | /// Prepend Type to TypeList |
45 | /// Usage: |
46 | /// using TypeListWithType = typename AppendToTypeList<Type, ConcreteTypeList>::Type; |
47 | template <typename TypeToPrepend, typename List, typename ... Types> |
48 | struct PrependToTypeList |
49 | { |
50 | using Type = typename PrependToTypeList<TypeToPrepend, typename List::Tail, Types ..., typename List::Head>::Type; |
51 | }; |
52 | |
53 | template <typename TypeToPrepend, typename ... Types> |
54 | struct PrependToTypeList<TypeToPrepend, TypeList<>, Types ...> |
55 | { |
56 | using Type = TypeList<TypeToPrepend, Types ...>; |
57 | }; |
58 | |
59 | /// Append Type to TypeList |
60 | /// Usage: |
61 | /// using TypeListWithType = typename AppendToTypeList<Type, ConcreteTypeList>::Type; |
62 | template <typename TypeToAppend, typename List, typename ... Types> |
63 | struct AppendToTypeList |
64 | { |
65 | using Type = typename AppendToTypeList<TypeToAppend, typename List::Tail, Types ..., typename List::Head>::Type; |
66 | }; |
67 | |
68 | template <typename TypeToAppend, typename ... Types> |
69 | struct AppendToTypeList<TypeToAppend, TypeList<>, Types ...> |
70 | { |
71 | using Type = TypeList<Types ..., TypeToAppend>; |
72 | }; |
73 | |
74 | /// Apply TypeList as variadic template argument of Class. |
75 | /// Usage: |
76 | /// using ClassWithAppliedTypeList = typename ApplyTypeListForClass<Class, ConcreteTypeList>::Type; |
77 | template <template <typename ...> typename Class, typename List, typename ... Types> |
78 | struct ApplyTypeListForClass |
79 | { |
80 | using Type = typename ApplyTypeListForClass<Class, typename List::Tail, Types ..., typename List::Head>::Type; |
81 | }; |
82 | |
83 | template <template <typename ...> typename Class, typename ... Types> |
84 | struct ApplyTypeListForClass<Class, TypeList<>, Types ...> |
85 | { |
86 | using Type = Class<Types ...>; |
87 | }; |
88 | |
89 | /// TypeList concatenation. |
90 | /// Usage: |
91 | /// using ResultTypeList = typename TypeListConcat<LeftList, RightList>::Type; |
92 | template <typename TypeListLeft, typename TypeListRight> |
93 | struct TypeListConcat |
94 | { |
95 | using Type = typename TypeListConcat< |
96 | typename AppendToTypeList<typename TypeListRight::Head, TypeListLeft>::Type, |
97 | typename TypeListRight::Tail>::Type; |
98 | }; |
99 | |
100 | template <typename TypeListLeft> |
101 | struct TypeListConcat<TypeListLeft, TypeList<>> |
102 | { |
103 | using Type = TypeListLeft; |
104 | }; |
105 | |
106 | /// TypeList Map function. |
107 | /// Usage: |
108 | /// using ResultTypeList = typename TypeListMap<Function, TypeListArgs>::Type; |
109 | template <template <typename> typename Function, typename TypeListArgs> |
110 | struct TypeListMap |
111 | { |
112 | using Type = typename PrependToTypeList< |
113 | Function<typename TypeListArgs::Head>, |
114 | typename TypeListMap<Function, typename TypeListArgs::Tail>::Type>::Type; |
115 | }; |
116 | |
117 | template <template <typename> typename Function> |
118 | struct TypeListMap<Function, TypeList<>> |
119 | { |
120 | using Type = TypeList<>; |
121 | }; |
122 | |
123 | } |
124 | |