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