www.pudn.com > Loki.rar > Typelist.h


//////////////////////////////////////////////////////////////////////////////// 
// The Loki Library 
// Copyright (c) 2001 by Andrei Alexandrescu 
// This code accompanies the book: 
// Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design  
//     Patterns Applied". Copyright (c) 2001. Addison-Wesley. 
// Permission to use, copy, modify, distribute and sell this software for any  
//     purpose is hereby granted without fee, provided that the above copyright  
//     notice appear in all copies and that both that copyright notice and this  
//     permission notice appear in supporting documentation. 
// The author or Addison-Welsey Longman make no representations about the  
//     suitability of this software for any purpose. It is provided "as is"  
//     without express or implied warranty. 
//////////////////////////////////////////////////////////////////////////////// 
 
// Last update: May 19, 2002 
 
#ifndef TYPELIST_INC_ 
#define TYPELIST_INC_ 
 
#include "static_check.h" 
#include "Nulltype.h" 
#include "TypeManip.h" 
 
//////////////////////////////////////////////////////////////////////////////// 
// macros TYPELIST_1, TYPELIST_2, ... TYPELIST_50 
// Each takes a number of arguments equal to its numeric suffix 
// The arguments are type names. TYPELIST_NN generates a typelist containing  
//     all types passed as arguments, in that order. 
// Example: TYPELIST_2(char, int) generates a type containing char and int. 
//////////////////////////////////////////////////////////////////////////////// 
 
#define TYPELIST_1(T1) ::Loki::Typelist 
 
#define TYPELIST_2(T1, T2) ::Loki::Typelist 
 
#define TYPELIST_3(T1, T2, T3) ::Loki::Typelist 
 
#define TYPELIST_4(T1, T2, T3, T4) \ 
    ::Loki::Typelist 
 
#define TYPELIST_5(T1, T2, T3, T4, T5) \ 
    ::Loki::Typelist 
 
#define TYPELIST_6(T1, T2, T3, T4, T5, T6) \ 
    ::Loki::Typelist 
 
#define TYPELIST_7(T1, T2, T3, T4, T5, T6, T7) \ 
    ::Loki::Typelist 
 
#define TYPELIST_8(T1, T2, T3, T4, T5, T6, T7, T8) \ 
    ::Loki::Typelist 
 
#define TYPELIST_9(T1, T2, T3, T4, T5, T6, T7, T8, T9) \ 
    ::Loki::Typelist 
 
#define TYPELIST_10(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10) \ 
    ::Loki::Typelist 
 
#define TYPELIST_11(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11) \ 
    ::Loki::Typelist 
 
#define TYPELIST_12(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12) \ 
    ::Loki::Typelist 
 
#define TYPELIST_13(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13) \ 
    ::Loki::Typelist 
 
#define TYPELIST_14(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \ 
        T11, T12, T13, T14) \ 
    ::Loki::Typelist 
 
#define TYPELIST_15(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \ 
        T11, T12, T13, T14, T15) \ 
    ::Loki::Typelist 
 
#define TYPELIST_16(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \ 
        T11, T12, T13, T14, T15, T16) \ 
    ::Loki::Typelist 
 
#define TYPELIST_17(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \ 
        T11, T12, T13, T14, T15, T16, T17) \ 
    ::Loki::Typelist 
 
#define TYPELIST_18(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \ 
        T11, T12, T13, T14, T15, T16, T17, T18) \ 
    ::Loki::Typelist 
 
#define TYPELIST_19(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \ 
        T11, T12, T13, T14, T15, T16, T17, T18, T19) \ 
    ::Loki::Typelist 
 
#define TYPELIST_20(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \ 
        T11, T12, T13, T14, T15, T16, T17, T18, T19, T20) \ 
    ::Loki::Typelist 
 
#define TYPELIST_21(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \ 
        T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, T21) \ 
    ::Loki::Typelist 
 
#define TYPELIST_22(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \ 
        T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22) \ 
    ::Loki::Typelist 
 
#define TYPELIST_23(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \ 
        T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23) \ 
    ::Loki::Typelist 
 
#define TYPELIST_24(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \ 
        T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24) \ 
    ::Loki::Typelist 
 
#define TYPELIST_25(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \ 
        T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25) \ 
    ::Loki::Typelist 
 
#define TYPELIST_26(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \ 
        T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \ 
        T21, T22, T23, T24, T25, T26) \ 
    ::Loki::Typelist 
 
