added iOS source code
[wl-app.git] / iOS / Pods / Realm / include / core / realm / util / type_list.hpp
1 /*************************************************************************
2  *
3  * Copyright 2016 Realm Inc.
4  *
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
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
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.
16  *
17  **************************************************************************/
18
19 #ifndef REALM_UTIL_TYPE_LIST_HPP
20 #define REALM_UTIL_TYPE_LIST_HPP
21
22 namespace realm {
23 namespace util {
24
25
26 /// The 'cons' operator for building lists of types.
27 ///
28 /// \tparam H The head of the list, that is, the first type in the
29 /// list.
30 ///
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>.
34 ///
35 /// Note that 'void' is interpreted as a zero-length list.
36 template <class H, class T>
37 struct TypeCons {
38     typedef H head;
39     typedef T tail;
40 };
41
42
43 /// Append a type the the end of a type list. The resulting type list
44 /// is available as TypeAppend<List, T>::type.
45 ///
46 /// \tparam List A list of types constructed using TypeCons<>. Note
47 /// that 'void' is interpreted as a zero-length list.
48 ///
49 /// \tparam T The new type to be appended.
50 template <class List, class T>
51 struct TypeAppend {
52     typedef TypeCons<typename List::head, typename TypeAppend<typename List::tail, T>::type> type;
53 };
54 /// Base case for empty type list.
55 template <class T>
56 struct TypeAppend<void, T> {
57     typedef TypeCons<T, void> type;
58 };
59
60
61 /// Get an element from the specified list of types. The result is
62 /// available as TypeAt<List, i>::type.
63 ///
64 /// \tparam List A list of types constructed using TypeCons<>. Note
65 /// that 'void' is interpreted as a zero-length list.
66 ///
67 /// \tparam i The index of the list element to get.
68 template <class List, int i>
69 struct TypeAt {
70     typedef typename TypeAt<typename List::tail, i - 1>::type type;
71 };
72 /// Base case for empty type list.
73 template <class List>
74 struct TypeAt<List, 0> {
75     typedef typename List::head type;
76 };
77
78
79 /// Count the number of elements in the specified list of types. The
80 /// result is available as TypeCount<List>::value.
81 ///
82 /// \tparam List The list of types, constructed using TypeCons<>. Note
83 /// that 'void' is interpreted as a zero-length list.
84 template <class List>
85 struct TypeCount {
86     static const int value = 1 + TypeCount<typename List::tail>::value;
87 };
88 /// Base case for empty type list.
89 template <>
90 struct TypeCount<void> {
91     static const int value = 0;
92 };
93
94
95 /// Find the first type in the specified list that satisfies the
96 /// specified predicate.
97 ///
98 /// \tparam List The list of types, constructed using TypeCons<>. Note
99 /// that 'void' is interpreted as a zero-length list.
100 ///
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>
104 struct FindType {
105 private:
106     typedef typename List::head type_1;
107     typedef typename FindType<typename List::tail, Pred>::type type_2;
108
109 public:
110     typedef typename std::conditional<Pred<type_1>::value, type_1, type_2>::type type;
111 };
112 /// Base case for empty type list.
113 template <template <class> class Pred>
114 struct FindType<void, Pred> {
115     typedef void type;
116 };
117
118
119 /// Execute an action for each element in the specified list of types.
120 ///
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>
124 struct ForEachType {
125     /// Execute the `Op<T,i>::%exec()` for each type `T` at index `i`
126     /// in `List`.
127     static void exec()
128     {
129         Op<typename List::head, i>::exec();
130         ForEachType<typename List::tail, Op, i + 1>::exec();
131     }
132     /// Execute the `Op<T,i>::%exec(a)` for each type `T` at index `i`
133     /// in `List`.
134     template <class A>
135     static void exec(const A& a)
136     {
137         Op<typename List::head, i>::exec(a);
138         ForEachType<typename List::tail, Op, i + 1>::exec(a);
139     }
140     /// Execute the `Op<T,i>::%exec(a,b)` for each type `T` at index
141     /// `i` in `List`.
142     template <class A, class B>
143     static void exec(const A& a, const B& b)
144     {
145         Op<typename List::head, i>::exec(a, b);
146         ForEachType<typename List::tail, Op, i + 1>::exec(a, b);
147     }
148     /// Execute the `Op<T,i>::%exec(a,b,c)` for each type `T` at index
149     /// `i` in `List`.
150     template <class A, class B, class C>
151     static void exec(const A& a, const B& b, const C& c)
152     {
153         Op<typename List::head, i>::exec(a, b, c);
154         ForEachType<typename List::tail, Op, i + 1>::exec(a, b, c);
155     }
156 };
157 /// Base case for empty type list.
158 template <template <class T, int i> class Op, int i>
159 struct ForEachType<void, Op, i> {
160     static void exec()
161     {
162     }
163     template <class A>
164     static void exec(const A&)
165     {
166     }
167     template <class A, class B>
168     static void exec(const A&, const B&)
169     {
170     }
171     template <class A, class B, class C>
172     static void exec(const A&, const B&, const C&)
173     {
174     }
175 };
176
177
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.
182 ///
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>
186 struct HasType {
187     /// Execute the `Op<T,i>::%exec()` for each type `T` at index `i`
188     /// in `List`.
189     static bool exec()
190     {
191         return Pred<typename List::head, i>::exec() || HasType<typename List::tail, Pred, i + 1>::exec();
192     }
193     /// Execute the `Op<T,i>::%exec(a)` for each type `T` at index `i`
194     /// in `List`.
195     template <class A>
196     static bool exec(const A& a)
197     {
198         return Pred<typename List::head, i>::exec(a) || HasType<typename List::tail, Pred, i + 1>::exec(a);
199     }
200     /// Execute the `Op<T,i>::%exec(a,b)` for each type `T` at index
201     /// `i` in `List`.
202     template <class A, class B>
203     static bool exec(const A& a, const B& b)
204     {
205         return Pred<typename List::head, i>::exec(a, b) || HasType<typename List::tail, Pred, i + 1>::exec(a, b);
206     }
207     /// Execute the `Op<T,i>::%exec(a,b,c)` for each type `T` at index
208     /// `i` in `List`.
209     template <class A, class B, class C>
210     static bool exec(const A& a, const B& b, const C& c)
211     {
212         return Pred<typename List::head, i>::exec(a, b, c) ||
213                HasType<typename List::tail, Pred, i + 1>::exec(a, b, c);
214     }
215 };
216 /// Base case for empty type list.
217 template <template <class T, int i> class Pred, int i>
218 struct HasType<void, Pred, i> {
219     static bool exec()
220     {
221         return false;
222     }
223     template <class A>
224     static bool exec(const A&)
225     {
226         return false;
227     }
228     template <class A, class B>
229     static bool exec(const A&, const B&)
230     {
231         return false;
232     }
233     template <class A, class B, class C>
234     static bool exec(const A&, const B&, const C&)
235     {
236         return false;
237     }
238 };
239
240
241 } // namespace util
242 } // namespace realm
243
244 #endif // REALM_UTIL_TYPE_LIST_HPP