1 // This file is part of the ustl library, an STL implementation.
3 // Copyright (c) 2007 by Mike Sharov <msharov@users.sourceforge.net>
5 // This implementation is adapted from the Loki library, distributed under
6 // the MIT license with Copyright (c) 2001 by Andrei Alexandrescu.
11 #ifndef TYPELIST_H_2A8F84704780530D531716D41B3EA3FE
12 #define TYPELIST_H_2A8F84704780530D531716D41B3EA3FE
20 /// The building block of typelists. Use it throught the Seq templates.
21 template <typename T
, typename U
>
27 /// Namespace containing typelist-related functionality.
30 //----------------------------------------------------------------------
31 // Seq template definitions. The macros expand to a spec per arg count
33 #define TL_MAX_SEQ_TYPES 9
34 #define TL_MAX_SEQ_SPECS 8
35 #define TL_SEQ_TYPE(n) T##n
36 #define TL_SEQ_TYPENAME(n) typename TL_SEQ_TYPE(n)
37 #define TL_SEQ_NULLTYPE_DEFAULT(n) TL_SEQ_TYPENAME(n)=NullType
38 #define TL_SEQ_TL_END(n) >
39 #define TL_SEQ_ONE_TYPELIST(n) Typelist<TL_SEQ_TYPE(n)
41 /// Creates a typelist from a sequence of types
42 template <COMMA_LIST(TL_MAX_SEQ_TYPES
,TL_SEQ_NULLTYPE_DEFAULT
)>
44 typedef COMMA_LIST(TL_MAX_SEQ_TYPES
,TL_SEQ_ONE_TYPELIST
),
45 NullType
REPEAT(TL_MAX_SEQ_TYPES
,TL_SEQ_TL_END
) Type
;
48 #define TL_SEQ_SPEC(n) \
49 template <COMMA_LIST (n, TL_SEQ_TYPENAME)> \
50 struct Seq<COMMA_LIST (n, TL_SEQ_TYPE)> { \
51 typedef COMMA_LIST(n,TL_SEQ_ONE_TYPELIST), \
52 NullType REPEAT(n,TL_SEQ_TL_END) Type; \
54 LIST(TL_MAX_SEQ_SPECS
,TL_SEQ_SPEC
, ;);
58 #undef TL_SEQ_ONE_TYPELIST
59 #undef TL_SEQ_NULLTYPE_DEFAULT
61 #undef TL_MAX_SEQ_SPECS
63 //----------------------------------------------------------------------
64 // Various utility functions follow.
66 /// Length<List>::value is the number of types in the typelist.
67 template <typename List
> struct Length
{ };
68 template <> struct Length
<NullType
> { enum { value
= 0 }; };
69 template <typename T
, typename U
>
70 struct Length
<Typelist
<T
, U
> > { enum { value
= 1 + Length
<U
>::value
}; };
72 /// TypeAt<List, i>::Result is the ith type in List
73 template <typename List
, unsigned index
> struct TypeAt
{ };
74 template <class Head
, class Tail
>
75 struct TypeAt
<Typelist
<Head
, Tail
>, 0> {
78 template <class Head
, class Tail
, unsigned index
>
79 struct TypeAt
<Typelist
<Head
, Tail
>, index
> {
80 typedef typename TypeAt
<Tail
, index
-1>::Result Result
;
83 /// TypeAtNonStrict<List,i,DefaultType>::Result is List[i] or DefaultType if out of range.
84 template <typename List
, unsigned index
, typename DefaultType
= NullType
>
85 struct TypeAtNonStrict
{
86 typedef DefaultType Result
;
88 template <typename Head
, typename Tail
, typename DefaultType
>
89 struct TypeAtNonStrict
<Typelist
<Head
, Tail
>, 0, DefaultType
> {
92 template <typename Head
, typename Tail
, unsigned index
, typename DefaultType
>
93 struct TypeAtNonStrict
<Typelist
<Head
, Tail
>, index
, DefaultType
> {
94 typedef typename TypeAtNonStrict
<Tail
, index
-1, DefaultType
>::Result Result
;
97 /// IndexOf<List,T>::value is the position of T in List, or -1 if not found.
98 template <typename List
, typename T
> struct IndexOf
;
100 struct IndexOf
<NullType
, T
> { enum { value
= -1 }; };
101 template <typename T
, typename Tail
>
102 struct IndexOf
<Typelist
<T
, Tail
>, T
> { enum { value
= 0 }; };
103 template <typename Head
, typename Tail
, typename T
>
104 struct IndexOf
<Typelist
<Head
, Tail
>, T
> {
106 enum { iintail
= IndexOf
<Tail
, T
>::value
};
108 enum { value
= (iintail
== -1 ? -1 : 1+iintail
) };
111 /// Appends a type or a typelist to another in Append<TList, T>::Result
112 template <typename List
, typename T
> struct Append
;
113 template <> struct Append
<NullType
, NullType
> { typedef NullType Result
; };
114 template <typename T
> struct Append
<NullType
, T
> {
115 typedef Typelist
<T
,NullType
> Result
;
117 template <typename Head
, typename Tail
>
118 struct Append
<NullType
, Typelist
<Head
, Tail
> > {
119 typedef Typelist
<Head
, Tail
> Result
;
121 template <typename Head
, typename Tail
, typename T
>
122 struct Append
<Typelist
<Head
, Tail
>, T
> {
123 typedef Typelist
<Head
, typename Append
<Tail
, T
>::Result
> Result
;
126 // Erase<List, T>::Result contains List without the first T.
127 template <typename TList
, typename T
> struct Erase
;
128 template <typename T
>
129 struct Erase
<NullType
, T
> { typedef NullType Result
; };
130 template <typename T
, typename Tail
>
131 struct Erase
<Typelist
<T
, Tail
>, T
> { typedef Tail Result
; };
132 template <typename Head
, typename Tail
, typename T
>
133 struct Erase
<Typelist
<Head
, Tail
>, T
> {
134 typedef Typelist
<Head
, typename Erase
<Tail
, T
>::Result
> Result
;
137 // EraseAll<List, T>::Result contains List without any T.
138 template <typename List
, typename T
> struct EraseAll
;
139 template <typename T
>
140 struct EraseAll
<NullType
, T
> { typedef NullType Result
; };
141 template <typename T
, typename Tail
>
142 struct EraseAll
<Typelist
<T
, Tail
>, T
> {
143 typedef typename EraseAll
<Tail
, T
>::Result Result
;
145 template <typename Head
, typename Tail
, typename T
>
146 struct EraseAll
<Typelist
<Head
, Tail
>, T
> {
147 typedef Typelist
<Head
, typename EraseAll
<Tail
, T
>::Result
> Result
;
150 /// Removes all duplicate types in a typelist
151 template <typename List
> struct NoDuplicates
;
152 template <> struct NoDuplicates
<NullType
> { typedef NullType Result
; };
153 template <typename Head
, typename Tail
>
154 struct NoDuplicates
< Typelist
<Head
, Tail
> > {
156 typedef typename NoDuplicates
<Tail
>::Result L1
;
157 typedef typename Erase
<L1
, Head
>::Result L2
;
159 typedef Typelist
<Head
, L2
> Result
;
162 // Replaces the first occurence of a type in a typelist, with another type
163 template <typename List
, typename T
, typename U
> struct Replace
;
164 template <typename T
, typename U
>
165 struct Replace
<NullType
, T
, U
> { typedef NullType Result
; };
166 template <typename T
, typename Tail
, typename U
>
167 struct Replace
<Typelist
<T
, Tail
>, T
, U
> {
168 typedef Typelist
<U
, Tail
> Result
;
170 template <typename Head
, typename Tail
, typename T
, typename U
>
171 struct Replace
<Typelist
<Head
, Tail
>, T
, U
> {
172 typedef Typelist
<Head
, typename Replace
<Tail
, T
, U
>::Result
> Result
;
175 // Replaces all occurences of a type in a typelist, with another type
176 template <typename List
, typename T
, typename U
> struct ReplaceAll
;
177 template <typename T
, typename U
>
178 struct ReplaceAll
<NullType
, T
, U
> { typedef NullType Result
; };
179 template <typename T
, typename Tail
, typename U
>
180 struct ReplaceAll
<Typelist
<T
, Tail
>, T
, U
> {
181 typedef Typelist
<U
, typename ReplaceAll
<Tail
, T
, U
>::Result
> Result
;
183 template <typename Head
, typename Tail
, typename T
, typename U
>
184 struct ReplaceAll
<Typelist
<Head
, Tail
>, T
, U
> {
185 typedef Typelist
<Head
, typename ReplaceAll
<Tail
, T
, U
>::Result
> Result
;
188 // Reverses a typelist
189 template <typename List
> struct Reverse
;
190 template <> struct Reverse
<NullType
> { typedef NullType Result
; };
191 template <typename Head
, typename Tail
>
192 struct Reverse
< Typelist
<Head
, Tail
> > {
193 typedef typename Append
<typename Reverse
<Tail
>::Result
, Head
>::Result Result
;
196 // Finds the type in a typelist that is the most derived from a given type
197 template <typename List
, typename T
> struct MostDerived
;
198 template <typename T
> struct MostDerived
<NullType
, T
> { typedef T Result
; };
199 template <typename Head
, typename Tail
, typename T
>
200 struct MostDerived
<Typelist
<Head
, Tail
>, T
> {
202 typedef typename MostDerived
<Tail
, T
>::Result Candidate
;
204 typedef typename Select
<SuperSubclass
<Candidate
,Head
>::value
, Head
, Candidate
>::Result Result
;
207 // Arranges the types in a typelist so that the most derived types appear first
208 template <typename List
> struct DerivedToFront
;
209 template <> struct DerivedToFront
<NullType
> { typedef NullType Result
; };
210 template <typename Head
, typename Tail
>
211 struct DerivedToFront
< Typelist
<Head
, Tail
> > {
213 typedef typename MostDerived
<Tail
, Head
>::Result TheMostDerived
;
214 typedef typename Replace
<Tail
, TheMostDerived
, Head
>::Result Temp
;
215 typedef typename DerivedToFront
<Temp
>::Result L
;
217 typedef Typelist
<TheMostDerived
, L
> Result
;
220 //----------------------------------------------------------------------