#define TYPELIST_27(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \ 
        T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \ 
        T21, T22, T23, T24, T25, T26, T27) \ 
    ::Loki::Typelist 
 
#define TYPELIST_28(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \ 
        T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \ 
        T21, T22, T23, T24, T25, T26, T27, T28) \ 
    ::Loki::Typelist 
 
#define TYPELIST_29(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \ 
        T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \ 
        T21, T22, T23, T24, T25, T26, T27, T28, T29) \ 
    ::Loki::Typelist 
 
#define TYPELIST_30(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \ 
        T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \ 
        T21, T22, T23, T24, T25, T26, T27, T28, T29, T30) \ 
    ::Loki::Typelist 
 
#define TYPELIST_31(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \ 
        T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \ 
        T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, T31) \ 
    ::Loki::Typelist 
 
#define TYPELIST_32(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \ 
        T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \ 
        T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, T31, T32) \ 
    ::Loki::Typelist 
 
#define TYPELIST_33(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \ 
        T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \ 
        T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, T31, T32, T33) \ 
    ::Loki::Typelist 
 
#define TYPELIST_34(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \ 
        T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \ 
        T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, T31, T32, T33, T34) \ 
    ::Loki::Typelist 
 
#define TYPELIST_35(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \ 
        T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \ 
        T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, \ 
        T31, T32, T33, T34, T35) \ 
    ::Loki::Typelist 
 
#define TYPELIST_36(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \ 
        T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \ 
        T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, \ 
        T31, T32, T33, T34, T35, T36) \ 
    ::Loki::Typelist 
 
#define TYPELIST_37(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \ 
        T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \ 
        T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, \ 
        T31, T32, T33, T34, T35, T36, T37) \ 
    ::Loki::Typelist 
 
#define TYPELIST_38(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \ 
        T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \ 
        T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, \ 
        T31, T32, T33, T34, T35, T36, T37, T38) \ 
    ::Loki::Typelist 
 
#define TYPELIST_39(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \ 
        T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \ 
        T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, \ 
        T31, T32, T33, T34, T35, T36, T37, T38, T39) \ 
    ::Loki::Typelist 
 
#define TYPELIST_40(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \ 
        T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \ 
        T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, \ 
        T31, T32, T33, T34, T35, T36, T37, T38, T39, T40) \ 
    ::Loki::Typelist 
 
#define TYPELIST_41(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \ 
        T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \ 
        T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, \ 
        T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41) \ 
    ::Loki::Typelist 
 
#define TYPELIST_42(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \ 
        T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \ 
        T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, \ 
        T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42) \ 
    ::Loki::Typelist 
 
#define TYPELIST_43(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \ 
        T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \ 
        T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, \ 
        T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43) \ 
    ::Loki::Typelist 
 
#define TYPELIST_44(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \ 
        T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \ 
        T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, \ 
        T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, T41, T42, T43, T44) \ 
    ::Loki::Typelist 
 
#define TYPELIST_45(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \ 
        T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \ 
        T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, \ 
        T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, \ 
        T41, T42, T43, T44, T45) \ 
    ::Loki::Typelist 
 
#define TYPELIST_46(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \ 
        T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \ 
        T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, \ 
        T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, \ 
        T41, T42, T43, T44, T45, T46) \ 
    ::Loki::Typelist 
 
#define TYPELIST_47(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \ 
        T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \ 
        T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, \ 
        T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, \ 
        T41, T42, T43, T44, T45, T46, T47) \ 
    ::Loki::Typelist 
 
#define TYPELIST_48(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \ 
        T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \ 
        T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, \ 
        T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, \ 
        T41, T42, T43, T44, T45, T46, T47, T48) \ 
    ::Loki::Typelist 
 
#define TYPELIST_49(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \ 
        T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \ 
        T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, \ 
        T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, \ 
        T41, T42, T43, T44, T45, T46, T47, T48, T49) \ 
    ::Loki::Typelist 
 
#define TYPELIST_50(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, \ 
        T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, \ 
        T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, \ 
        T31, T32, T33, T34, T35, T36, T37, T38, T39, T40, \ 
        T41, T42, T43, T44, T45, T46, T47, T48, T49, T50) \ 
    ::Loki::Typelist 
 
namespace Loki 
{ 
//////////////////////////////////////////////////////////////////////////////// 
// class template Typelist 
// The building block of typelists of any length 
// Use it through the TYPELIST_NN macros 
// Defines nested types: 
//     Head (first element, a non-typelist type by convention) 
//     Tail (second element, can be another typelist) 
//////////////////////////////////////////////////////////////////////////////// 
 
