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