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
29namespace Poco {
30
31
32template <class Head, class Tail>
33struct TypeList;
34
35
36struct 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
60template <class Head, class Tail>
61struct 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
119template <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>
159struct 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{
167private:
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
174public:
175 typedef TypeList<T0, TailType> HeadType;
176};
177
178
179template <>
180struct TypeListType<>
181{
182 typedef NullTypeList HeadType;
183};
184
185
186template <int n>
187struct 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
203template <>
204struct 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
220template <int N, class Head>
221struct TypeGetter;
222
223
224template <int N, class Head, class Tail>
225struct 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
232template <class Head, class Tail>
233struct TypeGetter<0, TypeList<Head, Tail> >
234{
235 typedef typename TypeList<Head, Tail>::HeadType HeadType;
236 typedef typename TypeWrapper<HeadType>::CONSTTYPE ConstHeadType;
237};
238
239
240template <class Head, class T>
241struct 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
253template <class T>
254struct TypeLocator<NullTypeList, T>
255{
256 enum { value = -1 };
257};
258
259
260template <class T, class Tail>
261struct TypeLocator<TypeList<T, Tail>, T>
262{
263 enum { value = 0 };
264};
265
266
267template <class Head, class Tail, class T>
268struct TypeLocator<TypeList<Head, Tail>, T>
269{
270private:
271 enum { tmp = TypeLocator<Tail, T>::value };
272public:
273 enum { value = tmp == -1 ? -1 : 1 + tmp };
274};
275
276
277template <class Head, class T>
278struct 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
293template <>
294struct TypeAppender<NullTypeList, NullTypeList>
295{
296 typedef NullTypeList HeadType;
297};
298
299
300template <class T>
301struct TypeAppender<NullTypeList, T>
302{
303 typedef TypeList<T, NullTypeList> HeadType;
304};
305
306
307template <class Head, class Tail>
308struct TypeAppender<NullTypeList, TypeList<Head, Tail> >
309{
310 typedef TypeList<Head, Tail> HeadType;
311};
312
313
314template <class Head, class Tail, class T>
315struct TypeAppender<TypeList<Head, Tail>, T>
316{
317 typedef TypeList<Head, typename TypeAppender<Tail, T>::HeadType> HeadType;
318};
319
320
321template <class Head, class T>
322struct 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
332template <class T>
333struct TypeOneEraser<NullTypeList, T>
334{
335 typedef NullTypeList HeadType;
336};
337
338
339template <class T, class Tail>
340struct TypeOneEraser<TypeList<T, Tail>, T>
341{
342 typedef Tail HeadType;
343};
344
345
346template <class Head, class Tail, class T>
347struct TypeOneEraser<TypeList<Head, Tail>, T>
348{
349 typedef TypeList <Head, typename TypeOneEraser<Tail, T>::HeadType> HeadType;
350};
351
352
353template <class Head, class T>
354struct 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
364template <class T>
365struct TypeAllEraser<NullTypeList, T>
366{
367 typedef NullTypeList HeadType;
368};
369
370
371template <class T, class Tail>
372struct TypeAllEraser<TypeList<T, Tail>, T>
373{
374 typedef typename TypeAllEraser<Tail, T>::HeadType HeadType;
375};
376
377
378template <class Head, class Tail, class T>
379struct TypeAllEraser<TypeList<Head, Tail>, T>
380{
381 typedef TypeList <Head, typename TypeAllEraser<Tail, T>::HeadType> HeadType;
382};
383
384
385template <class Head>
386struct 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
396template <>
397struct TypeDuplicateEraser<NullTypeList>
398{
399 typedef NullTypeList HeadType;
400};
401
402
403template <class Head, class Tail>
404struct TypeDuplicateEraser<TypeList<Head, Tail> >
405{
406private:
407 typedef typename TypeDuplicateEraser<Tail>::HeadType L1;
408 typedef typename TypeOneEraser<L1, Head>::HeadType L2;
409public:
410 typedef TypeList<Head, L2> HeadType;
411};
412
413
414template <class Head, class T, class R>
415struct 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
426template <class T, class R>
427struct TypeOneReplacer<NullTypeList, T, R>
428{
429 typedef NullTypeList HeadType;
430};
431
432
433template <class T, class Tail, class R>
434struct TypeOneReplacer<TypeList<T, Tail>, T, R>
435{
436 typedef TypeList<R, Tail> HeadType;
437};
438
439
440template <class Head, class Tail, class T, class R>
441struct TypeOneReplacer<TypeList<Head, Tail>, T, R>
442{
443 typedef TypeList<Head, typename TypeOneReplacer<Tail, T, R>::HeadType> HeadType;
444};
445
446
447template <class Head, class T, class R>
448struct 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
459template <class T, class R>
460struct TypeAllReplacer<NullTypeList, T, R>
461{
462 typedef NullTypeList HeadType;
463};
464
465
466template <class T, class Tail, class R>
467struct TypeAllReplacer<TypeList<T, Tail>, T, R>
468{
469 typedef TypeList<R, typename TypeAllReplacer<Tail, T, R>::HeadType> HeadType;
470};
471
472
473template <class Head, class Tail, class T, class R>
474struct 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