]> git.cworth.org Git - vogl/blob - src/extlib/loki/include/loki/HierarchyGenerators.h
Initial vogl checkin
[vogl] / src / extlib / loki / include / loki / HierarchyGenerators.h
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>
111 typename H::template Rebind<T>::Result &Field(H &obj)
112 {
113         return obj;
114 }
115
116 template <class T, class H>
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 &()
132         {
133                 return value_;
134         }
135         operator const T &() const
136         {
137                 return value_;
138         }
139 };
140
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 ////////////////////////////////////////////////////////////////////////////////
146
147 template <class TList>
148 struct Tuple : public GenScatterHierarchy<TList, TupleUnit>
149 {
150 };
151
152 ////////////////////////////////////////////////////////////////////////////////
153 // helper class template FieldHelper
154 // See Field below
155 ////////////////////////////////////////////////////////////////////////////////
156
157 template <class H, unsigned int i> struct FieldHelper;
158
159 template <class H>
160 struct FieldHelper<H, 0>
161 {
162         typedef typename H::TList::Head ElementType;
163         typedef typename H::template Rebind<ElementType>::Result UnitType;
164
165         enum
166         {
167                 isTuple = Conversion<UnitType, TupleUnit<ElementType> >::sameType,
168                 isConst = TypeTraits<H>::isConst
169         };
170
171         typedef const typename H::LeftBase ConstLeftBase;
172
173         typedef typename Select<isConst, ConstLeftBase,
174                 typename H::LeftBase>::Result LeftBase;
175
176         typedef typename Select<isTuple, ElementType,
177                 UnitType>::Result UnqualifiedResultType;
178
179         typedef typename Select<isConst, const UnqualifiedResultType,
180                 UnqualifiedResultType>::Result ResultType;
181
182         static ResultType &Do(H &obj)
183         {
184                 LeftBase &leftBase = obj;
185                 return leftBase;
186         }
187 };
188
189 template <class H, unsigned int i>
190 struct FieldHelper
191 {
192         typedef typename TL::TypeAt<typename H::TList, i>::Result ElementType;
193         typedef typename H::template Rebind<ElementType>::Result UnitType;
194
195         enum
196         {
197                 isTuple = Conversion<UnitType, TupleUnit<ElementType> >::sameType,
198                 isConst = TypeTraits<H>::isConst
199         };
200
201         typedef const typename H::RightBase ConstRightBase;
202
203         typedef typename Select<isConst, ConstRightBase,
204                 typename H::RightBase>::Result RightBase;
205
206         typedef typename Select<isTuple, ElementType,
207                 UnitType>::Result UnqualifiedResultType;
208
209         typedef typename Select<isConst, const UnqualifiedResultType,
210                 UnqualifiedResultType>::Result ResultType;
211
212         static ResultType &Do(H &obj)
213         {
214                 RightBase &rightBase = obj;
215                 return FieldHelper<RightBase, i - 1>::Do(rightBase);
216         }
217 };
218
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):
224 // Field<i>(obj)
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 ////////////////////////////////////////////////////////////////////////////////
228
229 template <int i, class H>
230 typename FieldHelper<H, i>::ResultType &
231 Field(H &obj)
232 {
233         return FieldHelper<H, i>::Do(obj);
234 }
235
236 //    template <int i, class H>
237 //    const typename FieldHelper<H, i>::ResultType&
238 //    Field(const H& obj)
239 //    {
240 //        return FieldHelper<H, i>::Do(obj);
241 //    }
242
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 ////////////////////////////////////////////////////////////////////////////////
249
250 template
251 <
252 class TList,
253       template <class AtomicType, class Base> class Unit,
254       class Root = EmptyType
255       >
256 class GenLinearHierarchy;
257
258 template
259 <
260 class T1,
261       class T2,
262       template <class, class> class Unit,
263       class Root
264       >
265 class GenLinearHierarchy<Typelist<T1, T2>, Unit, Root>
266         : public Unit< T1, GenLinearHierarchy<T2, Unit, Root> >
267 {
268 };
269
270 template
271 <
272 class T,
273       template <class, class> class Unit,
274       class Root
275       >
276 class GenLinearHierarchy<Typelist<T, NullType>, Unit, Root>
277         : public Unit<T, Root>
278 {
279 };
280
281 template
282 <
283 template <class, class> class Unit,
284          class Root
285          >
286 class GenLinearHierarchy<NullType , Unit, Root>
287         : public Root // is this better: Unit<NullType, Root> ?
288 {
289 };
290
291 #if defined(_MSC_VER) && _MSC_VER >= 1300
292 #pragma warning( pop )
293 #endif
294 }   // namespace Loki
295
296 #endif // end file guardian
297