]> git.cworth.org Git - vogl/blob - src/extlib/loki/include/loki/AbstractFactory.h
Initial vogl checkin
[vogl] / src / extlib / loki / include / loki / AbstractFactory.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_ABSTRACTFACTORY_INC_
16 #define LOKI_ABSTRACTFACTORY_INC_
17
18 // $Id: AbstractFactory.h 771 2006-10-27 18:05:03Z clitte_bbt $
19
20
21 #include "Typelist.h"
22 #include "Sequence.h"
23 #include "TypeManip.h"
24 #include "HierarchyGenerators.h"
25
26 #include <cassert>
27
28 /**
29  * \defgroup    FactoriesGroup Factories
30  * \defgroup    AbstractFactoryGroup Abstract Factory
31  * \ingroup             FactoriesGroup
32  * \brief               Implements an abstract object factory.
33  */
34
35 /**
36  * \class               AbstractFactory
37  * \ingroup             AbstractFactoryGroup
38  * \brief               Implements an abstract object factory.
39  */
40
41 namespace Loki
42 {
43
44 ////////////////////////////////////////////////////////////////////////////////
45 // class template AbstractFactoryUnit
46 // The building block of an Abstract Factory
47 ////////////////////////////////////////////////////////////////////////////////
48
49 template <class T>
50 class AbstractFactoryUnit
51 {
52 public:
53         virtual T *DoCreate(Type2Type<T>) = 0;
54         virtual ~AbstractFactoryUnit() {}
55 };
56
57 ////////////////////////////////////////////////////////////////////////////////
58 // class template AbstractFactory
59 // Defines an Abstract Factory interface starting from a typelist
60 ////////////////////////////////////////////////////////////////////////////////
61
62 template
63 <
64 class TList,
65       template <class> class Unit = AbstractFactoryUnit
66       >
67 class AbstractFactory : public GenScatterHierarchy<TList, Unit>
68 {
69 public:
70         typedef TList ProductList;
71
72         template <class T> T *Create()
73         {
74                 Unit<T>& unit = *this;
75                 return unit.DoCreate(Type2Type<T>());
76         }
77 };
78
79 ////////////////////////////////////////////////////////////////////////////////
80 // class template OpNewFactoryUnit
81 // Creates an object by invoking the new operator
82 ////////////////////////////////////////////////////////////////////////////////
83
84 template <class ConcreteProduct, class Base>
85 class OpNewFactoryUnit : public Base
86 {
87         typedef typename Base::ProductList BaseProductList;
88
89 protected:
90         typedef typename BaseProductList::Tail ProductList;
91
92 public:
93         typedef typename BaseProductList::Head AbstractProduct;
94         ConcreteProduct *DoCreate(Type2Type<AbstractProduct>)
95         {
96                 return new ConcreteProduct;
97         }
98 };
99
100 ////////////////////////////////////////////////////////////////////////////////
101 // class template PrototypeFactoryUnit
102 // Creates an object by cloning a prototype
103 // There is a difference between the implementation herein and the one described
104 //     in the book: GetPrototype and SetPrototype use the helper friend
105 //     functions DoGetPrototype and DoSetPrototype. The friend functions avoid
106 //     name hiding issues. Plus, GetPrototype takes a reference to pointer
107 //     instead of returning the pointer by value.
108 ////////////////////////////////////////////////////////////////////////////////
109
110 template <class ConcreteProduct, class Base>
111 class PrototypeFactoryUnit : public Base
112 {
113         typedef typename Base::ProductList BaseProductList;
114
115 protected:
116         typedef typename BaseProductList::Tail ProductList;
117
118 public:
119         typedef typename BaseProductList::Head AbstractProduct;
120
121         PrototypeFactoryUnit(AbstractProduct *p = 0)
122                 : pPrototype_(p)
123         {}
124
125         template <class CP, class Base1>
126         friend void DoGetPrototype(const PrototypeFactoryUnit<CP, Base1>& me,
127                                    typename Base1::ProductList::Head*& pPrototype);
128
129         template <class CP, class Base1>
130         friend void DoSetPrototype(PrototypeFactoryUnit<CP, Base1>& me,
131                                    typename Base1::ProductList::Head *pObj);
132
133         template <class U>
134         void GetPrototype(U*& p)
135         {
136                 return DoGetPrototype(*this, p);
137         }
138
139         template <class U>
140         void SetPrototype(U *pObj)
141         {
142                 DoSetPrototype(*this, pObj);
143         }
144
145         AbstractProduct *DoCreate(Type2Type<AbstractProduct>)
146         {
147                 assert(pPrototype_);
148                 return pPrototype_->Clone();
149         }
150
151 private:
152         AbstractProduct *pPrototype_;
153 };
154
155 template <class CP, class Base>
156 inline void DoGetPrototype(const PrototypeFactoryUnit<CP, Base>& me,
157                            typename Base::ProductList::Head*& pPrototype)
158 {
159         pPrototype = me.pPrototype_;
160 }
161
162 template <class CP, class Base>
163 inline void DoSetPrototype(PrototypeFactoryUnit<CP, Base>& me,
164                            typename Base::ProductList::Head *pObj)
165 {
166         me.pPrototype_ = pObj;
167 }
168
169 ////////////////////////////////////////////////////////////////////////////////
170 // class template ConcreteFactory
171 // Implements an AbstractFactory interface
172 ////////////////////////////////////////////////////////////////////////////////
173
174 template
175 <
176 class AbstractFact,
177       template <class, class> class Creator = OpNewFactoryUnit,
178       class TList = typename AbstractFact::ProductList
179       >
180 class ConcreteFactory
181         : public GenLinearHierarchy<
182         typename TL::Reverse<TList>::Result, Creator, AbstractFact>
183 {
184 public:
185         typedef typename AbstractFact::ProductList ProductList;
186         typedef TList ConcreteProductList;
187 };
188
189 } // namespace Loki
190
191
192 #endif // end file guardian
193