1 | // |
2 | // TypeList.h |
3 | // |
4 | // Library: Foundation |
5 | // Package: Core |
6 | // Module: TypeList |
7 | // |
8 | // Implementation of the TypeList template. |
9 | // |
10 | // Copyright (c) 2006, Applied Informatics Software Engineering GmbH. |
11 | // and Contributors. |
12 | // |
13 | // Portions extracted and adapted from |
14 | // The Loki Library |
15 | // Copyright (c) 2001 by Andrei Alexandrescu |
16 | // |
17 | // SPDX-License-Identifier: BSL-1.0 |
18 | // |
19 | |
20 | |
21 | #ifndef Foundation_TypeList_INCLUDED |
22 | #define Foundation_TypeList_INCLUDED |
23 | |
24 | |
25 | #include "Poco/Foundation.h" |
26 | #include "Poco/MetaProgramming.h" |
27 | |
28 | |
29 | namespace Poco { |
30 | |
31 | |
32 | template <class Head, class Tail> |
33 | struct TypeList; |
34 | |
35 | |
36 | struct NullTypeList |
37 | { |
38 | enum |
39 | { |
40 | length = 0 |
41 | }; |
42 | |
43 | bool operator == (const NullTypeList&) const |
44 | { |
45 | return true; |
46 | } |
47 | |
48 | bool operator != (const NullTypeList&) const |
49 | { |
50 | return false; |
51 | } |
52 | |
53 | bool operator < (const NullTypeList&) const |
54 | { |
55 | return false; |
56 | } |
57 | }; |
58 | |
59 | |
60 | template <class Head, class Tail> |
61 | struct TypeList |
62 | /// Compile Time List of Types |
63 | { |
64 | typedef Head HeadType; |
65 | typedef Tail TailType; |
66 | typedef typename TypeWrapper<HeadType>::CONSTTYPE ConstHeadType; |
67 | typedef typename TypeWrapper<TailType>::CONSTTYPE ConstTailType; |
68 | enum |
69 | { |
70 | length = TailType::length+1 |
71 | }; |
72 | |
73 | TypeList():head(), tail() |
74 | { |
75 | } |
76 | |
77 | TypeList(ConstHeadType& h, ConstTailType& t):head(h), tail(t) |
78 | { |
79 | } |
80 | |
81 | TypeList(const TypeList& tl): head(tl.head), tail(tl.tail) |
82 | { |
83 | } |
84 | |
85 | TypeList& operator = (const TypeList& tl) |
86 | { |
87 | if (this != &tl) |
88 | { |
89 | head = tl.head; |
90 | tail = tl.tail; |
91 | } |
92 | return *this; |
93 | } |
94 | |
95 | bool operator == (const TypeList& tl) const |
96 | { |
97 | return tl.head == head && tl.tail == tail; |
98 | } |
99 | |
100 | bool operator != (const TypeList& tl) const |
101 | { |
102 | return !(*this == tl); |
103 | } |
104 | |
105 | bool operator < (const TypeList& tl) const |
106 | { |
107 | if (head < tl.head) |
108 | return true; |
109 | else if (head == tl.head) |
110 | return tail < tl.tail; |
111 | return false; |
112 | } |
113 | |
114 | HeadType head; |
115 | TailType tail; |
116 | }; |
117 | |
118 | |
119 | template <typename T0 = NullTypeList, |
120 | typename T1 = NullTypeList, |
121 | typename T2 = NullTypeList, |
122 | typename T3 = NullTypeList, |
123 | typename T4 = NullTypeList, |
124 | typename T5 = NullTypeList, |
125 | typename T6 = NullTypeList, |
126 | typename T7 = NullTypeList, |
127 | typename T8 = NullTypeList, |
128 | typename T9 = NullTypeList, |
129 | typename T10 = NullTypeList, |
130 | typename T11 = NullTypeList, |
131 | typename T12 = NullTypeList, |
132 | typename T13 = NullTypeList, |
133 | typename T14 = NullTypeList, |
134 | typename T15 = NullTypeList, |
135 | typename T16 = NullTypeList, |
136 | typename T17 = NullTypeList, |
137 | typename T18 = NullTypeList, |
138 | typename T19 = NullTypeList, |
139 | typename T20 = NullTypeList, |
140 | typename T21 = NullTypeList, |
141 | typename T22 = NullTypeList, |
142 | typename T23 = NullTypeList, |
143 | typename T24 = NullTypeList, |
144 | typename T25 = NullTypeList, |
145 | typename T26 = NullTypeList, |
146 | typename T27 = NullTypeList, |
147 | typename T28 = NullTypeList, |
148 | typename T29 = NullTypeList, |
149 | typename T30 = NullTypeList, |
150 | typename T31 = NullTypeList, |
151 | typename T32 = NullTypeList, |
152 | typename T33 = NullTypeList, |
153 | typename T34 = NullTypeList, |
154 | typename T35 = NullTypeList, |
155 | typename T36 = NullTypeList, |
156 | typename T37 = NullTypeList, |
157 | typename T38 = NullTypeList, |
158 | typename T39 = NullTypeList> |
159 | struct TypeListType |
160 | /// TypeListType takes 1 - 40 typename arguments. |
161 | /// Usage: |
162 | /// |
163 | /// TypeListType<T0, T1, ... , Tn>::HeadType typeList; |
164 | /// |
165 | /// typeList is a TypeList of T0, T1, ... , Tn |
166 | { |
167 | private: |
168 | typedef typename |
169 | TypeListType<T1,T2, T3, T4, T5, T6, T7, T8, T9, T10, |
170 | T11,T12,T13,T14,T15,T16,T17,T18,T19,T20, |
171 | T21,T22,T23,T24,T25,T26,T27,T28,T29,T30, |
172 | T31,T32,T33,T34,T35,T36,T37,T38,T39>::HeadType TailType; |
173 | |
174 | public: |
175 | typedef TypeList<T0, TailType> HeadType; |
176 | }; |
177 | |
178 | |
179 | template <> |
180 | struct TypeListType<> |
181 | { |
182 | typedef NullTypeList HeadType; |
183 | }; |
184 | |
185 | |
186 | template <int n> |
187 | struct Getter |
188 | { |
189 | template <class Ret, class Head, class Tail> |
190 | inline static Ret& get(TypeList<Head, Tail>& val) |
191 | { |
192 | return Getter<n-1>::template get<Ret, typename Tail::HeadType, typename Tail::TailType>(val.tail); |
193 | } |
194 | |
195 | template <class Ret, class Head, class Tail> |
196 | inline static const Ret& get(const TypeList<Head, Tail>& val) |
197 | { |
198 | return Getter<n-1>::template get<Ret, typename Tail::HeadType, typename Tail::TailType>(val.tail); |
199 | } |
200 | }; |
201 | |
202 | |
203 | template <> |
204 | struct Getter<0> |
205 | { |
206 | template <class Ret, class Head, class Tail> |
207 | inline static Ret& get(TypeList<Head, Tail>& val) |
208 | { |
209 | return val.head; |
210 | } |
211 | |
212 | template <class Ret, class Head, class Tail> |
213 | inline static const Ret& get(const TypeList<Head, Tail>& val) |
214 | { |
215 | return val.head; |
216 | } |
217 | }; |
218 | |
219 | |
220 | template <int N, class Head> |
221 | struct TypeGetter; |
222 | |
223 | |
224 | template <int N, class Head, class Tail> |
225 | struct TypeGetter<N, TypeList<Head, Tail> > |
226 | { |
227 | typedef typename TypeGetter<N-1, Tail>::HeadType HeadType; |
228 | typedef typename TypeWrapper<HeadType>::CONSTTYPE ConstHeadType; |
229 | }; |
230 | |
231 | |
232 | template <class Head, class Tail> |
233 | struct TypeGetter<0, TypeList<Head, Tail> > |
234 | { |
235 | typedef typename TypeList<Head, Tail>::HeadType HeadType; |
236 | typedef typename TypeWrapper<HeadType>::CONSTTYPE ConstHeadType; |
237 | }; |
238 | |
239 | |
240 | template <class Head, class T> |
241 | struct TypeLocator; |
242 | /// TypeLocator returns the first occurrence of the type T in Head |
243 | /// or -1 if the type is not found. |
244 | /// |
245 | /// Usage example: |
246 | /// |
247 | /// TypeLocator<Head, int>::HeadType TypeLoc; |
248 | /// |
249 | /// if (2 == TypeLoc.value) ... |
250 | /// |
251 | |
252 | |
253 | template <class T> |
254 | struct TypeLocator<NullTypeList, T> |
255 | { |
256 | enum { value = -1 }; |
257 | }; |
258 | |
259 | |
260 | template <class T, class Tail> |
261 | struct TypeLocator<TypeList<T, Tail>, T> |
262 | { |
263 | enum { value = 0 }; |
264 | }; |
265 | |
266 | |
267 | template <class Head, class Tail, class T> |
268 | struct TypeLocator<TypeList<Head, Tail>, T> |
269 | { |
270 | private: |
271 | enum { tmp = TypeLocator<Tail, T>::value }; |
272 | public: |
273 | enum { value = tmp == -1 ? -1 : 1 + tmp }; |
274 | }; |
275 | |
276 | |
277 | template <class Head, class T> |
278 | struct TypeAppender; |
279 | /// TypeAppender appends T (type or a TypeList) to Head. |
280 | /// |
281 | /// Usage: |
282 | /// |
283 | /// typedef TypeListType<char>::HeadType Type1; |
284 | /// typedef TypeAppender<Type1, int>::HeadType Type2; |
285 | /// (Type2 is a TypeList of char,int) |
286 | /// |
287 | /// typedef TypeListType<float, double>::HeadType Type3; |
288 | /// typedef TypeAppender<Type2, Type3>::HeadType Type4; |
289 | /// (Type4 is a TypeList of char,int,float,double) |
290 | /// |
291 | |
292 | |
293 | template <> |
294 | struct TypeAppender<NullTypeList, NullTypeList> |
295 | { |
296 | typedef NullTypeList HeadType; |
297 | }; |
298 | |
299 | |
300 | template <class T> |
301 | struct TypeAppender<NullTypeList, T> |
302 | { |
303 | typedef TypeList<T, NullTypeList> HeadType; |
304 | }; |
305 | |
306 | |
307 | template <class Head, class Tail> |
308 | struct TypeAppender<NullTypeList, TypeList<Head, Tail> > |
309 | { |
310 | typedef TypeList<Head, Tail> HeadType; |
311 | }; |
312 | |
313 | |
314 | template <class Head, class Tail, class T> |
315 | struct TypeAppender<TypeList<Head, Tail>, T> |
316 | { |
317 | typedef TypeList<Head, typename TypeAppender<Tail, T>::HeadType> HeadType; |
318 | }; |
319 | |
320 | |
321 | template <class Head, class T> |
322 | struct TypeOneEraser; |
323 | /// TypeOneEraser erases the first occurrence of the type T in Head. |
324 | /// Usage: |
325 | /// |
326 | /// typedef TypeListType<char, int, float>::HeadType Type3; |
327 | /// typedef TypeOneEraser<Type3, int>::HeadType Type2; |
328 | /// (Type2 is a TypeList of char,float) |
329 | /// |
330 | |
331 | |
332 | template <class T> |
333 | struct TypeOneEraser<NullTypeList, T> |
334 | { |
335 | typedef NullTypeList HeadType; |
336 | }; |
337 | |
338 | |
339 | template <class T, class Tail> |
340 | struct TypeOneEraser<TypeList<T, Tail>, T> |
341 | { |
342 | typedef Tail HeadType; |
343 | }; |
344 | |
345 | |
346 | template <class Head, class Tail, class T> |
347 | struct TypeOneEraser<TypeList<Head, Tail>, T> |
348 | { |
349 | typedef TypeList <Head, typename TypeOneEraser<Tail, T>::HeadType> HeadType; |
350 | }; |
351 | |
352 | |
353 | template <class Head, class T> |
354 | struct TypeAllEraser; |
355 | /// TypeAllEraser erases all the occurrences of the type T in Head. |
356 | /// Usage: |
357 | /// |
358 | /// typedef TypeListType<char, int, float, int>::HeadType Type4; |
359 | /// typedef TypeAllEraser<Type4, int>::HeadType Type2; |
360 | /// (Type2 is a TypeList of char,float) |
361 | /// |
362 | |
363 | |
364 | template <class T> |
365 | struct TypeAllEraser<NullTypeList, T> |
366 | { |
367 | typedef NullTypeList HeadType; |
368 | }; |
369 | |
370 | |
371 | template <class T, class Tail> |
372 | struct TypeAllEraser<TypeList<T, Tail>, T> |
373 | { |
374 | typedef typename TypeAllEraser<Tail, T>::HeadType HeadType; |
375 | }; |
376 | |
377 | |
378 | template <class Head, class Tail, class T> |
379 | struct TypeAllEraser<TypeList<Head, Tail>, T> |
380 | { |
381 | typedef TypeList <Head, typename TypeAllEraser<Tail, T>::HeadType> HeadType; |
382 | }; |
383 | |
384 | |
385 | template <class Head> |
386 | struct TypeDuplicateEraser; |
387 | /// TypeDuplicateEraser erases all but the first occurrence of the type T in Head. |
388 | /// Usage: |
389 | /// |
390 | /// typedef TypeListType<char, int, float, int>::HeadType Type4; |
391 | /// typedef TypeDuplicateEraser<Type4, int>::HeadType Type3; |
392 | /// (Type3 is a TypeList of char,int,float) |
393 | /// |
394 | |
395 | |
396 | template <> |
397 | struct TypeDuplicateEraser<NullTypeList> |
398 | { |
399 | typedef NullTypeList HeadType; |
400 | }; |
401 | |
402 | |
403 | template <class Head, class Tail> |
404 | struct TypeDuplicateEraser<TypeList<Head, Tail> > |
405 | { |
406 | private: |
407 | typedef typename TypeDuplicateEraser<Tail>::HeadType L1; |
408 | typedef typename TypeOneEraser<L1, Head>::HeadType L2; |
409 | public: |
410 | typedef TypeList<Head, L2> HeadType; |
411 | }; |
412 | |
413 | |
414 | template <class Head, class T, class R> |
415 | struct TypeOneReplacer; |
416 | /// TypeOneReplacer replaces the first occurrence |
417 | /// of the type T in Head with type R. |
418 | /// Usage: |
419 | /// |
420 | /// typedef TypeListType<char, int, float, int>::HeadType Type4; |
421 | /// typedef TypeOneReplacer<Type4, int, double>::HeadType TypeR; |
422 | /// (TypeR is a TypeList of char,double,float,int) |
423 | /// |
424 | |
425 | |
426 | template <class T, class R> |
427 | struct TypeOneReplacer<NullTypeList, T, R> |
428 | { |
429 | typedef NullTypeList HeadType; |
430 | }; |
431 | |
432 | |
433 | template <class T, class Tail, class R> |
434 | struct TypeOneReplacer<TypeList<T, Tail>, T, R> |
435 | { |
436 | typedef TypeList<R, Tail> HeadType; |
437 | }; |
438 | |
439 | |
440 | template <class Head, class Tail, class T, class R> |
441 | struct TypeOneReplacer<TypeList<Head, Tail>, T, R> |
442 | { |
443 | typedef TypeList<Head, typename TypeOneReplacer<Tail, T, R>::HeadType> HeadType; |
444 | }; |
445 | |
446 | |
447 | template <class Head, class T, class R> |
448 | struct TypeAllReplacer; |
449 | /// TypeAllReplacer replaces all the occurrences |
450 | /// of the type T in Head with type R. |
451 | /// Usage: |
452 | /// |
453 | /// typedef TypeListType<char, int, float, int>::HeadType Type4; |
454 | /// typedef TypeAllReplacer<Type4, int, double>::HeadType TypeR; |
455 | /// (TypeR is a TypeList of char,double,float,double) |
456 | /// |
457 | |
458 | |
459 | template <class T, class R> |
460 | struct TypeAllReplacer<NullTypeList, T, R> |
461 | { |
462 | typedef NullTypeList HeadType; |
463 | }; |
464 | |
465 | |
466 | template <class T, class Tail, class R> |
467 | struct TypeAllReplacer<TypeList<T, Tail>, T, R> |
468 | { |
469 | typedef TypeList<R, typename TypeAllReplacer<Tail, T, R>::HeadType> HeadType; |
470 | }; |
471 | |
472 | |
473 | template <class Head, class Tail, class T, class R> |
474 | struct TypeAllReplacer<TypeList<Head, Tail>, T, R> |
475 | { |
476 | typedef TypeList<Head, typename TypeAllReplacer<Tail, T, R>::HeadType> HeadType; |
477 | }; |
478 | |
479 | |
480 | } // namespace Poco |
481 | |
482 | |
483 | #endif // Foundation_TypeList_INCLUDED |
484 | |