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
////////////////////////////////////////////////////////////////////////////////
16
#ifndef LOKI_HIERARCHYGENERATORS_INC_
17
#define LOKI_HIERARCHYGENERATORS_INC_
19
// $Header: /cvsroot/loki-lib/loki/include/loki/HierarchyGenerators.h,v 1.5 2006/01/16 19:05:09 rich_sposato Exp $
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
////////////////////////////////////////////////////////////////////////////////
131
operator T&() { return value_; }
132
operator const T&() const { return value_; }
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
////////////////////////////////////////////////////////////////////////////////
141
template <class TList>
142
struct Tuple : public GenScatterHierarchy<TList, TupleUnit>
146
////////////////////////////////////////////////////////////////////////////////
147
// helper class template FieldHelper
149
////////////////////////////////////////////////////////////////////////////////
151
template <class H, unsigned int i> struct FieldHelper;
154
struct FieldHelper<H, 0>
156
typedef typename H::TList::Head ElementType;
157
typedef typename H::template Rebind<ElementType>::Result UnitType;
161
isTuple = Conversion<UnitType, TupleUnit<ElementType> >::sameType,
162
isConst = TypeTraits<H>::isConst
165
typedef const typename H::LeftBase ConstLeftBase;
167
typedef typename Select<isConst, ConstLeftBase,
168
typename H::LeftBase>::Result LeftBase;
170
typedef typename Select<isTuple, ElementType,
171
UnitType>::Result UnqualifiedResultType;
173
typedef typename Select<isConst, const UnqualifiedResultType,
174
UnqualifiedResultType>::Result ResultType;
176
static ResultType& Do(H& obj)
178
LeftBase& leftBase = obj;
183
template <class H, unsigned int i>
186
typedef typename TL::TypeAt<typename H::TList, i>::Result ElementType;
187
typedef typename H::template Rebind<ElementType>::Result UnitType;
191
isTuple = Conversion<UnitType, TupleUnit<ElementType> >::sameType,
192
isConst = TypeTraits<H>::isConst
195
typedef const typename H::RightBase ConstRightBase;
197
typedef typename Select<isConst, ConstRightBase,
198
typename H::RightBase>::Result RightBase;
200
typedef typename Select<isTuple, ElementType,
201
UnitType>::Result UnqualifiedResultType;
203
typedef typename Select<isConst, const UnqualifiedResultType,
204
UnqualifiedResultType>::Result ResultType;
206
static ResultType& Do(H& obj)
208
RightBase& rightBase = obj;
209
return FieldHelper<RightBase, i - 1>::Do(rightBase);
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):
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
////////////////////////////////////////////////////////////////////////////////
223
template <int i, class H>
224
typename FieldHelper<H, i>::ResultType&
227
return FieldHelper<H, i>::Do(obj);
230
// template <int i, class H>
231
// const typename FieldHelper<H, i>::ResultType&
232
// Field(const H& obj)
234
// return FieldHelper<H, i>::Do(obj);
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
////////////////////////////////////////////////////////////////////////////////
247
template <class AtomicType, class Base> class Unit,
248
class Root = EmptyType
250
class GenLinearHierarchy;
256
template <class, class> class Unit,
259
class GenLinearHierarchy<Typelist<T1, T2>, Unit, Root>
260
: public Unit< T1, GenLinearHierarchy<T2, Unit, Root> >
267
template <class, class> class Unit,
270
class GenLinearHierarchy<Typelist<T, NullType>, Unit, Root>
271
: public Unit<T, Root>
277
template <class, class> class Unit,
280
class GenLinearHierarchy<NullType , Unit, Root>
281
: public Root // is this better: Unit<NullType, Root> ?
285
#if defined(_MSC_VER) && _MSC_VER >= 1300
286
#pragma warning( pop )
290
////////////////////////////////////////////////////////////////////////////////
292
// June 20, 2001: ported by Nick Thurn to gcc 2.95.3. Kudos, Nick!!!
293
// September 16, 2002: Fixed dependent template, using "::template" syntax. T.S.
296
////////////////////////////////////////////////////////////////////////////////
298
#endif // HIERARCHYGENERATORS_INC_
300
// $Log: HierarchyGenerators.h,v $
301
// Revision 1.5 2006/01/16 19:05:09 rich_sposato
302
// Added cvs keywords.