    template  
    struct Typelist 
    { 
       typedef T Head; 
       typedef U Tail; 
    }; 
 
    namespace TL 
    { 
 
//////////////////////////////////////////////////////////////////////////////// 
// class template MakeTypelist 
// Takes a number of arguments equal to its numeric suffix 
// The arguments are type names. 
// MakeTypeList::Result 
// returns a typelist that is of T1, T2, ... 
//////////////////////////////////////////////////////////////////////////////// 
 
        template 
        < 
            typename T1  = NullType, typename T2  = NullType, typename T3  = NullType, 
            typename T4  = NullType, typename T5  = NullType, typename T6  = NullType, 
            typename T7  = NullType, typename T8  = NullType, typename T9  = NullType, 
            typename T10 = NullType, typename T11 = NullType, typename T12 = NullType, 
            typename T13 = NullType, typename T14 = NullType, typename T15 = NullType, 
            typename T16 = NullType, typename T17 = NullType, typename T18 = NullType 
        >  
        struct MakeTypeList 
        { 
        private: 
            typedef typename MakeTypeList 
            < 
                T2 , T3 , T4 ,  
                T5 , T6 , T7 ,  
                T8 , T9 , T10,  
                T11, T12, T13, 
                T14, T15, T16,  
                T17, T18 
            > 
            ::Result TailResult; 
 
        public: 
            typedef Typelist Result; 
        }; 
 
        template<> 
        struct MakeTypeList 
        < 
            NullType, NullType, NullType,  
            NullType, NullType, NullType,  
            NullType, NullType, NullType,  
            NullType, NullType, NullType, 
            NullType, NullType, NullType, 
            NullType, NullType, NullType 
        >{ 
            typedef NullType Result; 
        }; 
 
 
//////////////////////////////////////////////////////////////////////////////// 
// class template is_Typelist 
// detects if type is Typelist (including Nulltype) 
// Invocation : 
// is_Typelist::value 
// returns a compile-time boolean constant containing true iff T is some Typelist 
// is_Typelist::type_id 
// returns a compile-time unsigned constant containing  
// 1 iff T == Typelist, 2 iff T == NullType and 3 otherwise 
//////////////////////////////////////////////////////////////////////////////// 
        struct Typelist_tag {}; 
        struct NullType_tag {}; 
        struct NoneList_tag {}; 
         
        enum  
        { 
            Typelist_ID = 1, 
            NullType_ID = 2, 
            NoneList_ID = 3 
        }; 
 
        template 
        struct is_Typelist 
        { 
        private: 
            typedef char (&ye1)[Typelist_ID]; 
            typedef char (&ye2)[NullType_ID]; 
            typedef char (&no) [NoneList_ID]; 
 
            template 
            static ye1 check(Type2Type< Typelist >); 
            static ye2 check(Type2Type); 
 
            static no  check(...); 
 
        public: 
            // VC7 fail NPS_HierarchyGenerators.h if this one is enum 
            static const unsigned int type_id = sizeof(check( Type2Type() )); 
 
            enum { value = type_id != sizeof(no) }; 
 
            typedef typename Select 
            < 
                type_id == Typelist_ID,  
                Typelist_tag, 
                typename Select::Result 
            >  
            ::Result type_tag; 
        }; 
 
 
 
#ifndef TL_FAST_COMPILATION 
 
// this macro will cause compile time error if _type_ is not a Typelist or NullType 
#define ASSERT_TYPELIST(_type_) \ 
STATIC_CHECK( ::Loki::TL::is_Typelist<_type_>::value, TList_is_not_legal_Typelist ) 
 
#else 
 
// might improve the compilation time 
#define ASSERT_TYPELIST(_type_) \ 
typedef char _type_##_is_not_a_Typelist[true] 
 
#endif // ndef TL_FAST_COMPILATION 
 
//////////////////////////////////////////////////////////////////////////////// 
// class template Length 
// Computes the length of a typelist 
// Invocation (TList is a typelist): 
// Length::value 
// returns a compile-time constant containing the length of TList, not counting 
//     the end terminator (which by convention is NullType) 
//////////////////////////////////////////////////////////////////////////////// 
 
        template  struct Length; 
         
        template <>  
        struct Length 
        { 
            enum { value = 0 }; 
        }; 
         
        template  
        struct Length 
        { 
        private: 
            ASSERT_TYPELIST(TList); 
             
