1 /*=========================================================================
2 
3   Program:   Visualization Toolkit
4   Module:    vtkTypeList.txx
5 
6   Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
7   All rights reserved.
8   See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
9 
10      This software is distributed WITHOUT ANY WARRANTY; without even
11      the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
12      PURPOSE.  See the above copyright notice for more information.
13 
14 =========================================================================*/
15 
16 #ifndef vtkTypeList_txx
17 #define vtkTypeList_txx
18 
19 #include "vtkTypeList.h"
20 
21 namespace vtkTypeList
22 {
23 
24 //------------------------------------------------------------------------------
25 // Description:
26 // Sets Result to T if Exp is true, or F if Exp is false.
27 template <bool Exp, typename T, typename F>
28 struct Select // True case:
29 {
30   typedef T Result;
31 };
32 
33 // False case:
34 template <typename T, typename F>
35 struct Select<false, T, F>
36 {
37   typedef F Result;
38 };
39 
40 //------------------------------------------------------------------------------
41 // Description:
42 // Sets member Result to true if a conversion exists to convert type From to
43 // type To. Member SameType will be true if the types are identical.
44 template <typename From, typename To>
45 struct CanConvert
46 {
47 private:
48   typedef char Small;
49   class Big { char dummy[2]; };
50   static Small DoTest(const To&); // Not implemented
51   static Big DoTest(...); // Not implemented
52   static From* MakeFrom(); // Not implemented
53 public:
54   enum {
55     Result = (sizeof(DoTest(*MakeFrom())) == sizeof(Small)),
56     SameType = false
57   };
58 };
59 
60 // Specialize for SameType:
61 template <typename T>
62 struct CanConvert<T, T>
63 {
64   enum { Result = true, SameType = true };
65 };
66 
67 //------------------------------------------------------------------------------
68 // Description:
69 // Sets the enum value Result to the index of type T in the TypeList TList.
70 // Result will equal -1 if the type is not found.
71 
72 // Terminal case:
73 template <typename T>
74 struct IndexOf<NullType, T>
75 {
76   enum { Result = -1 };
77 };
78 
79 // Matching case:
80 template <typename T, typename Tail>
81 struct IndexOf<TypeList<T, Tail>, T>
82 {
83   enum { Result = 0 };
84 };
85 
86 // Recursive case:
87 template <typename T, typename U, typename Tail>
88 struct IndexOf<TypeList<U, Tail>, T>
89 {
90 private:
91   enum { TailResult = IndexOf<Tail, T>::Result };
92 public:
93   enum { Result = TailResult == -1 ? -1 : 1 + TailResult };
94 };
95 
96 //------------------------------------------------------------------------------
97 // Description:
98 // Erase the first element of type T from TypeList TList.
99 
100 // Terminal case:
101 template <typename T>
102 struct Erase<NullType, T>
103 {
104   typedef NullType Result;
105 };
106 
107 // Match:
108 template <typename Tail, typename T>
109 struct Erase<TypeList<T, Tail>, T>
110 {
111   typedef Tail Result;
112 };
113 
114 // No match:
115 template <typename Head, typename Tail, typename T>
116 struct Erase<TypeList<Head, Tail>, T>
117 {
118   typedef TypeList<Head, typename Erase<Tail, T>::Result> Result;
119 };
120 
121 //------------------------------------------------------------------------------
122 // Description:
123 // Erase all type T from TypeList TList.
124 
125 // Terminal case:
126 template <typename T>
127 struct EraseAll<NullType, T>
128 {
129   typedef NullType Result;
130 };
131 
132 // Match:
133 template <typename Tail, typename T>
134 struct EraseAll<TypeList<T, Tail>, T>
135 {
136   typedef typename EraseAll<T, Tail>::Result Result;
137 };
138 
139 // No match:
140 template <typename Head, typename Tail, typename T>
141 struct EraseAll<TypeList<Head, Tail>, T>
142 {
143   typedef TypeList<Head, typename EraseAll<Tail, T>::Result> Result;
144 };
145 
146 //------------------------------------------------------------------------------
147 // Description:
148 // Remove all duplicate types from TypeList TList
149 
150 // Terminal case:
151 template <>
152 struct Unique<NullType>
153 {
154   typedef NullType Result;
155 };
156 
157 template <typename Head, typename Tail>
158 struct Unique<TypeList<Head, Tail> >
159 {
160 private:
161   typedef typename Unique<Tail>::Result UniqueTail;
162   typedef typename Erase<UniqueTail, Head>::Result NewTail;
163 public:
164   typedef TypeList<Head, NewTail> Result;
165 };
166 
167 //------------------------------------------------------------------------------
168 // Description:
169 // Replace the first instance of Bad with Good in the TypeList TList.
170 
171 // Terminal case:
172 template <typename Bad, typename Good>
173 struct Replace<NullType, Bad, Good>
174 {
175   typedef NullType Result;
176 };
177 
178 // Match:
179 template <typename Tail, typename Bad, typename Good>
180 struct Replace<TypeList<Bad, Tail>, Bad, Good>
181 {
182   typedef TypeList<Good, Tail> Result;
183 };
184 
185 // No match:
186 template <typename Head, typename Tail, typename Bad, typename Good>
187 struct Replace<TypeList<Head, Tail>, Bad, Good>
188 {
189   typedef TypeList<Head, typename Replace<Tail, Bad, Good>::Result> Result;
190 };
191 
192 // Trivial case:
193 template <typename Head, typename Tail, typename T>
194 struct Replace<TypeList<Head, Tail>, T, T>
195 {
196   typedef TypeList<Head, Tail> Result;
197 };
198 
199 //------------------------------------------------------------------------------
200 // Description:
201 // Replace all instances of Bad with Good in the TypeList TList.
202 
203 // Terminal case:
204 template <typename Bad, typename Good>
205 struct ReplaceAll<NullType, Bad, Good>
206 {
207   typedef NullType Result;
208 };
209 
210 // Match:
211 template <typename Tail, typename Bad, typename Good>
212 struct ReplaceAll<TypeList<Bad, Tail>, Bad, Good>
213 {
214   typedef TypeList<Good, typename ReplaceAll<Tail, Bad, Good>::Result> Result;
215 };
216 
217 // No match:
218 template <typename Head, typename Tail, typename Bad, typename Good>
219 struct ReplaceAll<TypeList<Head, Tail>, Bad, Good>
220 {
221   typedef TypeList<Head, typename ReplaceAll<Tail, Bad, Good>::Result> Result;
222 };
223 
224 // Trivial case:
225 template <typename Head, typename Tail, typename T>
226 struct ReplaceAll<TypeList<Head, Tail>, T, T>
227 {
228   typedef TypeList<Head, Tail> Result;
229 };
230 
231 //------------------------------------------------------------------------------
232 // Description:
233 // Given a type T and a TypeList TList, store the most derived type of T in
234 // TList as Result. If no subclasses of T exist in TList, T will be set as
235 // Result, even if T itself is not in TList.
236 
237 // Terminal case:
238 template <typename T>
239 struct MostDerived<NullType, T>
240 {
241   typedef T Result;
242 };
243 
244 // Recursive case:
245 template <typename Head, typename Tail, typename T>
246 struct MostDerived<TypeList<Head, Tail>, T>
247 {
248 private:
249   typedef typename MostDerived<Tail, T>::Result TailResult;
250 public:
251   typedef
252     typename Select<
253       CanConvert<TailResult, Head>::Result, Head, TailResult
254     >::Result Result;
255 };
256 
257 //------------------------------------------------------------------------------
258 // Description:
259 // Sort the TypeList from most-derived to least-derived type, storing the
260 // sorted TypeList in Result. Note that the input TypeList cannot have duplicate
261 // types (see Unique).
262 
263 // Terminal case:
264 template <>
265 struct DerivedToFront<NullType>
266 {
267   typedef NullType Result;
268 };
269 
270 // Recursive case:
271 template <typename Head, typename Tail>
272 struct DerivedToFront<TypeList<Head, Tail> >
273 {
274 private:
275   typedef typename MostDerived<Tail, Head>::Result Derived;
276   typedef typename Replace<Tail, Derived, Head>::Result Replaced;
277   typedef typename DerivedToFront<Replaced>::Result NewTail;
278 public:
279   typedef TypeList<Derived, NewTail> Result;
280 };
281 
282 //------------------------------------------------------------------------------
283 // Description:
284 // Appends type T to TypeList TList and stores the result in Result.
285 
286 // Corner case, both are NullType:
287 template < >
288 struct Append<vtkTypeList::NullType, vtkTypeList::NullType>
289 {
290   typedef vtkTypeList::NullType Result;
291 };
292 
293 // Terminal case (Single type):
294 template <typename T>
295 struct Append<vtkTypeList::NullType, T>
296 {
297   typedef vtkTypeList::TypeList<T, vtkTypeList::NullType> Result;
298 };
299 
300 // Terminal case (TypeList):
301 template <typename Head, typename Tail>
302 struct Append<vtkTypeList::NullType, vtkTypeList::TypeList<Head, Tail> >
303 {
304   typedef vtkTypeList::TypeList<Head, Tail> Result;
305 };
306 
307 // Recursive case:
308 template <typename Head, typename Tail, typename T>
309 struct Append<vtkTypeList::TypeList<Head, Tail>, T>
310 {
311   typedef vtkTypeList::TypeList<Head, typename Append<Tail, T>::Result > Result;
312 };
313 
314 }
315 
316 #endif // vtkTypeList_txx
317