]> git.cworth.org Git - vogl/blob - src/extlib/loki/include/loki/Typelist.h
Initial vogl checkin
[vogl] / src / extlib / loki / include / loki / Typelist.h
1 ////////////////////////////////////////////////////////////////////////////////
2 // The Loki Library
3 // Copyright (c) 2001 by Andrei Alexandrescu
4 // This code accompanies the book:
5 // Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design
6 //     Patterns Applied". Copyright (c) 2001. Addison-Wesley.
7 // Permission to use, copy, modify, distribute and sell this software for any
8 //     purpose is hereby granted without fee, provided that the above copyright
9 //     notice appear in all copies and that both that copyright notice and this
10 //     permission notice appear in supporting documentation.
11 // The author or Addison-Welsey Longman make no representations about the
12 //     suitability of this software for any purpose. It is provided "as is"
13 //     without express or implied warranty.
14 ////////////////////////////////////////////////////////////////////////////////
15 #ifndef LOKI_TYPELIST_INC_
16 #define LOKI_TYPELIST_INC_
17
18 // $Id: Typelist.h 749 2006-10-17 19:49:26Z syntheticpp $
19
20
21 #include "NullType.h"
22 #include "TypeManip.h"
23 #include "TypelistMacros.h"
24
25
26 namespace Loki
27 {
28 ////////////////////////////////////////////////////////////////////////////////
29 // class template Typelist
30 // The building block of typelists of any length
31 // Use it through the LOKI_TYPELIST_NN macros
32 // Defines nested types:
33 //     Head (first element, a non-typelist type by convention)
34 //     Tail (second element, can be another typelist)
35 ////////////////////////////////////////////////////////////////////////////////
36
37 template <class T, class U>
38 struct Typelist
39 {
40         typedef T Head;
41         typedef U Tail;
42 };
43
44 // Typelist utility algorithms
45
46 namespace TL
47 {
48
49 ////////////////////////////////////////////////////////////////////////////////
50 // class template MakeTypelist
51 // Takes a number of arguments equal to its numeric suffix
52 // The arguments are type names.
53 // MakeTypelist<T1, T2, ...>::Result
54 // returns a typelist that is of T1, T2, ...
55 ////////////////////////////////////////////////////////////////////////////////
56
57 template
58 <
59 typename T1  = NullType, typename T2  = NullType, typename T3  = NullType,
60          typename T4  = NullType, typename T5  = NullType, typename T6  = NullType,
61          typename T7  = NullType, typename T8  = NullType, typename T9  = NullType,
62          typename T10 = NullType, typename T11 = NullType, typename T12 = NullType,
63          typename T13 = NullType, typename T14 = NullType, typename T15 = NullType,
64          typename T16 = NullType, typename T17 = NullType, typename T18 = NullType
65          >
66 struct MakeTypelist
67 {
68 private:
69         typedef typename MakeTypelist
70         <
71         T2 , T3 , T4 ,
72            T5 , T6 , T7 ,
73            T8 , T9 , T10,
74            T11, T12, T13,
75            T14, T15, T16,
76            T17, T18
77            >
78            ::Result TailResult;
79
80 public:
81         typedef Typelist<T1, TailResult> Result;
82 };
83
84 template<>
85 struct MakeTypelist<>
86 {
87         typedef NullType Result;
88 };
89
90 ////////////////////////////////////////////////////////////////////////////////
91 // class template Length
92 // Computes the length of a typelist
93 // Invocation (TList is a typelist):
94 // Length<TList>::value
95 // returns a compile-time constant containing the length of TList, not counting
96 //     the end terminator (which by convention is NullType)
97 ////////////////////////////////////////////////////////////////////////////////
98
99 template <class TList> struct Length;
100 template <> struct Length<NullType>
101 {
102         enum { value = 0 };
103 };
104
105 template <class T, class U>
106 struct Length< Typelist<T, U> >
107 {
108         enum { value = 1 + Length<U>::value };
109 };
110
111 ////////////////////////////////////////////////////////////////////////////////
112 // class template TypeAt
113 // Finds the type at a given index in a typelist
114 // Invocation (TList is a typelist and index is a compile-time integral
115 //     constant):
116 // TypeAt<TList, index>::Result
117 // returns the type in position 'index' in TList
118 // If you pass an out-of-bounds index, the result is a compile-time error
119 ////////////////////////////////////////////////////////////////////////////////
120
121 template <class TList, unsigned int index> struct TypeAt;
122
123 template <class Head, class Tail>
124 struct TypeAt<Typelist<Head, Tail>, 0>
125 {
126         typedef Head Result;
127 };
128
129 template <class Head, class Tail, unsigned int i>
130 struct TypeAt<Typelist<Head, Tail>, i>
131 {
132         typedef typename TypeAt<Tail, i - 1>::Result Result;
133 };
134
135 ////////////////////////////////////////////////////////////////////////////////
136 // class template TypeAtNonStrict
137 // Finds the type at a given index in a typelist
138 // Invocations (TList is a typelist and index is a compile-time integral
139 //     constant):
140 // a) TypeAt<TList, index>::Result
141 // returns the type in position 'index' in TList, or NullType if index is
142 //     out-of-bounds
143 // b) TypeAt<TList, index, D>::Result
144 // returns the type in position 'index' in TList, or D if index is out-of-bounds
145 ////////////////////////////////////////////////////////////////////////////////
146
147 template <class TList, unsigned int index,
148          typename DefaultType = NullType>
149 struct TypeAtNonStrict
150 {
151         typedef DefaultType Result;
152 };
153
154 template <class Head, class Tail, typename DefaultType>
155 struct TypeAtNonStrict<Typelist<Head, Tail>, 0, DefaultType>
156 {
157         typedef Head Result;
158 };
159
160 template <class Head, class Tail, unsigned int i, typename DefaultType>
161 struct TypeAtNonStrict<Typelist<Head, Tail>, i, DefaultType>
162 {
163         typedef typename
164         TypeAtNonStrict<Tail, i - 1, DefaultType>::Result Result;
165 };
166
167 ////////////////////////////////////////////////////////////////////////////////
168 // class template IndexOf
169 // Finds the index of a type in a typelist
170 // Invocation (TList is a typelist and T is a type):
171 // IndexOf<TList, T>::value
172 // returns the position of T in TList, or NullType if T is not found in TList
173 ////////////////////////////////////////////////////////////////////////////////
174
175 template <class TList, class T> struct IndexOf;
176
177 template <class T>
178 struct IndexOf<NullType, T>
179 {
180         enum { value = -1 };
181 };
182
183 template <class T, class Tail>
184 struct IndexOf<Typelist<T, Tail>, T>
185 {
186         enum { value = 0 };
187 };
188
189 template <class Head, class Tail, class T>
190 struct IndexOf<Typelist<Head, Tail>, T>
191 {
192 private:
193         enum { temp = IndexOf<Tail, T>::value };
194 public:
195         enum { value = (temp == -1 ? -1 : 1 + temp) };
196 };
197
198 ////////////////////////////////////////////////////////////////////////////////
199 // class template Append
200 // Appends a type or a typelist to another
201 // Invocation (TList is a typelist and T is either a type or a typelist):
202 // Append<TList, T>::Result
203 // returns a typelist that is TList followed by T and NullType-terminated
204 ////////////////////////////////////////////////////////////////////////////////
205
206 template <class TList, class T> struct Append;
207
208 template <> struct Append<NullType, NullType>
209 {
210         typedef NullType Result;
211 };
212
213 template <class T> struct Append<NullType, T>
214 {
215         typedef Typelist<T,NullType> Result;
216 };
217
218 template <class Head, class Tail>
219 struct Append<NullType, Typelist<Head, Tail> >
220 {
221         typedef Typelist<Head, Tail> Result;
222 };
223
224 template <class Head, class Tail, class T>
225 struct Append<Typelist<Head, Tail>, T>
226 {
227         typedef Typelist<Head,
228                 typename Append<Tail, T>::Result>
229                 Result;
230 };
231
232 ////////////////////////////////////////////////////////////////////////////////
233 // class template Erase
234 // Erases the first occurence, if any, of a type in a typelist
235 // Invocation (TList is a typelist and T is a type):
236 // Erase<TList, T>::Result
237 // returns a typelist that is TList without the first occurence of T
238 ////////////////////////////////////////////////////////////////////////////////
239
240 template <class TList, class T> struct Erase;
241
242 template <class T>                         // Specialization 1
243 struct Erase<NullType, T>
244 {
245         typedef NullType Result;
246 };
247
248 template <class T, class Tail>             // Specialization 2
249 struct Erase<Typelist<T, Tail>, T>
250 {
251         typedef Tail Result;
252 };
253
254 template <class Head, class Tail, class T> // Specialization 3
255 struct Erase<Typelist<Head, Tail>, T>
256 {
257         typedef Typelist<Head,
258                 typename Erase<Tail, T>::Result>
259                 Result;
260 };
261
262 ////////////////////////////////////////////////////////////////////////////////
263 // class template EraseAll
264 // Erases all first occurences, if any, of a type in a typelist
265 // Invocation (TList is a typelist and T is a type):
266 // EraseAll<TList, T>::Result
267 // returns a typelist that is TList without any occurence of T
268 ////////////////////////////////////////////////////////////////////////////////
269
270 template <class TList, class T> struct EraseAll;
271 template <class T>
272 struct EraseAll<NullType, T>
273 {
274         typedef NullType Result;
275 };
276 template <class T, class Tail>
277 struct EraseAll<Typelist<T, Tail>, T>
278 {
279         // Go all the way down the list removing the type
280         typedef typename EraseAll<Tail, T>::Result Result;
281 };
282 template <class Head, class Tail, class T>
283 struct EraseAll<Typelist<Head, Tail>, T>
284 {
285         // Go all the way down the list removing the type
286         typedef Typelist<Head,
287                 typename EraseAll<Tail, T>::Result>
288                 Result;
289 };
290
291 ////////////////////////////////////////////////////////////////////////////////
292 // class template NoDuplicates
293 // Removes all duplicate types in a typelist
294 // Invocation (TList is a typelist):
295 // NoDuplicates<TList, T>::Result
296 ////////////////////////////////////////////////////////////////////////////////
297
298 template <class TList> struct NoDuplicates;
299
300 template <> struct NoDuplicates<NullType>
301 {
302         typedef NullType Result;
303 };
304
305 template <class Head, class Tail>
306 struct NoDuplicates< Typelist<Head, Tail> >
307 {
308 private:
309         typedef typename NoDuplicates<Tail>::Result L1;
310         typedef typename Erase<L1, Head>::Result L2;
311 public:
312         typedef Typelist<Head, L2> Result;
313 };
314
315 ////////////////////////////////////////////////////////////////////////////////
316 // class template Replace
317 // Replaces the first occurence of a type in a typelist, with another type
318 // Invocation (TList is a typelist, T, U are types):
319 // Replace<TList, T, U>::Result
320 // returns a typelist in which the first occurence of T is replaced with U
321 ////////////////////////////////////////////////////////////////////////////////
322
323 template <class TList, class T, class U> struct Replace;
324
325 template <class T, class U>
326 struct Replace<NullType, T, U>
327 {
328         typedef NullType Result;
329 };
330
331 template <class T, class Tail, class U>
332 struct Replace<Typelist<T, Tail>, T, U>
333 {
334         typedef Typelist<U, Tail> Result;
335 };
336
337 template <class Head, class Tail, class T, class U>
338 struct Replace<Typelist<Head, Tail>, T, U>
339 {
340         typedef Typelist<Head,
341                 typename Replace<Tail, T, U>::Result>
342                 Result;
343 };
344
345 ////////////////////////////////////////////////////////////////////////////////
346 // class template ReplaceAll
347 // Replaces all occurences of a type in a typelist, with another type
348 // Invocation (TList is a typelist, T, U are types):
349 // Replace<TList, T, U>::Result
350 // returns a typelist in which all occurences of T is replaced with U
351 ////////////////////////////////////////////////////////////////////////////////
352
353 template <class TList, class T, class U> struct ReplaceAll;
354
355 template <class T, class U>
356 struct ReplaceAll<NullType, T, U>
357 {
358         typedef NullType Result;
359 };
360
361 template <class T, class Tail, class U>
362 struct ReplaceAll<Typelist<T, Tail>, T, U>
363 {
364         typedef Typelist<U, typename ReplaceAll<Tail, T, U>::Result> Result;
365 };
366
367 template <class Head, class Tail, class T, class U>
368 struct ReplaceAll<Typelist<Head, Tail>, T, U>
369 {
370         typedef Typelist<Head,
371                 typename ReplaceAll<Tail, T, U>::Result>
372                 Result;
373 };
374
375 ////////////////////////////////////////////////////////////////////////////////
376 // class template Reverse
377 // Reverses a typelist
378 // Invocation (TList is a typelist):
379 // Reverse<TList>::Result
380 // returns a typelist that is TList reversed
381 ////////////////////////////////////////////////////////////////////////////////
382
383 template <class TList> struct Reverse;
384
385 template <>
386 struct Reverse<NullType>
387 {
388         typedef NullType Result;
389 };
390
391 template <class Head, class Tail>
392 struct Reverse< Typelist<Head, Tail> >
393 {
394         typedef typename Append<
395         typename Reverse<Tail>::Result, Head>::Result Result;
396 };
397
398 ////////////////////////////////////////////////////////////////////////////////
399 // class template MostDerived
400 // Finds the type in a typelist that is the most derived from a given type
401 // Invocation (TList is a typelist, T is a type):
402 // MostDerived<TList, T>::Result
403 // returns the type in TList that's the most derived from T
404 ////////////////////////////////////////////////////////////////////////////////
405
406 template <class TList, class T> struct MostDerived;
407
408 template <class T>
409 struct MostDerived<NullType, T>
410 {
411         typedef T Result;
412 };
413
414 template <class Head, class Tail, class T>
415 struct MostDerived<Typelist<Head, Tail>, T>
416 {
417 private:
418         typedef typename MostDerived<Tail, T>::Result Candidate;
419 public:
420         typedef typename Select<
421         SuperSubclass<Candidate,Head>::value,
422                       Head, Candidate>::Result Result;
423 };
424
425 ////////////////////////////////////////////////////////////////////////////////
426 // class template DerivedToFront
427 // Arranges the types in a typelist so that the most derived types appear first
428 // Invocation (TList is a typelist):
429 // DerivedToFront<TList>::Result
430 // returns the reordered TList
431 ////////////////////////////////////////////////////////////////////////////////
432
433 template <class TList> struct DerivedToFront;
434
435 template <>
436 struct DerivedToFront<NullType>
437 {
438         typedef NullType Result;
439 };
440
441 template <class Head, class Tail>
442 struct DerivedToFront< Typelist<Head, Tail> >
443 {
444 private:
445         typedef typename MostDerived<Tail, Head>::Result
446         TheMostDerived;
447         typedef typename Replace<Tail,
448                 TheMostDerived, Head>::Result Temp;
449         typedef typename DerivedToFront<Temp>::Result L;
450 public:
451         typedef Typelist<TheMostDerived, L> Result;
452 };
453
454 }   // namespace TL
455 }   // namespace Loki
456
457
458 #endif // end file guardian
459