            typedef typename TList::Head Head; 
            typedef typename TList::Tail Tail; 
 
        public: 
            enum { value = 1 + Length::value }; 
        }; 
 
//////////////////////////////////////////////////////////////////////////////// 
// class template TypeAt 
// Finds the type at a given index in a typelist 
// Invocation (TList is a typelist and index is a compile-time integral  
//     constant): 
// TypeAt::Result 
// returns the type in position 'index' in TList 
// If you pass an out-of-bounds index, the result is a compile-time error 
//////////////////////////////////////////////////////////////////////////////// 
 
        template   
        struct TypeAt 
        { 
            typedef typename TList::Head Head; 
            typedef typename TList::Tail Tail; 
         
        private: 
            ASSERT_TYPELIST(TList); 
 
            template 
            struct In 
            { 
                typedef typename TypeAt::Result Result; 
            }; 
 
            template<> 
            struct In<0> 
            { 
                typedef Head Result; 
            }; 
 
        public: 
            typedef typename In::Result Result; 
        }; 
         
//////////////////////////////////////////////////////////////////////////////// 
// class template TypeAtNonStrict 
// Finds the type at a given index in a typelist 
// Invocations (TList is a typelist and index is a compile-time integral  
//     constant): 
// a) TypeAt::Result 
// returns the type in position 'index' in TList, or NullType if index is  
//     out-of-bounds 
// b) TypeAt::Result 
// returns the type in position 'index' in TList, or D if index is out-of-bounds 
//////////////////////////////////////////////////////////////////////////////// 
 
 
        template   
        struct TypeAtNonStrict 
        { 
            typedef typename TList::Head Head; 
            typedef typename TList::Tail Tail; 
         
        private: 
            ASSERT_TYPELIST(TList); 
 
            template 
            struct In 
            { 
                typedef typename TypeAtNonStrict 
                < 
                    typename TList1::Tail,  
                    i - 1, 
                    DefaultType 
                > 
                ::Result Result; 
            }; 
 
            template<> 
            struct In, 0> 
            { 
                typedef Head Result; 
            }; 
 
            template<> 
            struct In 
            { 
                typedef DefaultType Result; 
            }; 
        public: 
            typedef typename In::Result Result; 
        }; 
 
//////////////////////////////////////////////////////////////////////////////// 
// class template IndexOf 
// Finds the index of a type in a typelist 
// Invocation (TList is a typelist and T is a type): 
// IndexOf::value 
// returns the position of T in TList, or NullType if T is not found in TList 
//////////////////////////////////////////////////////////////////////////////// 
 
        template   
        struct IndexOf 
        { 
            typedef typename TList::Head Head; 
            typedef typename TList::Tail Tail; 
         
        private: 
            ASSERT_TYPELIST(TList); 
 
            template 
            struct In 
            { 
            private: 
                typedef typename TList1::Tail Tail; 
 
                enum { temp = (IndexOf::value) }; 
 
            public: 
                enum { value = temp == -1 ? -1 : 1 + temp  }; 
            }; 
 
            template<> 
            struct In< Typelist > 
            { 
                enum { value = 0 }; 
            }; 
 
            template<> 
            struct In 
            { 
                enum { value = -1 }; 
            }; 
 
        public: 
            enum { value = In::value }; 
        }; 
 
//////////////////////////////////////////////////////////////////////////////// 
// class template Append 
// Appends a type or a typelist to another 
// Invocation (TList is a typelist and T is either a type or a typelist): 
// Append::Result 
// returns a typelist that is TList followed by T and NullType-terminated 
//////////////////////////////////////////////////////////////////////////////// 
 
        template   
        struct Append 
        { 
            typedef typename TList::Head Head; 
            typedef typename TList::Tail Tail; 
         
        private: 
            ASSERT_TYPELIST(TList); 
 
            template 
            struct In 
            { 
                typedef typename TList1::Tail Tail; 
 
                typedef Typelist 
                < 
                    Head,  
                    typename Append::Result 
                >  
                Result; 
            }; 
 
            template<> 
            struct In 
            { 
                typedef typename Select 
                < 
                    is_Typelist::value,  
                    T, TYPELIST_1(T)  
                > 
                ::Result Result; 
            }; 
 
