1 ////////////////////////////////////////////////////////////////////////////////
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_
18 // $Id: HierarchyGenerators.h 751 2006-10-17 19:50:37Z syntheticpp $
22 #include "TypeTraits.h"
23 #include "EmptyType.h"
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 )
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 ////////////////////////////////////////////////////////////////////////////////
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;
56 template <class TList, template <class> class Unit>
57 class GenScatterHierarchy;
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>
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
71 typedef Unit<T> Result;
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>
82 template <class AtomicType, template <class> class Unit>
83 class GenScatterHierarchy : public Unit<AtomicType>
85 typedef Unit<AtomicType> LeftBase;
86 template <typename T> struct Rebind
88 typedef Unit<T> Result;
92 template <template <class> class Unit>
93 class GenScatterHierarchy<NullType, Unit>
95 template <typename T> struct Rebind
97 typedef Unit<T> Result;
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):
107 // returns a reference to Unit<T>, where Unit is the template used to generate H
108 ////////////////////////////////////////////////////////////////////////////////
110 template <class T, class H>
111 typename H::template Rebind<T>::Result &Field(H &obj)
116 template <class T, class H>
117 const typename H::template Rebind<T>::Result &Field(const H &obj)
122 ////////////////////////////////////////////////////////////////////////////////
123 // function template TupleUnit
124 // The building block of tuples
125 ////////////////////////////////////////////////////////////////////////////////
135 operator const T &() const
141 ////////////////////////////////////////////////////////////////////////////////
142 // class template Tuple
143 // Implements a tuple class that holds a number of values and provides field
144 // access to them via the Field function (below)
145 ////////////////////////////////////////////////////////////////////////////////
147 template <class TList>
148 struct Tuple : public GenScatterHierarchy<TList, TupleUnit>
152 ////////////////////////////////////////////////////////////////////////////////
153 // helper class template FieldHelper
155 ////////////////////////////////////////////////////////////////////////////////
157 template <class H, unsigned int i> struct FieldHelper;
160 struct FieldHelper<H, 0>
162 typedef typename H::TList::Head ElementType;
163 typedef typename H::template Rebind<ElementType>::Result UnitType;
167 isTuple = Conversion<UnitType, TupleUnit<ElementType> >::sameType,
168 isConst = TypeTraits<H>::isConst
171 typedef const typename H::LeftBase ConstLeftBase;
173 typedef typename Select<isConst, ConstLeftBase,
174 typename H::LeftBase>::Result LeftBase;
176 typedef typename Select<isTuple, ElementType,
177 UnitType>::Result UnqualifiedResultType;
179 typedef typename Select<isConst, const UnqualifiedResultType,
180 UnqualifiedResultType>::Result ResultType;
182 static ResultType &Do(H &obj)
184 LeftBase &leftBase = obj;
189 template <class H, unsigned int i>
192 typedef typename TL::TypeAt<typename H::TList, i>::Result ElementType;
193 typedef typename H::template Rebind<ElementType>::Result UnitType;
197 isTuple = Conversion<UnitType, TupleUnit<ElementType> >::sameType,
198 isConst = TypeTraits<H>::isConst
201 typedef const typename H::RightBase ConstRightBase;
203 typedef typename Select<isConst, ConstRightBase,
204 typename H::RightBase>::Result RightBase;
206 typedef typename Select<isTuple, ElementType,
207 UnitType>::Result UnqualifiedResultType;
209 typedef typename Select<isConst, const UnqualifiedResultType,
210 UnqualifiedResultType>::Result ResultType;
212 static ResultType &Do(H &obj)
214 RightBase &rightBase = obj;
215 return FieldHelper<RightBase, i - 1>::Do(rightBase);
219 ////////////////////////////////////////////////////////////////////////////////
220 // function template Field
221 // Accesses a field in an object of a type generated with GenScatterHierarchy
222 // Invocation (obj is an object of a type H generated with GenScatterHierarchy,
223 // i is the index of a type in the typelist used to generate H):
225 // returns a reference to Unit<T>, where Unit is the template used to generate H
226 // and T is the i-th type in the typelist
227 ////////////////////////////////////////////////////////////////////////////////
229 template <int i, class H>
230 typename FieldHelper<H, i>::ResultType &
233 return FieldHelper<H, i>::Do(obj);
236 // template <int i, class H>
237 // const typename FieldHelper<H, i>::ResultType&
238 // Field(const H& obj)
240 // return FieldHelper<H, i>::Do(obj);
243 ////////////////////////////////////////////////////////////////////////////////
244 // class template GenLinearHierarchy
245 // Generates a linear hierarchy starting from a typelist and a template
246 // Invocation (TList is a typelist, Unit is a template of two args):
247 // GenScatterHierarchy<TList, Unit>
248 ////////////////////////////////////////////////////////////////////////////////
253 template <class AtomicType, class Base> class Unit,
254 class Root = EmptyType
256 class GenLinearHierarchy;
262 template <class, class> class Unit,
265 class GenLinearHierarchy<Typelist<T1, T2>, Unit, Root>
266 : public Unit< T1, GenLinearHierarchy<T2, Unit, Root> >
273 template <class, class> class Unit,
276 class GenLinearHierarchy<Typelist<T, NullType>, Unit, Root>
277 : public Unit<T, Root>
283 template <class, class> class Unit,
286 class GenLinearHierarchy<NullType , Unit, Root>
287 : public Root // is this better: Unit<NullType, Root> ?
291 #if defined(_MSC_VER) && _MSC_VER >= 1300
292 #pragma warning( pop )
296 #endif // end file guardian