Build system improvements
[ustl.git] / typelist.h
blob88c92e80d47af74e1a3b5714277b908f1dcb2c80
1 // This file is part of the ustl library, an STL implementation.
2 //
3 // Copyright (c) 2007 by Mike Sharov <msharov@users.sourceforge.net>
4 //
5 // This implementation is adapted from the Loki library, distributed under
6 // the MIT license with Copyright (c) 2001 by Andrei Alexandrescu.
7 //
8 // typelist.h
9 //
11 #ifndef TYPELIST_H_2A8F84704780530D531716D41B3EA3FE
12 #define TYPELIST_H_2A8F84704780530D531716D41B3EA3FE
14 #include "metamac.h"
15 #include "typet.h"
17 namespace ustl {
18 namespace tm {
20 /// The building block of typelists. Use it throught the Seq templates.
21 template <typename T, typename U>
22 struct Typelist {
23 typedef T Head;
24 typedef U Tail;
27 /// Namespace containing typelist-related functionality.
28 namespace tl {
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)>
43 struct Seq {
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, ;);
56 #undef TL_SEQ_SPEC
57 #undef TL_SEQ_TL_END
58 #undef TL_SEQ_ONE_TYPELIST
59 #undef TL_SEQ_NULLTYPE_DEFAULT
60 #undef TL_SEQ_TYPE
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> {
76 typedef Head Result;
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> {
90 typedef Head Result;
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;
99 template <typename T>
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> {
105 private:
106 enum { iintail = IndexOf<Tail, T>::value };
107 public:
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> > {
155 private:
156 typedef typename NoDuplicates<Tail>::Result L1;
157 typedef typename Erase<L1, Head>::Result L2;
158 public:
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> {
201 private:
202 typedef typename MostDerived<Tail, T>::Result Candidate;
203 public:
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> > {
212 private:
213 typedef typename MostDerived<Tail, Head>::Result TheMostDerived;
214 typedef typename Replace<Tail, TheMostDerived, Head>::Result Temp;
215 typedef typename DerivedToFront<Temp>::Result L;
216 public:
217 typedef Typelist<TheMostDerived, L> Result;
220 //----------------------------------------------------------------------
222 } // namespace tl
223 } // namespace tm
224 } // namespace ustl
226 #endif