        public: 
            typedef typename In::Result Result; 
        }; 
         
//////////////////////////////////////////////////////////////////////////////// 
// class template Erase 
// Erases the first occurence, if any, of a type in a typelist 
// Invocation (TList is a typelist and T is a type): 
// Erase::Result 
// returns a typelist that is TList without the first occurence of T 
//////////////////////////////////////////////////////////////////////////////// 
 
        template   
        struct Erase 
        { 
            typedef typename TList::Head Head; 
            typedef typename TList::Tail Tail; 
         
        private: 
            ASSERT_TYPELIST(TList); 
 
            template 
            struct In 
            { 
                typedef typename TList1::Tail Tail; 
 
                typedef Typelist 
                < 
                    Head,  
                    typename Erase::Result 
                > 
                Result; 
            }; 
 
            template<> 
            struct In< Typelist > 
            { 
                typedef Tail Result; 
            }; 
 
            template<> 
            struct In 
            { 
                typedef NullType Result; 
            }; 
 
        public: 
            typedef typename In::Result Result; 
        }; 
 
//////////////////////////////////////////////////////////////////////////////// 
// class template EraseAll 
// Erases all first occurences, if any, of a type in a typelist 
// Invocation (TList is a typelist and T is a type): 
// EraseAll::Result 
// returns a typelist that is TList without any occurence of T 
//////////////////////////////////////////////////////////////////////////////// 
 
        template   
        struct EraseAll 
        { 
            typedef typename TList::Head Head; 
            typedef typename TList::Tail Tail; 
         
        private: 
            ASSERT_TYPELIST(TList); 
 
            template 
            struct In 
            { 
            private: 
                typedef typename TList1::Tail Tail; 
                typedef typename EraseAll::Result TailResult; 
             
            public: 
                typedef typename Select 
                < 
                    SameType::value, 
                    TailResult, 
                    Typelist 
                > 
                ::Result Result; 
            }; 
 
            template<> 
            struct In 
            { 
                typedef NullType Result; 
            }; 
 
        public: 
            typedef typename In::Result Result; 
        }; 
 
//////////////////////////////////////////////////////////////////////////////// 
// class template NoDuplicates 
// Removes all duplicate types in a typelist 
// Invocation (TList is a typelist): 
// NoDuplicates::Result 
//////////////////////////////////////////////////////////////////////////////// 
 
        template   
        struct NoDuplicates 
        { 
        private: 
            typedef typename TList::Head Head; 
            typedef typename TList::Tail Tail; 
         
            ASSERT_TYPELIST(TList); 
 
            typedef typename NoDuplicates::Result L1; 
            typedef typename Erase::Result    L2; 
 
        public: 
            typedef Typelist Result; 
        }; 
         
        template <>  
        struct NoDuplicates 
        { 
            typedef NullType Result; 
        }; 
 
//////////////////////////////////////////////////////////////////////////////// 
// class template Replace 
// Replaces the first occurence of a type in a typelist, with another type 
// Invocation (TList is a typelist, T, U are types): 
// Replace::Result 
// returns a typelist in which the first occurence of T is replaced with U 
//////////////////////////////////////////////////////////////////////////////// 
 
        template   
        struct Replace 
        { 
            typedef typename TList::Head Head; 
            typedef typename TList::Tail Tail; 
         
        private: 
            ASSERT_TYPELIST(TList); 
 
            template 
            struct In 
            { 
                typedef typename TList1::Tail Tail; 
 
                typedef Typelist 
                < 
                    Head,  
                    typename Replace::Result 
                > 
                Result; 
            }; 
 
            template<> 
            struct In< Typelist > 
            { 
                typedef Typelist Result; 
            }; 
 
            template<> 
            struct In 
            { 
                typedef NullType Result; 
            }; 
 
        public: 
            typedef typename In::Result Result; 
        }; 
 
//////////////////////////////////////////////////////////////////////////////// 
// class template ReplaceAll 
// Replaces all occurences of a type in a typelist, with another type 
// Invocation (TList is a typelist, T, U are types): 
// Replace::Result 
// returns a typelist in which all occurences of T is replaced with U 
//////////////////////////////////////////////////////////////////////////////// 
 
        template   
        struct ReplaceAll 
        { 
            typedef typename TList::Head Head; 
            typedef typename TList::Tail Tail; 
         
        private: 
            ASSERT_TYPELIST(TList); 
 
            template 
            struct In 
            { 
            private: 
                typedef typename TList1::Tail Tail; 
                typedef typename ReplaceAll::Result TailResult; 
             
            public: 
                typedef typename Select 
                < 
                    SameType::value, 
                    Typelist, 
                    Typelist 
                > 
                ::Result Result; 
            }; 
 
