Typelist.h

00001 
00002 // The Loki Library
00003 // Copyright (c) 2001 by Andrei Alexandrescu
00004 // This code accompanies the book:
00005 // Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design 
00006 //     Patterns Applied". Copyright (c) 2001. Addison-Wesley.
00007 // Permission to use, copy, modify, distribute and sell this software for any 
00008 //     purpose is hereby granted without fee, provided that the above copyright 
00009 //     notice appear in all copies and that both that copyright notice and this 
00010 //     permission notice appear in supporting documentation.
00011 // The author or Addison-Welsey Longman make no representations about the 
00012 //     suitability of this software for any purpose. It is provided "as is" 
00013 //     without express or implied warranty.
00015 #ifndef LOKI_TYPELIST_INC_
00016 #define LOKI_TYPELIST_INC_
00017 
00018 // $Id: Typelist.h 749 2006-10-17 19:49:26Z syntheticpp $
00019 
00020 
00021 #include "NullType.h"
00022 #include "TypeManip.h"
00023 #include "TypelistMacros.h"
00024 
00025 
00026 namespace Loki
00027 {
00029 // class template Typelist
00030 // The building block of typelists of any length
00031 // Use it through the LOKI_TYPELIST_NN macros
00032 // Defines nested types:
00033 //     Head (first element, a non-typelist type by convention)
00034 //     Tail (second element, can be another typelist)
00036 
00037     template <class T, class U>
00038     struct Typelist
00039     {
00040        typedef T Head;
00041        typedef U Tail;
00042     };
00043 
00044 // Typelist utility algorithms
00045 
00046     namespace TL
00047     {
00048 
00050 // class template MakeTypelist
00051 // Takes a number of arguments equal to its numeric suffix
00052 // The arguments are type names.
00053 // MakeTypelist<T1, T2, ...>::Result
00054 // returns a typelist that is of T1, T2, ...
00056 
00057         template
00058         <
00059             typename T1  = NullType, typename T2  = NullType, typename T3  = NullType,
00060             typename T4  = NullType, typename T5  = NullType, typename T6  = NullType,
00061             typename T7  = NullType, typename T8  = NullType, typename T9  = NullType,
00062             typename T10 = NullType, typename T11 = NullType, typename T12 = NullType,
00063             typename T13 = NullType, typename T14 = NullType, typename T15 = NullType,
00064             typename T16 = NullType, typename T17 = NullType, typename T18 = NullType
00065         > 
00066         struct MakeTypelist
00067         {
00068         private:
00069             typedef typename MakeTypelist
00070             <
00071                 T2 , T3 , T4 , 
00072                 T5 , T6 , T7 , 
00073                 T8 , T9 , T10, 
00074                 T11, T12, T13,
00075                 T14, T15, T16, 
00076                 T17, T18
00077             >
00078             ::Result TailResult;
00079 
00080         public:
00081             typedef Typelist<T1, TailResult> Result;
00082         };
00083 
00084         template<>
00085         struct MakeTypelist<>
00086         {
00087             typedef NullType Result;
00088         };
00089 
00091 // class template Length
00092 // Computes the length of a typelist
00093 // Invocation (TList is a typelist):
00094 // Length<TList>::value
00095 // returns a compile-time constant containing the length of TList, not counting
00096 //     the end terminator (which by convention is NullType)
00098 
00099         template <class TList> struct Length;
00100         template <> struct Length<NullType>
00101         {
00102             enum { value = 0 };
00103         };
00104         
00105         template <class T, class U>
00106         struct Length< Typelist<T, U> >
00107         {
00108             enum { value = 1 + Length<U>::value };
00109         };
00110 
00112 // class template TypeAt
00113 // Finds the type at a given index in a typelist
00114 // Invocation (TList is a typelist and index is a compile-time integral 
00115 //     constant):
00116 // TypeAt<TList, index>::Result
00117 // returns the type in position 'index' in TList
00118 // If you pass an out-of-bounds index, the result is a compile-time error
00120 
00121         template <class TList, unsigned int index> struct TypeAt;
00122         
00123         template <class Head, class Tail>
00124         struct TypeAt<Typelist<Head, Tail>, 0>
00125         {
00126             typedef Head Result;
00127         };
00128 
00129         template <class Head, class Tail, unsigned int i>
00130         struct TypeAt<Typelist<Head, Tail>, i>
00131         {
00132             typedef typename TypeAt<Tail, i - 1>::Result Result;
00133         };
00134 
00136 // class template TypeAtNonStrict
00137 // Finds the type at a given index in a typelist
00138 // Invocations (TList is a typelist and index is a compile-time integral 
00139 //     constant):
00140 // a) TypeAt<TList, index>::Result
00141 // returns the type in position 'index' in TList, or NullType if index is 
00142 //     out-of-bounds
00143 // b) TypeAt<TList, index, D>::Result
00144 // returns the type in position 'index' in TList, or D if index is out-of-bounds
00146 
00147         template <class TList, unsigned int index,
00148             typename DefaultType = NullType>
00149         struct TypeAtNonStrict
00150         {
00151             typedef DefaultType Result;
00152         };
00153         
00154         template <class Head, class Tail, typename DefaultType>
00155         struct TypeAtNonStrict<Typelist<Head, Tail>, 0, DefaultType>
00156         {
00157             typedef Head Result;
00158         };
00159         
00160         template <class Head, class Tail, unsigned int i, typename DefaultType>
00161         struct TypeAtNonStrict<Typelist<Head, Tail>, i, DefaultType>
00162         {
00163             typedef typename 
00164                 TypeAtNonStrict<Tail, i - 1, DefaultType>::Result Result;
00165         };
00166 
00168 // class template IndexOf
00169 // Finds the index of a type in a typelist
00170 // Invocation (TList is a typelist and T is a type):
00171 // IndexOf<TList, T>::value
00172 // returns the position of T in TList, or NullType if T is not found in TList
00174 
00175         template <class TList, class T> struct IndexOf;
00176         
00177         template <class T>
00178         struct IndexOf<NullType, T>
00179         {
00180             enum { value = -1 };
00181         };
00182         
00183         template <class T, class Tail>
00184         struct IndexOf<Typelist<T, Tail>, T>
00185         {
00186             enum { value = 0 };
00187         };
00188         
00189         template <class Head, class Tail, class T>
00190         struct IndexOf<Typelist<Head, Tail>, T>
00191         {
00192         private:
00193             enum { temp = IndexOf<Tail, T>::value };
00194         public:
00195             enum { value = (temp == -1 ? -1 : 1 + temp) };
00196         };
00197 
00199 // class template Append
00200 // Appends a type or a typelist to another
00201 // Invocation (TList is a typelist and T is either a type or a typelist):
00202 // Append<TList, T>::Result
00203 // returns a typelist that is TList followed by T and NullType-terminated
00205 
00206         template <class TList, class T> struct Append;
00207         
00208         template <> struct Append<NullType, NullType>
00209         {
00210             typedef NullType Result;
00211         };
00212         
00213         template <class T> struct Append<NullType, T>
00214         {
00215             typedef Typelist<T,NullType> Result;
00216         };
00217 
00218         template <class Head, class Tail>
00219         struct Append<NullType, Typelist<Head, Tail> >
00220         {
00221             typedef Typelist<Head, Tail> Result;
00222         };
00223         
00224         template <class Head, class Tail, class T>
00225         struct Append<Typelist<Head, Tail>, T>
00226         {
00227             typedef Typelist<Head, 
00228                     typename Append<Tail, T>::Result>
00229                 Result;
00230         };
00231         
00233 // class template Erase
00234 // Erases the first occurence, if any, of a type in a typelist
00235 // Invocation (TList is a typelist and T is a type):
00236 // Erase<TList, T>::Result
00237 // returns a typelist that is TList without the first occurence of T
00239 
00240         template <class TList, class T> struct Erase;
00241         
00242         template <class T>                         // Specialization 1
00243         struct Erase<NullType, T>
00244         {
00245             typedef NullType Result;
00246         };
00247 
00248         template <class T, class Tail>             // Specialization 2
00249         struct Erase<Typelist<T, Tail>, T>
00250         {
00251             typedef Tail Result;
00252         };
00253 
00254         template <class Head, class Tail, class T> // Specialization 3
00255         struct Erase<Typelist<Head, Tail>, T>
00256         {
00257             typedef Typelist<Head, 
00258                     typename Erase<Tail, T>::Result>
00259                 Result;
00260         };
00261 
00263 // class template EraseAll
00264 // Erases all first occurences, if any, of a type in a typelist
00265 // Invocation (TList is a typelist and T is a type):
00266 // EraseAll<TList, T>::Result
00267 // returns a typelist that is TList without any occurence of T
00269 
00270         template <class TList, class T> struct EraseAll;
00271         template <class T>
00272         struct EraseAll<NullType, T>
00273         {
00274             typedef NullType Result;
00275         };
00276         template <class T, class Tail>
00277         struct EraseAll<Typelist<T, Tail>, T>
00278         {
00279             // Go all the way down the list removing the type
00280             typedef typename EraseAll<Tail, T>::Result Result;
00281         };
00282         template <class Head, class Tail, class T>
00283         struct EraseAll<Typelist<Head, Tail>, T>
00284         {
00285             // Go all the way down the list removing the type
00286             typedef Typelist<Head, 
00287                     typename EraseAll<Tail, T>::Result>
00288                 Result;
00289         };
00290 
00292 // class template NoDuplicates
00293 // Removes all duplicate types in a typelist
00294 // Invocation (TList is a typelist):
00295 // NoDuplicates<TList, T>::Result
00297 
00298         template <class TList> struct NoDuplicates;
00299         
00300         template <> struct NoDuplicates<NullType>
00301         {
00302             typedef NullType Result;
00303         };
00304 
00305         template <class Head, class Tail>
00306         struct NoDuplicates< Typelist<Head, Tail> >
00307         {
00308         private:
00309             typedef typename NoDuplicates<Tail>::Result L1;
00310             typedef typename Erase<L1, Head>::Result L2;
00311         public:
00312             typedef Typelist<Head, L2> Result;
00313         };
00314 
00316 // class template Replace
00317 // Replaces the first occurence of a type in a typelist, with another type
00318 // Invocation (TList is a typelist, T, U are types):
00319 // Replace<TList, T, U>::Result
00320 // returns a typelist in which the first occurence of T is replaced with U
00322 
00323         template <class TList, class T, class U> struct Replace;
00324         
00325         template <class T, class U>
00326         struct Replace<NullType, T, U>
00327         {
00328             typedef NullType Result;
00329         };
00330 
00331         template <class T, class Tail, class U>
00332         struct Replace<Typelist<T, Tail>, T, U>
00333         {
00334             typedef Typelist<U, Tail> Result;
00335         };
00336 
00337         template <class Head, class Tail, class T, class U>
00338         struct Replace<Typelist<Head, Tail>, T, U>
00339         {
00340             typedef Typelist<Head,
00341                     typename Replace<Tail, T, U>::Result>
00342                 Result;
00343         };
00344 
00346 // class template ReplaceAll
00347 // Replaces all occurences of a type in a typelist, with another type
00348 // Invocation (TList is a typelist, T, U are types):
00349 // Replace<TList, T, U>::Result
00350 // returns a typelist in which all occurences of T is replaced with U
00352 
00353         template <class TList, class T, class U> struct ReplaceAll;
00354         
00355         template <class T, class U>
00356         struct ReplaceAll<NullType, T, U>
00357         {
00358             typedef NullType Result;
00359         };
00360         
00361         template <class T, class Tail, class U>
00362         struct ReplaceAll<Typelist<T, Tail>, T, U>
00363         {
00364             typedef Typelist<U, typename ReplaceAll<Tail, T, U>::Result> Result;
00365         };
00366         
00367         template <class Head, class Tail, class T, class U>
00368         struct ReplaceAll<Typelist<Head, Tail>, T, U>
00369         {
00370             typedef Typelist<Head,
00371                     typename ReplaceAll<Tail, T, U>::Result>
00372                 Result;
00373         };
00374 
00376 // class template Reverse
00377 // Reverses a typelist
00378 // Invocation (TList is a typelist):
00379 // Reverse<TList>::Result
00380 // returns a typelist that is TList reversed
00382 
00383         template <class TList> struct Reverse;
00384         
00385         template <>
00386         struct Reverse<NullType>
00387         {
00388             typedef NullType Result;
00389         };
00390         
00391         template <class Head, class Tail>
00392         struct Reverse< Typelist<Head, Tail> >
00393         {
00394             typedef typename Append<
00395                 typename Reverse<Tail>::Result, Head>::Result Result;
00396         };
00397 
00399 // class template MostDerived
00400 // Finds the type in a typelist that is the most derived from a given type
00401 // Invocation (TList is a typelist, T is a type):
00402 // MostDerived<TList, T>::Result
00403 // returns the type in TList that's the most derived from T
00405 
00406         template <class TList, class T> struct MostDerived;
00407         
00408         template <class T>
00409         struct MostDerived<NullType, T>
00410         {
00411             typedef T Result;
00412         };
00413         
00414         template <class Head, class Tail, class T>
00415         struct MostDerived<Typelist<Head, Tail>, T>
00416         {
00417         private:
00418             typedef typename MostDerived<Tail, T>::Result Candidate;
00419         public:
00420             typedef typename Select<
00421                 SuperSubclass<Candidate,Head>::value,
00422                     Head, Candidate>::Result Result;
00423         };
00424 
00426 // class template DerivedToFront
00427 // Arranges the types in a typelist so that the most derived types appear first
00428 // Invocation (TList is a typelist):
00429 // DerivedToFront<TList>::Result
00430 // returns the reordered TList 
00432 
00433         template <class TList> struct DerivedToFront;
00434         
00435         template <>
00436         struct DerivedToFront<NullType>
00437         {
00438             typedef NullType Result;
00439         };
00440         
00441         template <class Head, class Tail>
00442         struct DerivedToFront< Typelist<Head, Tail> >
00443         {
00444         private:
00445             typedef typename MostDerived<Tail, Head>::Result
00446                 TheMostDerived;
00447             typedef typename Replace<Tail,
00448                 TheMostDerived, Head>::Result Temp;
00449             typedef typename DerivedToFront<Temp>::Result L;
00450         public:
00451             typedef Typelist<TheMostDerived, L> Result;
00452         };
00453         
00454     }   // namespace TL
00455 }   // namespace Loki
00456 
00457 
00458 #endif // end file guardian
00459 

Generated on Sun Feb 25 16:52:28 2007 for Loki by  doxygen 1.5.1-p1