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
////////////////////////////////////////////////////////////////////////////////
16
// Last update: October 10, 2002
19
// $Header: /cvsroot/loki-lib/loki/include/loki/Typelist.h,v 1.5 2006/01/16 19:05:09 rich_sposato Exp $
21
#ifndef LOKI_TYPELIST_INC_
22
#define LOKI_TYPELIST_INC_
25
#include "TypeManip.h"
26
#include "TypelistMacros.h"
31
////////////////////////////////////////////////////////////////////////////////
32
// class template Typelist
33
// The building block of typelists of any length
34
// Use it through the LOKI_TYPELIST_NN macros
35
// Defines nested types:
36
// Head (first element, a non-typelist type by convention)
37
// Tail (second element, can be another typelist)
38
////////////////////////////////////////////////////////////////////////////////
40
template <class T, class U>
47
// Typelist utility algorithms
52
////////////////////////////////////////////////////////////////////////////////
53
// class template MakeTypelist
54
// Takes a number of arguments equal to its numeric suffix
55
// The arguments are type names.
56
// MakeTypelist<T1, T2, ...>::Result
57
// returns a typelist that is of T1, T2, ...
58
////////////////////////////////////////////////////////////////////////////////
62
typename T1 = NullType, typename T2 = NullType, typename T3 = NullType,
63
typename T4 = NullType, typename T5 = NullType, typename T6 = NullType,
64
typename T7 = NullType, typename T8 = NullType, typename T9 = NullType,
65
typename T10 = NullType, typename T11 = NullType, typename T12 = NullType,
66
typename T13 = NullType, typename T14 = NullType, typename T15 = NullType,
67
typename T16 = NullType, typename T17 = NullType, typename T18 = NullType
72
typedef typename MakeTypelist
84
typedef Typelist<T1, TailResult> Result;
90
typedef NullType Result;
93
////////////////////////////////////////////////////////////////////////////////
94
// class template Length
95
// Computes the length of a typelist
96
// Invocation (TList is a typelist):
97
// Length<TList>::value
98
// returns a compile-time constant containing the length of TList, not counting
99
// the end terminator (which by convention is NullType)
100
////////////////////////////////////////////////////////////////////////////////
102
template <class TList> struct Length;
103
template <> struct Length<NullType>
108
template <class T, class U>
109
struct Length< Typelist<T, U> >
111
enum { value = 1 + Length<U>::value };
114
////////////////////////////////////////////////////////////////////////////////
115
// class template TypeAt
116
// Finds the type at a given index in a typelist
117
// Invocation (TList is a typelist and index is a compile-time integral
119
// TypeAt<TList, index>::Result
120
// returns the type in position 'index' in TList
121
// If you pass an out-of-bounds index, the result is a compile-time error
122
////////////////////////////////////////////////////////////////////////////////
124
template <class TList, unsigned int index> struct TypeAt;
126
template <class Head, class Tail>
127
struct TypeAt<Typelist<Head, Tail>, 0>
132
template <class Head, class Tail, unsigned int i>
133
struct TypeAt<Typelist<Head, Tail>, i>
135
typedef typename TypeAt<Tail, i - 1>::Result Result;
138
////////////////////////////////////////////////////////////////////////////////
139
// class template TypeAtNonStrict
140
// Finds the type at a given index in a typelist
141
// Invocations (TList is a typelist and index is a compile-time integral
143
// a) TypeAt<TList, index>::Result
144
// returns the type in position 'index' in TList, or NullType if index is
146
// b) TypeAt<TList, index, D>::Result
147
// returns the type in position 'index' in TList, or D if index is out-of-bounds
148
////////////////////////////////////////////////////////////////////////////////
150
template <class TList, unsigned int index,
151
typename DefaultType = NullType>
152
struct TypeAtNonStrict
154
typedef DefaultType Result;
157
template <class Head, class Tail, typename DefaultType>
158
struct TypeAtNonStrict<Typelist<Head, Tail>, 0, DefaultType>
163
template <class Head, class Tail, unsigned int i, typename DefaultType>
164
struct TypeAtNonStrict<Typelist<Head, Tail>, i, DefaultType>
167
TypeAtNonStrict<Tail, i - 1, DefaultType>::Result Result;
170
////////////////////////////////////////////////////////////////////////////////
171
// class template IndexOf
172
// Finds the index of a type in a typelist
173
// Invocation (TList is a typelist and T is a type):
174
// IndexOf<TList, T>::value
175
// returns the position of T in TList, or NullType if T is not found in TList
176
////////////////////////////////////////////////////////////////////////////////
178
template <class TList, class T> struct IndexOf;
181
struct IndexOf<NullType, T>
186
template <class T, class Tail>
187
struct IndexOf<Typelist<T, Tail>, T>
192
template <class Head, class Tail, class T>
193
struct IndexOf<Typelist<Head, Tail>, T>
196
enum { temp = IndexOf<Tail, T>::value };
198
enum { value = (temp == -1 ? -1 : 1 + temp) };
201
////////////////////////////////////////////////////////////////////////////////
202
// class template Append
203
// Appends a type or a typelist to another
204
// Invocation (TList is a typelist and T is either a type or a typelist):
205
// Append<TList, T>::Result
206
// returns a typelist that is TList followed by T and NullType-terminated
207
////////////////////////////////////////////////////////////////////////////////
209
template <class TList, class T> struct Append;
211
template <> struct Append<NullType, NullType>
213
typedef NullType Result;
216
template <class T> struct Append<NullType, T>
218
typedef Typelist<T,NullType> Result;
221
template <class Head, class Tail>
222
struct Append<NullType, Typelist<Head, Tail> >
224
typedef Typelist<Head, Tail> Result;
227
template <class Head, class Tail, class T>
228
struct Append<Typelist<Head, Tail>, T>
230
typedef Typelist<Head,
231
typename Append<Tail, T>::Result>
235
////////////////////////////////////////////////////////////////////////////////
236
// class template Erase
237
// Erases the first occurence, if any, of a type in a typelist
238
// Invocation (TList is a typelist and T is a type):
239
// Erase<TList, T>::Result
240
// returns a typelist that is TList without the first occurence of T
241
////////////////////////////////////////////////////////////////////////////////
243
template <class TList, class T> struct Erase;
245
template <class T> // Specialization 1
246
struct Erase<NullType, T>
248
typedef NullType Result;
251
template <class T, class Tail> // Specialization 2
252
struct Erase<Typelist<T, Tail>, T>
257
template <class Head, class Tail, class T> // Specialization 3
258
struct Erase<Typelist<Head, Tail>, T>
260
typedef Typelist<Head,
261
typename Erase<Tail, T>::Result>
265
////////////////////////////////////////////////////////////////////////////////
266
// class template EraseAll
267
// Erases all first occurences, if any, of a type in a typelist
268
// Invocation (TList is a typelist and T is a type):
269
// EraseAll<TList, T>::Result
270
// returns a typelist that is TList without any occurence of T
271
////////////////////////////////////////////////////////////////////////////////
273
template <class TList, class T> struct EraseAll;
275
struct EraseAll<NullType, T>
277
typedef NullType Result;
279
template <class T, class Tail>
280
struct EraseAll<Typelist<T, Tail>, T>
282
// Go all the way down the list removing the type
283
typedef typename EraseAll<Tail, T>::Result Result;
285
template <class Head, class Tail, class T>
286
struct EraseAll<Typelist<Head, Tail>, T>
288
// Go all the way down the list removing the type
289
typedef Typelist<Head,
290
typename EraseAll<Tail, T>::Result>
294
////////////////////////////////////////////////////////////////////////////////
295
// class template NoDuplicates
296
// Removes all duplicate types in a typelist
297
// Invocation (TList is a typelist):
298
// NoDuplicates<TList, T>::Result
299
////////////////////////////////////////////////////////////////////////////////
301
template <class TList> struct NoDuplicates;
303
template <> struct NoDuplicates<NullType>
305
typedef NullType Result;
308
template <class Head, class Tail>
309
struct NoDuplicates< Typelist<Head, Tail> >
312
typedef typename NoDuplicates<Tail>::Result L1;
313
typedef typename Erase<L1, Head>::Result L2;
315
typedef Typelist<Head, L2> Result;
318
////////////////////////////////////////////////////////////////////////////////
319
// class template Replace
320
// Replaces the first occurence of a type in a typelist, with another type
321
// Invocation (TList is a typelist, T, U are types):
322
// Replace<TList, T, U>::Result
323
// returns a typelist in which the first occurence of T is replaced with U
324
////////////////////////////////////////////////////////////////////////////////
326
template <class TList, class T, class U> struct Replace;
328
template <class T, class U>
329
struct Replace<NullType, T, U>
331
typedef NullType Result;
334
template <class T, class Tail, class U>
335
struct Replace<Typelist<T, Tail>, T, U>
337
typedef Typelist<U, Tail> Result;
340
template <class Head, class Tail, class T, class U>
341
struct Replace<Typelist<Head, Tail>, T, U>
343
typedef Typelist<Head,
344
typename Replace<Tail, T, U>::Result>
348
////////////////////////////////////////////////////////////////////////////////
349
// class template ReplaceAll
350
// Replaces all occurences of a type in a typelist, with another type
351
// Invocation (TList is a typelist, T, U are types):
352
// Replace<TList, T, U>::Result
353
// returns a typelist in which all occurences of T is replaced with U
354
////////////////////////////////////////////////////////////////////////////////
356
template <class TList, class T, class U> struct ReplaceAll;
358
template <class T, class U>
359
struct ReplaceAll<NullType, T, U>
361
typedef NullType Result;
364
template <class T, class Tail, class U>
365
struct ReplaceAll<Typelist<T, Tail>, T, U>
367
typedef Typelist<U, typename ReplaceAll<Tail, T, U>::Result> Result;
370
template <class Head, class Tail, class T, class U>
371
struct ReplaceAll<Typelist<Head, Tail>, T, U>
373
typedef Typelist<Head,
374
typename ReplaceAll<Tail, T, U>::Result>
378
////////////////////////////////////////////////////////////////////////////////
379
// class template Reverse
380
// Reverses a typelist
381
// Invocation (TList is a typelist):
382
// Reverse<TList>::Result
383
// returns a typelist that is TList reversed
384
////////////////////////////////////////////////////////////////////////////////
386
template <class TList> struct Reverse;
389
struct Reverse<NullType>
391
typedef NullType Result;
394
template <class Head, class Tail>
395
struct Reverse< Typelist<Head, Tail> >
397
typedef typename Append<
398
typename Reverse<Tail>::Result, Head>::Result Result;
401
////////////////////////////////////////////////////////////////////////////////
402
// class template MostDerived
403
// Finds the type in a typelist that is the most derived from a given type
404
// Invocation (TList is a typelist, T is a type):
405
// MostDerived<TList, T>::Result
406
// returns the type in TList that's the most derived from T
407
////////////////////////////////////////////////////////////////////////////////
409
template <class TList, class T> struct MostDerived;
412
struct MostDerived<NullType, T>
417
template <class Head, class Tail, class T>
418
struct MostDerived<Typelist<Head, Tail>, T>
421
typedef typename MostDerived<Tail, T>::Result Candidate;
423
typedef typename Select<
424
SuperSubclass<Candidate,Head>::value,
425
Head, Candidate>::Result Result;
428
////////////////////////////////////////////////////////////////////////////////
429
// class template DerivedToFront
430
// Arranges the types in a typelist so that the most derived types appear first
431
// Invocation (TList is a typelist):
432
// DerivedToFront<TList>::Result
433
// returns the reordered TList
434
////////////////////////////////////////////////////////////////////////////////
436
template <class TList> struct DerivedToFront;
439
struct DerivedToFront<NullType>
441
typedef NullType Result;
444
template <class Head, class Tail>
445
struct DerivedToFront< Typelist<Head, Tail> >
448
typedef typename MostDerived<Tail, Head>::Result
450
typedef typename Replace<Tail,
451
TheMostDerived, Head>::Result Temp;
452
typedef typename DerivedToFront<Temp>::Result L;
454
typedef Typelist<TheMostDerived, L> Result;
460
////////////////////////////////////////////////////////////////////////////////
462
// June 09, 2001: Fix bug in parameter list of macros LOKI_TYPELIST_23 to LOKI_TYPELIST_27
463
// (credit due to Dave Taylor)
464
// June 20, 2001: ported by Nick Thurn to gcc 2.95.3. Kudos, Nick!!!
465
// November 22, 2001: fixed bug in DerivedToFront
466
// (credit due to Gianni Luciani who noticed the bug first;
468
// Friedrik Hedman who fixed the bug but didn't send the fix;
469
// Kevin Cline who sent the first actual fix)
470
// May 13, 2002: LOKI_TYPELIST_46 called LOKI_TYPELIST_45 with only 44 parameters.
471
// Credit due to Robert Minsk
472
// September 16, 2002: Changed MostDerived to use the new SuperSubclass template
473
// (rather than the SUPERSUBCLASS macro).
474
// Minor fix in Reverse, adding support for empty lists, like all the other
476
// Fixed DerivedToFront, to use Replace, rather than ReplaceAll. T.S.
477
// Oct 10, 2002: added MakeTypelist (SGB/MKH)
478
////////////////////////////////////////////////////////////////////////////////
480
#endif // LOKI_TYPELIST_INC_
482
// $Log: Typelist.h,v $
483
// Revision 1.5 2006/01/16 19:05:09 rich_sposato
484
// Added cvs keywords.