            template<> 
            struct In 
            { 
                typedef NullType Result; 
            }; 
 
        public: 
            typedef typename In::Result Result; 
        }; 
 
//////////////////////////////////////////////////////////////////////////////// 
// class template Reverse 
// Reverses a typelist 
// Invocation (TList is a typelist): 
// Reverse::Result 
// returns a typelist that is TList reversed 
//////////////////////////////////////////////////////////////////////////////// 
 
        template  struct Reverse; 
         
        template <> 
        struct Reverse 
        { 
            typedef NullType Result; 
        }; 
         
        template   
        struct Reverse 
        { 
        private: 
            typedef typename TList::Head Head; 
            typedef typename TList::Tail Tail; 
         
            ASSERT_TYPELIST(TList); 
 
        public: 
            typedef typename Append< 
                typename Reverse::Result, Head>::Result Result; 
        }; 
 
 
//////////////////////////////////////////////////////////////////////////////// 
// class template MostDerived 
// Finds the type in a typelist that is the most derived from a given type 
// Invocation (TList is a typelist, T is a type): 
// Replace::Result 
// returns the type in TList that's the most derived from T 
//////////////////////////////////////////////////////////////////////////////// 
 
        template   
        struct MostDerived 
        { 
            typedef typename TList::Head Head; 
            typedef typename TList::Tail Tail; 
         
        private: 
            ASSERT_TYPELIST(TList); 
 
            template 
            struct In 
            { 
            private: 
                typedef typename TList1::Tail Tail; 
                typedef typename TList1::Head Head; 
                typedef typename MostDerived::Result Candidate; 
             
            public: 
                typedef typename Select 
                < 
                    SUPERSUBCLASS(Candidate, Head), 
                    Head, Candidate 
                > 
                ::Result Result; 
            }; 
 
            template<> 
            struct In 
            { 
                typedef T Result; 
            }; 
 
        public: 
            typedef typename In::Result Result; 
        }; 
         
//////////////////////////////////////////////////////////////////////////////// 
// class template DerivedToFront 
// Arranges the types in a typelist so that the most derived types appear first 
// Invocation (TList is a typelist): 
// DerivedToFront::Result 
// returns the reordered TList  
//////////////////////////////////////////////////////////////////////////////// 
         
        template  struct DerivedToFront; 
         
        template <> 
        struct DerivedToFront 
        { 
            typedef NullType Result; 
        }; 
         
        template  
        struct DerivedToFront 
        { 
        private: 
            ASSERT_TYPELIST(TList); 
 
            typedef typename TList::Head Head; 
            typedef typename TList::Tail Tail; 
         
            typedef typename MostDerived::Result TheMostDerived; 
            typedef typename ReplaceAll::Result Temp; 
            typedef typename DerivedToFront::Result L; 
 
        public: 
            typedef Typelist Result; 
        }; 
                 
 
//////////////////////////////////////////////////////////////////////////////// 
// class template DerivedToFrontAll 
// Arranges all the types in a typelist so that the most derived types appear first 
// Invocation (TList is a typelist): 
// DerivedToFront::Result 
// returns the reordered TList  
//////////////////////////////////////////////////////////////////////////////// 
         
        template  struct DerivedToFrontAll; 
         
        template <> 
        struct DerivedToFrontAll 
        { 
            typedef NullType Result; 
        }; 
         
        template  
        struct DerivedToFrontAll 
        { 
        private: 
            ASSERT_TYPELIST(TList); 
 
            typedef typename TList::Head Head; 
            typedef typename TList::Tail Tail; 
         
            typedef typename MostDerived::Result TheMostDerived; 
            typedef typename Replace::Result L; 
             
            typedef typename DerivedToFrontAll::Result TailResult; 
 
        public: 
            typedef Typelist Result; 
        }; 
                                     
    }   // namespace TL 
}   // namespace Loki 
 
//////////////////////////////////////////////////////////////////////////////// 
// Change log: 
// June 09, 2001: Fix bug in parameter list of macros TYPELIST_23 to TYPELIST_27 
//      (credit due to Dave Taylor) 
// June 20, 2001: ported by Nick Thurn to gcc 2.95.3. Kudos, Nick!!! 
// May  10, 2002: ported by Rani Sharoni to VC7 (RTM - 9466) 
//////////////////////////////////////////////////////////////////////////////// 
 
#endif // TYPELIST_INC_