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: June 20, 2001
17
18 #ifndef FACTORY_INC_
19 #define FACTORY_INC_
20
21 #include "TypeInfo.h"
22 #include "AssocVector.h"
23 #include <exception>
24
25 namespace Loki
26 {
27
28 ////////////////////////////////////////////////////////////////////////////////
29 // class template DefaultFactoryError
30 // Manages the "Unknown Type" error in an object factory
31 ////////////////////////////////////////////////////////////////////////////////
32
33 template <typename IdentifierType, class AbstractProduct>
34 struct DefaultFactoryError
35 {
36 struct Exception : public std::exception
37 {
38 const char* what() const { return "Unknown Type"; }
39 };
40
41 static AbstractProduct* OnUnknownType(IdentifierType)
42 {
43 throw Exception();
44 }
45 };
46
47 ////////////////////////////////////////////////////////////////////////////////
48 // class template Factory
49 // Implements a generic object factory
50 ////////////////////////////////////////////////////////////////////////////////
51
52 template
53 <
54 class AbstractProduct,
55 typename IdentifierType,
56 typename ProductCreator = AbstractProduct* (*)(),
57 template<typename, class>
58 class FactoryErrorPolicy = DefaultFactoryError
59 >
60 class Factory
61 : public FactoryErrorPolicy<IdentifierType, AbstractProduct>
62 {
63 public:
64 bool Register(const IdentifierType& id, ProductCreator creator)
65 {
66 return associations_.insert(
67 IdToProductMap::value_type(id, creator)).second;
68 }
69
70 bool Unregister(const IdentifierType& id)
71 {
72 return associations_.erase(id) == 1;
73 }
74
75 AbstractProduct* CreateObject(const IdentifierType& id)
76 {
77 typename IdToProductMap::const_iterator i = associations_.find(id);
78 if (i != associations_.end())
79 {
80 return (i->second)();
81 }
82 return OnUnknownType(id);
83 }
84
85 private:
86 typedef AssocVector<IdentifierType, ProductCreator> IdToProductMap;
87 IdToProductMap associations_;
88 };
89
90 ////////////////////////////////////////////////////////////////////////////////
91 // class template CloneFactory
92 // Implements a generic cloning factory
93 ////////////////////////////////////////////////////////////////////////////////
94
95 template
96 <
97 class AbstractProduct,
98 class ProductCreator =
99 AbstractProduct* (*)(const AbstractProduct*),
100 template<typename, class>
101 class FactoryErrorPolicy = DefaultFactoryError
102 >
103 class CloneFactory
104 : public FactoryErrorPolicy<TypeInfo, AbstractProduct>
105 {
106 public:
107 bool Register(const TypeInfo& ti, ProductCreator creator)
108 {
109 return associations_.insert(
110 IdToProductMap::value_type(ti, creator)).second;
111 }
112
113 bool Unregister(const TypeInfo& id)
114 {
115 return associations_.erase(id) == 1;
116 }
117
118 AbstractProduct* CreateObject(const AbstractProduct* model)
119 {
120 if (model == 0) return 0;
121
122 typename IdToProductMap::const_iterator i =
123 associations_.find(typeid(*model));
124 if (i != associations_.end())
125 {
126 return (i->second)(model);
127 }
128 return OnUnknownType(typeid(*model));
129 }
130
131 private:
132 typedef AssocVector<TypeInfo, ProductCreator> IdToProductMap;
133 IdToProductMap associations_;
134 };
135 } // namespace Loki
136
137 ////////////////////////////////////////////////////////////////////////////////
138 // Change log:
139 // June 20, 2001: ported by Nick Thurn to gcc 2.95.3. Kudos, Nick!!!
140 ////////////////////////////////////////////////////////////////////////////////
141
142 #endif // FACTORY_INC_