-
Notifications
You must be signed in to change notification settings - Fork 2
/
factory.h
96 lines (82 loc) · 2.2 KB
/
factory.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
/*
@copyright Russell Standish 2000-2013
@author Russell Standish
This file is part of Classdesc
Open source licensed under the MIT license. See LICENSE for details.
*/
#ifndef CLASSDESC_FACTORY_H
#define CLASSDESC_FACTORY_H
#include "classdesc.h"
#include <sstream>
namespace classdesc
{
/// factory template for a class heirarchy. \a B is the base class,
/// and \a Type is the type class
template <class B, class Type>
class Factory
{
struct CreatorBase
{
virtual ~CreatorBase() {}
virtual B* create() const=0;
};
typedef std::map<Type, shared_ptr<CreatorBase> > Fmap;
Fmap fmap;
template <class T>
struct Creator: public CreatorBase
{
B* create() const {return new T();}
};
public:
/// register type T for use with this factory
template <class T>
void registerType(const Type& t)
{
fmap.insert
(make_pair(t, shared_ptr<CreatorBase>(new Creator<T>)));
}
/// convenience method for registering a type.
template <class T> void registerType()
{registerType<T>(T().type());}
/**
Users of this template must define a constructor that registers
all the types in the heirarchy.
For example, assuming Foo and Bar are subtypes of FooBase:
template <> Factory<Foobase>::Factory()
{
registerType<Foo>();
registerType<Bar>();
};
*/
Factory();
struct InvalidType: public exception
{
string s;
InvalidType(const Type& t) {
std::ostringstream os;
os<<"invalid type "<<t;
s=os.str();
}
const char* what() const throw() {return s.c_str();}
~InvalidType() throw() {}
};
/// Create a default constructed object given by the type string
B* create(const Type& t) const
{
typename Fmap::const_iterator i=fmap.find(t);
if (i==fmap.end())
throw InvalidType(t);
else
return i->second->create();
}
/// return list of registered types
std::vector<string> types() const
{
std::vector<string> r;
for (typename Fmap::const_iterator i=fmap.begin(); i!=fmap.end(); ++i)
r.push_back(i->first);
return r;
}
};
}
#endif