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-Welsey 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
16 // Last update: March 05, 2001
17
18 #ifndef HIERARCHYGENERATORS_INC_
19 #define HIERARCHYGENERATORS_INC_
20
21 #include "Typelist.h"
22 #include "TypeTraits.h"
23 #include "EmptyType.h"
24
25 namespace Loki
26 {
27 ////////////////////////////////////////////////////////////////////////////////
28 // class template GenScatterHierarchy
29 // Generates a scattered hierarchy starting from a typelist and a template
30 // Invocation (TList is a typelist, Model is a template of one arg):
31 // GenScatterHierarchy<TList, Model>
32 // The generated class inherits all classes generated by instantiating the
33 // template 'Model' with the types contained in TList
34 ////////////////////////////////////////////////////////////////////////////////
35
36 template <class TList, template <class> class Unit>
37 class GenScatterHierarchy;
38
39 template <class T1, class T2, template <class> class Unit>
40 class GenScatterHierarchy<Typelist<T1, T2>, Unit>
41 : public GenScatterHierarchy<T1, Unit>
42 , public GenScatterHierarchy<T2, Unit>
43 {
44 public:
45 typedef Typelist<T1, T2> TList;
46 typedef GenScatterHierarchy<T1, Unit> LeftBase;
47 typedef GenScatterHierarchy<T2, Unit> RightBase;
48 template <typename T> struct Rebind
49 {
50 typedef Unit<T> Result;
51 };
52 };
53
54 template <class AtomicType, template <class> class Unit>
55 class GenScatterHierarchy : public Unit<AtomicType>
56 {
57 typedef Unit<AtomicType> LeftBase;
58 template <typename T> struct Rebind
59 {
60 typedef Unit<T> Result;
61 };
62 };
63
64 template <template <class> class Unit>
65 class GenScatterHierarchy<NullType, Unit>
66 {
67 template <typename T> struct Rebind
68 {
69 typedef Unit<T> Result;
70 };
71 };
72
73 ////////////////////////////////////////////////////////////////////////////////
74 // function template Field
75 // Accesses a field in an object of a type generated with GenScatterHierarchy
76 // Invocation (obj is an object of a type H generated with GenScatterHierarchy,
77 // T is a type in the typelist used to generate H):
78 // Field<T>(obj)
79 // returns a reference to Unit<T>, where Unit is the template used to generate H
80 ////////////////////////////////////////////////////////////////////////////////
81
82 template <class T, class H>
83 typename H::Rebind<T>::Result& Field(H& obj)
84 {
85 return obj;
86 }
87
88 template <class T, class H>
89 const typename H::Rebind<T>::Result& Field(const H& obj)
90 {
91 return obj;
92 }
93
94 ////////////////////////////////////////////////////////////////////////////////
95 // function template TupleUnit
96 // The building block of tuples
97 ////////////////////////////////////////////////////////////////////////////////
98
99 template <class T>
100 struct TupleUnit
101 {
102 T value_;
103 operator T&() { return value_; }
104 operator const T&() const { return value_; }
105 };
106
107 ////////////////////////////////////////////////////////////////////////////////
108 // class template Tuple
109 // Implements a tuple class that holds a number of values and provides field
110 // access to them via the Field function (below)
111 ////////////////////////////////////////////////////////////////////////////////
112
113 template <class TList>
114 struct Tuple : public GenScatterHierarchy<TList, TupleUnit>
115 {
116 };
117
118 ////////////////////////////////////////////////////////////////////////////////
119 // helper class template FieldHelper
120 // See Field below
121 ////////////////////////////////////////////////////////////////////////////////
122
123 template <class H, unsigned int i> struct FieldHelper;
124
125 template <class H>
126 struct FieldHelper<H, 0>
127 {
128 typedef typename H::TList::Head ElementType;
129 typedef typename H::Rebind<ElementType>::Result UnitType;
130
131 enum
132 {
133 isTuple = Conversion<UnitType, TupleUnit<ElementType> >::sameType,
134 isConst = TypeTraits<H>::isConst
135 };
136
137 typedef const typename H::LeftBase ConstLeftBase;
138
139 typedef typename Select<isConst, ConstLeftBase,
140 typename H::LeftBase>::Result LeftBase;
141
142 typedef typename Select<isTuple, ElementType,
143 UnitType>::Result UnqualifiedResultType;
144
145 typedef typename Select<isConst, const UnqualifiedResultType,
146 UnqualifiedResultType>::Result ResultType;
147
148 static ResultType& Do(H& obj)
149 {
150 LeftBase& leftBase = obj;
151 return leftBase;
152 }
153 };
154
155 template <class H, unsigned int i>
156 struct FieldHelper
157 {
158 typedef typename TL::TypeAt<typename H::TList, i>::Result ElementType;
159 typedef typename H::Rebind<ElementType>::Result UnitType;
160
161 enum
162 {
163 isTuple = Conversion<UnitType, TupleUnit<ElementType> >::sameType,
164 isConst = TypeTraits<H>::isConst
165 };
166
167 typedef const typename H::RightBase ConstRightBase;
168
169 typedef typename Select<isConst, ConstRightBase,
170 typename H::RightBase>::Result RightBase;
171
172 typedef typename Select<isTuple, ElementType,
173 UnitType>::Result UnqualifiedResultType;
174
175 typedef typename Select<isConst, const UnqualifiedResultType,
176 UnqualifiedResultType>::Result ResultType;
177
178 static ResultType& Do(H& obj)
179 {
180 RightBase& rightBase = obj;
181 return FieldHelper<RightBase, i - 1>::Do(rightBase);
182 }
183 };
184
185 ////////////////////////////////////////////////////////////////////////////////
186 // function template Field
187 // Accesses a field in an object of a type generated with GenScatterHierarchy
188 // Invocation (obj is an object of a type H generated with GenScatterHierarchy,
189 // i is the index of a type in the typelist used to generate H):
190 // Field<i>(obj)
191 // returns a reference to Unit<T>, where Unit is the template used to generate H
192 // and T is the i-th type in the typelist
193 ////////////////////////////////////////////////////////////////////////////////
194
195 template <int i, class H>
196 typename FieldHelper<H, i>::ResultType&
197 Field(H& obj)
198 {
199 return FieldHelper<H, i>::Do(obj);
200 }
201
202 // template <int i, class H>
203 // const typename FieldHelper<H, i>::ResultType&
204 // Field(const H& obj)
205 // {
206 // return FieldHelper<H, i>::Do(obj);
207 // }
208
209 ////////////////////////////////////////////////////////////////////////////////
210 // class template GenLinearHierarchy
211 // Generates a linear hierarchy starting from a typelist and a template
212 // Invocation (TList is a typelist, Model is a template of two args):
213 // GenScatterHierarchy<TList, Model>
214 ////////////////////////////////////////////////////////////////////////////////
215
216 template
217 <
218 class TList,
219 template <class AtomicType, class Base> class Unit,
220 class Root = EmptyType
221 >
222 class GenLinearHierarchy;
223
224 template
225 <
226 class T1,
227 class T2,
228 template <class, class> class Unit,
229 class Root
230 >
231 class GenLinearHierarchy<Typelist<T1, T2>, Unit, Root>
232 : public Unit< T1, GenLinearHierarchy<T2, Unit, Root> >
233 {
234 };
235
236 template
237 <
238 class T,
239 template <class, class> class Unit,
240 class Root
241 >
242 class GenLinearHierarchy<Typelist<T, NullType>, Unit, Root>
243 : public Unit<T, Root>
244 {
245 };
246
247 } // namespace Loki
248
249 ////////////////////////////////////////////////////////////////////////////////
250 // Change log:
251 // June 20, 2001: ported by Nick Thurn to gcc 2.95.3. Kudos, Nick!!!
252 ////////////////////////////////////////////////////////////////////////////////
253
254 #endif // HIERARCHYGENERATORS_INC_