1 ////////////////////////////////////////////////////////////////////////////////
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 749 2006-10-17 19:49:26Z syntheticpp $
22 #include "TypeManip.h"
23 #include "TypelistMacros.h"
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>
44 // Typelist utility algorithms
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 ////////////////////////////////////////////////////////////////////////////////
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
69 typedef typename MakeTypelist
81 typedef Typelist<T1, TailResult> Result;
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>
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
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>
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
140 // a) TypeAt<TList, index>::Result
141 // returns the type in position 'index' in TList, or NullType if index is
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>
160 template <class Head, class Tail, unsigned int i, typename DefaultType>
161 struct TypeAtNonStrict<Typelist<Head, Tail>, i, DefaultType>
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;
178 struct IndexOf<NullType, T>
183 template <class T, class Tail>
184 struct IndexOf<Typelist<T, Tail>, T>
189 template <class Head, class Tail, class T>
190 struct IndexOf<Typelist<Head, Tail>, T>
193 enum { temp = IndexOf<Tail, T>::value };
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>
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>
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>
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;
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>
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> >
309 typedef typename NoDuplicates<Tail>::Result L1;
310 typedef typename Erase<L1, Head>::Result L2;
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>
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>
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;
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;
409 struct MostDerived<NullType, T>
414 template <class Head, class Tail, class T>
415 struct MostDerived<Typelist<Head, Tail>, T>
418 typedef typename MostDerived<Tail, T>::Result Candidate;
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;
436 struct DerivedToFront<NullType>
438 typedef NullType Result;
441 template <class Head, class Tail>
442 struct DerivedToFront< Typelist<Head, Tail> >
445 typedef typename MostDerived<Tail, Head>::Result
447 typedef typename Replace<Tail,
448 TheMostDerived, Head>::Result Temp;
449 typedef typename DerivedToFront<Temp>::Result L;
451 typedef Typelist<TheMostDerived, L> Result;
458 #endif // end file guardian