Fixed FerrisLoki permisions.
[fic.git] / FerrisLoki / Typelist.h
blob33625e610e485c8e16764366752783c01327a642
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_
18 // $Id: Typelist.h,v 1.1 2007/12/10 11:58:52 ben Exp $
21 #include "NullType.h"
22 #include "TypeManip.h"
23 #include "TypelistMacros.h"
26 namespace Loki
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 ////////////////////////////////////////////////////////////////////////////////
37 template <class T, class U>
38 struct Typelist
40 typedef T Head;
41 typedef U Tail;
44 // Typelist utility algorithms
46 namespace TL
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 ////////////////////////////////////////////////////////////////////////////////
57 template
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
66 struct MakeTypelist
68 private:
69 typedef typename MakeTypelist
71 T2 , T3 , T4 ,
72 T5 , T6 , T7 ,
73 T8 , T9 , T10,
74 T11, T12, T13,
75 T14, T15, T16,
76 T17, T18
78 ::Result TailResult;
80 public:
81 typedef Typelist<T1, TailResult> Result;
84 template<>
85 struct MakeTypelist<>
87 typedef NullType Result;
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 ////////////////////////////////////////////////////////////////////////////////
99 template <class TList> struct Length;
100 template <> struct Length<NullType>
102 enum { value = 0 };
105 template <class T, class U>
106 struct Length< Typelist<T, U> >
108 enum { value = 1 + Length<U>::value };
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 ////////////////////////////////////////////////////////////////////////////////
121 template <class TList, unsigned int index> struct TypeAt;
123 template <class Head, class Tail>
124 struct TypeAt<Typelist<Head, Tail>, 0>
126 typedef Head Result;
129 template <class Head, class Tail, unsigned int i>
130 struct TypeAt<Typelist<Head, Tail>, i>
132 typedef typename TypeAt<Tail, i - 1>::Result Result;
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 ////////////////////////////////////////////////////////////////////////////////
147 template <class TList, unsigned int index,
148 typename DefaultType = NullType>
149 struct TypeAtNonStrict
151 typedef DefaultType Result;
154 template <class Head, class Tail, typename DefaultType>
155 struct TypeAtNonStrict<Typelist<Head, Tail>, 0, DefaultType>
157 typedef Head Result;
160 template <class Head, class Tail, unsigned int i, typename DefaultType>
161 struct TypeAtNonStrict<Typelist<Head, Tail>, i, DefaultType>
163 typedef typename
164 TypeAtNonStrict<Tail, i - 1, DefaultType>::Result Result;
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 ////////////////////////////////////////////////////////////////////////////////
175 template <class TList, class T> struct IndexOf;
177 template <class T>
178 struct IndexOf<NullType, T>
180 enum { value = -1 };
183 template <class T, class Tail>
184 struct IndexOf<Typelist<T, Tail>, T>
186 enum { value = 0 };
189 template <class Head, class Tail, class T>
190 struct IndexOf<Typelist<Head, Tail>, T>
192 private:
193 enum { temp = IndexOf<Tail, T>::value };
194 public:
195 enum { value = (temp == -1 ? -1 : 1 + temp) };
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 ////////////////////////////////////////////////////////////////////////////////
206 template <class TList, class T> struct Append;
208 template <> struct Append<NullType, NullType>
210 typedef NullType Result;
213 template <class T> struct Append<NullType, T>
215 typedef Typelist<T,NullType> Result;
218 template <class Head, class Tail>
219 struct Append<NullType, Typelist<Head, Tail> >
221 typedef Typelist<Head, Tail> Result;
224 template <class Head, class Tail, class T>
225 struct Append<Typelist<Head, Tail>, T>
227 typedef Typelist<Head,
228 typename Append<Tail, T>::Result>
229 Result;
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 ////////////////////////////////////////////////////////////////////////////////
240 template <class TList, class T> struct Erase;
242 template <class T> // Specialization 1
243 struct Erase<NullType, T>
245 typedef NullType Result;
248 template <class T, class Tail> // Specialization 2
249 struct Erase<Typelist<T, Tail>, T>
251 typedef Tail Result;
254 template <class Head, class Tail, class T> // Specialization 3
255 struct Erase<Typelist<Head, Tail>, T>
257 typedef Typelist<Head,
258 typename Erase<Tail, T>::Result>
259 Result;
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 ////////////////////////////////////////////////////////////////////////////////
270 template <class TList, class T> struct EraseAll;
271 template <class T>
272 struct EraseAll<NullType, T>
274 typedef NullType Result;
276 template <class T, class Tail>
277 struct EraseAll<Typelist<T, Tail>, T>
279 // Go all the way down the list removing the type
280 typedef typename EraseAll<Tail, T>::Result Result;
282 template <class Head, class Tail, class T>
283 struct EraseAll<Typelist<Head, Tail>, T>
285 // Go all the way down the list removing the type
286 typedef Typelist<Head,
287 typename EraseAll<Tail, T>::Result>
288 Result;
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 ////////////////////////////////////////////////////////////////////////////////
298 template <class TList> struct NoDuplicates;
300 template <> struct NoDuplicates<NullType>
302 typedef NullType Result;
305 template <class Head, class Tail>
306 struct NoDuplicates< Typelist<Head, Tail> >
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;
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 ////////////////////////////////////////////////////////////////////////////////
323 template <class TList, class T, class U> struct Replace;
325 template <class T, class U>
326 struct Replace<NullType, T, U>
328 typedef NullType Result;
331 template <class T, class Tail, class U>
332 struct Replace<Typelist<T, Tail>, T, U>
334 typedef Typelist<U, Tail> Result;
337 template <class Head, class Tail, class T, class U>
338 struct Replace<Typelist<Head, Tail>, T, U>
340 typedef Typelist<Head,
341 typename Replace<Tail, T, U>::Result>
342 Result;
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 ////////////////////////////////////////////////////////////////////////////////
353 template <class TList, class T, class U> struct ReplaceAll;
355 template <class T, class U>
356 struct ReplaceAll<NullType, T, U>
358 typedef NullType Result;
361 template <class T, class Tail, class U>
362 struct ReplaceAll<Typelist<T, Tail>, T, U>
364 typedef Typelist<U, typename ReplaceAll<Tail, T, U>::Result> Result;
367 template <class Head, class Tail, class T, class U>
368 struct ReplaceAll<Typelist<Head, Tail>, T, U>
370 typedef Typelist<Head,
371 typename ReplaceAll<Tail, T, U>::Result>
372 Result;
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 ////////////////////////////////////////////////////////////////////////////////
383 template <class TList> struct Reverse;
385 template <>
386 struct Reverse<NullType>
388 typedef NullType Result;
391 template <class Head, class Tail>
392 struct Reverse< Typelist<Head, Tail> >
394 typedef typename Append<
395 typename Reverse<Tail>::Result, Head>::Result Result;
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 ////////////////////////////////////////////////////////////////////////////////
406 template <class TList, class T> struct MostDerived;
408 template <class T>
409 struct MostDerived<NullType, T>
411 typedef T Result;
414 template <class Head, class Tail, class T>
415 struct MostDerived<Typelist<Head, Tail>, T>
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;
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 ////////////////////////////////////////////////////////////////////////////////
433 template <class TList> struct DerivedToFront;
435 template <>
436 struct DerivedToFront<NullType>
438 typedef NullType Result;
441 template <class Head, class Tail>
442 struct DerivedToFront< Typelist<Head, Tail> >
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;
454 } // namespace TL
455 } // namespace Loki
458 #endif // end file guardian