| 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 | |