1 /*************************************************************************
3 * Copyright 2016 Realm Inc.
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
17 **************************************************************************/
19 #ifndef REALM_UTIL_TYPE_LIST_HPP
20 #define REALM_UTIL_TYPE_LIST_HPP
26 /// The 'cons' operator for building lists of types.
28 /// \tparam H The head of the list, that is, the first type in the
31 /// \tparam T The tail of the list, that is, the list of types
32 /// following the head. It is 'void' if nothing follows the head,
33 /// otherwise it matches TypeCons<H2,T2>.
35 /// Note that 'void' is interpreted as a zero-length list.
36 template <class H, class T>
43 /// Append a type the the end of a type list. The resulting type list
44 /// is available as TypeAppend<List, T>::type.
46 /// \tparam List A list of types constructed using TypeCons<>. Note
47 /// that 'void' is interpreted as a zero-length list.
49 /// \tparam T The new type to be appended.
50 template <class List, class T>
52 typedef TypeCons<typename List::head, typename TypeAppend<typename List::tail, T>::type> type;
54 /// Base case for empty type list.
56 struct TypeAppend<void, T> {
57 typedef TypeCons<T, void> type;
61 /// Get an element from the specified list of types. The result is
62 /// available as TypeAt<List, i>::type.
64 /// \tparam List A list of types constructed using TypeCons<>. Note
65 /// that 'void' is interpreted as a zero-length list.
67 /// \tparam i The index of the list element to get.
68 template <class List, int i>
70 typedef typename TypeAt<typename List::tail, i - 1>::type type;
72 /// Base case for empty type list.
74 struct TypeAt<List, 0> {
75 typedef typename List::head type;
79 /// Count the number of elements in the specified list of types. The
80 /// result is available as TypeCount<List>::value.
82 /// \tparam List The list of types, constructed using TypeCons<>. Note
83 /// that 'void' is interpreted as a zero-length list.
86 static const int value = 1 + TypeCount<typename List::tail>::value;
88 /// Base case for empty type list.
90 struct TypeCount<void> {
91 static const int value = 0;
95 /// Find the first type in the specified list that satisfies the
96 /// specified predicate.
98 /// \tparam List The list of types, constructed using TypeCons<>. Note
99 /// that 'void' is interpreted as a zero-length list.
101 /// \tparam Pred Must be such that `Pred<T>::%value` is true if, and
102 /// only if the predicate is satisfied for `T`.
103 template <class List, template <class> class Pred>
106 typedef typename List::head type_1;
107 typedef typename FindType<typename List::tail, Pred>::type type_2;
110 typedef typename std::conditional<Pred<type_1>::value, type_1, type_2>::type type;
112 /// Base case for empty type list.
113 template <template <class> class Pred>
114 struct FindType<void, Pred> {
119 /// Execute an action for each element in the specified list of types.
121 /// \tparam List The list of types, constructed using TypeCons<>. Note
122 /// that 'void' is interpreted as a zero-length list.
123 template <class List, template <class T, int i> class Op, int i = 0>
125 /// Execute the `Op<T,i>::%exec()` for each type `T` at index `i`
129 Op<typename List::head, i>::exec();
130 ForEachType<typename List::tail, Op, i + 1>::exec();
132 /// Execute the `Op<T,i>::%exec(a)` for each type `T` at index `i`
135 static void exec(const A& a)
137 Op<typename List::head, i>::exec(a);
138 ForEachType<typename List::tail, Op, i + 1>::exec(a);
140 /// Execute the `Op<T,i>::%exec(a,b)` for each type `T` at index
142 template <class A, class B>
143 static void exec(const A& a, const B& b)
145 Op<typename List::head, i>::exec(a, b);
146 ForEachType<typename List::tail, Op, i + 1>::exec(a, b);
148 /// Execute the `Op<T,i>::%exec(a,b,c)` for each type `T` at index
150 template <class A, class B, class C>
151 static void exec(const A& a, const B& b, const C& c)
153 Op<typename List::head, i>::exec(a, b, c);
154 ForEachType<typename List::tail, Op, i + 1>::exec(a, b, c);
157 /// Base case for empty type list.
158 template <template <class T, int i> class Op, int i>
159 struct ForEachType<void, Op, i> {
164 static void exec(const A&)
167 template <class A, class B>
168 static void exec(const A&, const B&)
171 template <class A, class B, class C>
172 static void exec(const A&, const B&, const C&)
178 /// Execute a predicate for each element in the specified list of
179 /// types, and return true if, and only if the predicate returns true
180 /// for at least one of those elements. Iteration over the type list
181 /// is terminated as soon as a predicate returns true.
183 /// \tparam List The list of types, constructed using TypeCons<>. Note
184 /// that 'void' is interpreted as a zero-length list.
185 template <class List, template <class T, int i> class Pred, int i = 0>
187 /// Execute the `Op<T,i>::%exec()` for each type `T` at index `i`
191 return Pred<typename List::head, i>::exec() || HasType<typename List::tail, Pred, i + 1>::exec();
193 /// Execute the `Op<T,i>::%exec(a)` for each type `T` at index `i`
196 static bool exec(const A& a)
198 return Pred<typename List::head, i>::exec(a) || HasType<typename List::tail, Pred, i + 1>::exec(a);
200 /// Execute the `Op<T,i>::%exec(a,b)` for each type `T` at index
202 template <class A, class B>
203 static bool exec(const A& a, const B& b)
205 return Pred<typename List::head, i>::exec(a, b) || HasType<typename List::tail, Pred, i + 1>::exec(a, b);
207 /// Execute the `Op<T,i>::%exec(a,b,c)` for each type `T` at index
209 template <class A, class B, class C>
210 static bool exec(const A& a, const B& b, const C& c)
212 return Pred<typename List::head, i>::exec(a, b, c) ||
213 HasType<typename List::tail, Pred, i + 1>::exec(a, b, c);
216 /// Base case for empty type list.
217 template <template <class T, int i> class Pred, int i>
218 struct HasType<void, Pred, i> {
224 static bool exec(const A&)
228 template <class A, class B>
229 static bool exec(const A&, const B&)
233 template <class A, class B, class C>
234 static bool exec(const A&, const B&, const C&)
244 #endif // REALM_UTIL_TYPE_LIST_HPP