1#pragma once
2
3#include <cstddef>
4#include <utility>
5#include <Core/Defines.h>
6
7namespace DB
8{
9
10template <typename... TTail>
11struct 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
25template <typename THead, typename... TTail>
26struct 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;
47template <typename TypeToPrepend, typename List, typename ... Types>
48struct PrependToTypeList
49{
50 using Type = typename PrependToTypeList<TypeToPrepend, typename List::Tail, Types ..., typename List::Head>::Type;
51};
52
53template <typename TypeToPrepend, typename ... Types>
54struct 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;
62template <typename TypeToAppend, typename List, typename ... Types>
63struct AppendToTypeList
64{
65 using Type = typename AppendToTypeList<TypeToAppend, typename List::Tail, Types ..., typename List::Head>::Type;
66};
67
68template <typename TypeToAppend, typename ... Types>
69struct 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;
77template <template <typename ...> typename Class, typename List, typename ... Types>
78struct ApplyTypeListForClass
79{
80 using Type = typename ApplyTypeListForClass<Class, typename List::Tail, Types ..., typename List::Head>::Type;
81};
82
83template <template <typename ...> typename Class, typename ... Types>
84struct 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;
92template <typename TypeListLeft, typename TypeListRight>
93struct TypeListConcat
94{
95 using Type = typename TypeListConcat<
96 typename AppendToTypeList<typename TypeListRight::Head, TypeListLeft>::Type,
97 typename TypeListRight::Tail>::Type;
98};
99
100template <typename TypeListLeft>
101struct TypeListConcat<TypeListLeft, TypeList<>>
102{
103 using Type = TypeListLeft;
104};
105
106/// TypeList Map function.
107/// Usage:
108/// using ResultTypeList = typename TypeListMap<Function, TypeListArgs>::Type;
109template <template <typename> typename Function, typename TypeListArgs>
110struct TypeListMap
111{
112 using Type = typename PrependToTypeList<
113 Function<typename TypeListArgs::Head>,
114 typename TypeListMap<Function, typename TypeListArgs::Tail>::Type>::Type;
115};
116
117template <template <typename> typename Function>
118struct TypeListMap<Function, TypeList<>>
119{
120 using Type = TypeList<>;
121};
122
123}
124