1 //////////////////////////////////////////////////////////////////////////////// 2 // The Loki Library 3 // Copyright (c) 2001 by Andrei Alexandrescu 4 // This code accompanies the book: 5 // Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design 6 // Patterns Applied". Copyright (c) 2001. Addison-Wesley. 7 // Permission to use, copy, modify, distribute and sell this software for any 8 // purpose is hereby granted without fee, provided that the above copyright 9 // notice appear in all copies and that both that copyright notice and this 10 // permission notice appear in supporting documentation. 11 // The author or Addison-Wesley Longman make no representations about the 12 // suitability of this software for any purpose. It is provided "as is" 13 // without express or implied warranty. 14 //////////////////////////////////////////////////////////////////////////////// 15 #ifndef LOKI_HIERARCHYGENERATORS_INC_ 16 #define LOKI_HIERARCHYGENERATORS_INC_ 17 18 // $Id: HierarchyGenerators.h 751 2006-10-17 19:50:37Z syntheticpp $ 19 20 21 #include "Typelist.h" 22 #include "TypeTraits.h" 23 #include "EmptyType.h" 24 25 namespace Loki 26 { 27 #if defined(_MSC_VER) && _MSC_VER >= 1300 28 #pragma warning( push ) 29 // 'class1' : base-class 'class2' is already a base-class of 'class3' 30 #pragma warning( disable : 4584 ) 31 #endif // _MSC_VER 32 33 //////////////////////////////////////////////////////////////////////////////// 34 // class template GenScatterHierarchy 35 // Generates a scattered hierarchy starting from a typelist and a template 36 // Invocation (TList is a typelist, Unit is a template of one arg): 37 // GenScatterHierarchy<TList, Unit> 38 // The generated class inherits all classes generated by instantiating the 39 // template 'Unit' with the types contained in TList 40 //////////////////////////////////////////////////////////////////////////////// 41 42 namespace Private 43 { 44 // The following type helps to overcome subtle flaw in the original 45 // implementation of GenScatterHierarchy. 46 // The flaw is revealed when the input type list of GenScatterHierarchy 47 // contains more then one element of the same type (e.g. LOKI_TYPELIST_2(int, int)). 48 // In this case GenScatterHierarchy will contain multiple bases of the same 49 // type and some of them will not be reachable (per 10.3). 50 // For example before the fix the first element of Tuple<LOKI_TYPELIST_2(int, int)> 51 // is not reachable in any way! 52 template<class, class> 53 struct ScatterHierarchyTag; 54 } 55 56 template <class TList, template <class> class Unit> 57 class GenScatterHierarchy; 58 59 template <class T1, class T2, template <class> class Unit> 60 class GenScatterHierarchy<Typelist<T1, T2>, Unit> 61 : public GenScatterHierarchy<Private::ScatterHierarchyTag<T1, T2>, Unit> 62 , public GenScatterHierarchy<T2, Unit> 63 { 64 public: 65 typedef Typelist<T1, T2> TList; 66 // Insure that LeftBase is unique and therefore reachable 67 typedef GenScatterHierarchy<Private::ScatterHierarchyTag<T1, T2>, Unit> LeftBase; 68 typedef GenScatterHierarchy<T2, Unit> RightBase; 69 template <typename T> struct Rebind 70 { 71 typedef Unit<T> Result; 72 }; 73 }; 74 75 // In the middle *unique* class that resolve possible ambiguity 76 template <class T1, class T2, template <class> class Unit> 77 class GenScatterHierarchy<Private::ScatterHierarchyTag<T1, T2>, Unit> 78 : public GenScatterHierarchy<T1, Unit> 79 { 80 }; 81 82 template <class AtomicType, template <class> class Unit> 83 class GenScatterHierarchy : public Unit<AtomicType> 84 { 85 typedef Unit<AtomicType> LeftBase; 86 template <typename T> struct Rebind 87 { 88 typedef Unit<T> Result; 89 }; 90 }; 91 92 template <template <class> class Unit> 93 class GenScatterHierarchy<NullType, Unit> 94 { 95 template <typename T> struct Rebind 96 { 97 typedef Unit<T> Result; 98 }; 99 }; 100 101 //////////////////////////////////////////////////////////////////////////////// 102 // function template Field 103 // Accesses a field in an object of a type generated with GenScatterHierarchy 104 // Invocation (obj is an object of a type H generated with GenScatterHierarchy, 105 // T is a type in the typelist used to generate H): 106 // Field<T>(obj) 107 // returns a reference to Unit<T>, where Unit is the template used to generate H 108 //////////////////////////////////////////////////////////////////////////////// 109 110 template <class T, class H> Field(H & obj)111 typename H::template Rebind<T>::Result& Field(H& obj) 112 { 113 return obj; 114 } 115 116 template <class T, class H> Field(const H & obj)117 const typename H::template Rebind<T>::Result& Field(const H& obj) 118 { 119 return obj; 120 } 121 122 //////////////////////////////////////////////////////////////////////////////// 123 // function template TupleUnit 124 // The building block of tuples 125 //////////////////////////////////////////////////////////////////////////////// 126 127 template <class T> 128 struct TupleUnit 129 { 130 T value_; 131 operator T&() { return value_; } 132 operator const T&() const { return value_; } 133 }; 134 135 //////////////////////////////////////////////////////////////////////////////// 136 // class template Tuple 137 // Implements a tuple class that holds a number of values and provides field 138 // access to them via the Field function (below) 139 //////////////////////////////////////////////////////////////////////////////// 140 141 template <class TList> 142 struct Tuple : public GenScatterHierarchy<TList, TupleUnit> 143 { 144 }; 145 146 //////////////////////////////////////////////////////////////////////////////// 147 // helper class template FieldHelper 148 // See Field below 149 //////////////////////////////////////////////////////////////////////////////// 150 151 template <class H, unsigned int i> struct FieldHelper; 152 153 template <class H> 154 struct FieldHelper<H, 0> 155 { 156 typedef typename H::TList::Head ElementType; 157 typedef typename H::template Rebind<ElementType>::Result UnitType; 158 159 enum 160 { 161 isTuple = Conversion<UnitType, TupleUnit<ElementType> >::sameType, 162 isConst = TypeTraits<H>::isConst 163 }; 164 165 typedef const typename H::LeftBase ConstLeftBase; 166 167 typedef typename Select<isConst, ConstLeftBase, 168 typename H::LeftBase>::Result LeftBase; 169 170 typedef typename Select<isTuple, ElementType, 171 UnitType>::Result UnqualifiedResultType; 172 173 typedef typename Select<isConst, const UnqualifiedResultType, 174 UnqualifiedResultType>::Result ResultType; 175 176 static ResultType& Do(H& obj) 177 { 178 LeftBase& leftBase = obj; 179 return leftBase; 180 } 181 }; 182 183 template <class H, unsigned int i> 184 struct FieldHelper 185 { 186 typedef typename TL::TypeAt<typename H::TList, i>::Result ElementType; 187 typedef typename H::template Rebind<ElementType>::Result UnitType; 188 189 enum 190 { 191 isTuple = Conversion<UnitType, TupleUnit<ElementType> >::sameType, 192 isConst = TypeTraits<H>::isConst 193 }; 194 195 typedef const typename H::RightBase ConstRightBase; 196 197 typedef typename Select<isConst, ConstRightBase, 198 typename H::RightBase>::Result RightBase; 199 200 typedef typename Select<isTuple, ElementType, 201 UnitType>::Result UnqualifiedResultType; 202 203 typedef typename Select<isConst, const UnqualifiedResultType, 204 UnqualifiedResultType>::Result ResultType; 205 206 static ResultType& Do(H& obj) 207 { 208 RightBase& rightBase = obj; 209 return FieldHelper<RightBase, i - 1>::Do(rightBase); 210 } 211 }; 212 213 //////////////////////////////////////////////////////////////////////////////// 214 // function template Field 215 // Accesses a field in an object of a type generated with GenScatterHierarchy 216 // Invocation (obj is an object of a type H generated with GenScatterHierarchy, 217 // i is the index of a type in the typelist used to generate H): 218 // Field<i>(obj) 219 // returns a reference to Unit<T>, where Unit is the template used to generate H 220 // and T is the i-th type in the typelist 221 //////////////////////////////////////////////////////////////////////////////// 222 223 template <int i, class H> 224 typename FieldHelper<H, i>::ResultType& 225 Field(H& obj) 226 { 227 return FieldHelper<H, i>::Do(obj); 228 } 229 230 // template <int i, class H> 231 // const typename FieldHelper<H, i>::ResultType& 232 // Field(const H& obj) 233 // { 234 // return FieldHelper<H, i>::Do(obj); 235 // } 236 237 //////////////////////////////////////////////////////////////////////////////// 238 // class template GenLinearHierarchy 239 // Generates a linear hierarchy starting from a typelist and a template 240 // Invocation (TList is a typelist, Unit is a template of two args): 241 // GenScatterHierarchy<TList, Unit> 242 //////////////////////////////////////////////////////////////////////////////// 243 244 template 245 < 246 class TList, 247 template <class AtomicType, class Base> class Unit, 248 class Root = EmptyType 249 > 250 class GenLinearHierarchy; 251 252 template 253 < 254 class T1, 255 class T2, 256 template <class, class> class Unit, 257 class Root 258 > 259 class GenLinearHierarchy<Typelist<T1, T2>, Unit, Root> 260 : public Unit< T1, GenLinearHierarchy<T2, Unit, Root> > 261 { 262 }; 263 264 template 265 < 266 class T, 267 template <class, class> class Unit, 268 class Root 269 > 270 class GenLinearHierarchy<Typelist<T, NullType>, Unit, Root> 271 : public Unit<T, Root> 272 { 273 }; 274 275 template 276 < 277 template <class, class> class Unit, 278 class Root 279 > 280 class GenLinearHierarchy<NullType , Unit, Root> 281 : public Root // is this better: Unit<NullType, Root> ? 282 { 283 }; 284 285 #if defined(_MSC_VER) && _MSC_VER >= 1300 286 #pragma warning( pop ) 287 #endif 288 } // namespace Loki 289 290 #endif // end file guardian 291 292