DIY  2.0
data-parallel out-of-core C++ library
factory.hpp
1 template<class Interface, typename KeyT = int>
2 struct Factory
3 {
4  public:
5  typedef KeyT Key;
6  typedef Interface* Type;
7  typedef Type (*Creator)();
8 
9  bool define(Key const& key, Creator v) { return _registry.insert(typename Registry::value_type(key, v)).second; }
10  Type create(Key const& key)
11  {
12  typename Registry::const_iterator i = _registry.find(key);
13  if (i == _registry.end())
14  throw std::invalid_argument(std::string(__PRETTY_FUNCTION__) + ": key not registered");
15  else
16  return i->second();
17  }
18 
19  template<class Base, class Actual>
20  static
21  Base* create_func() { return new Actual; }
22 
23  private:
24  typedef std::map<Key, Creator> Registry;
25  Registry _registry;
26 };
27 
28 struct Base
29 {
30  public:
31  typedef ::Factory<Base> Factory;
32  virtual ~Base() {}
33  virtual int answer() const = 0;
34 
35  static
36  Factory::Type create(Factory::Key const& name) { return _factory.create(name); }
37 
38  template<class Derived>
39  static void define(Factory::Key const& name)
40  {
41  bool new_key = _factory.define(name, &Factory::template create_func<Base, Derived>);
42  if (not new_key)
43  throw std::logic_error(std::string(__PRETTY_FUNCTION__) + ": name already registered");
44  }
45 
46  private:
47  static Factory _factory;
48 };
49 Base::Factory Base::_factory;
50 
51 struct A: Base
52 {
53  virtual int answer() const { return 42; }
54 };
55 
56 int main()
57 {
58  Base::define<A>("A");
59  assert(Base::create("A")->answer() == 42);
60  return 0;
61 }
Definition: factory.hpp:2
Definition: factory.hpp:51
Definition: factory.hpp:28