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,v 1.1 2007/12/10 11:58:52 ben Exp $
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