]> git.tdb.fi Git - libs/core.git/blob - source/core/typeregistry.h
Use C++11 features with containers
[libs/core.git] / source / core / typeregistry.h
1 #ifndef MSP_CORE_TYPEREGISTRY_H_
2 #define MSP_CORE_TYPEREGISTRY_H_
3
4 #include <map>
5 #include <string>
6 #include "maputils.h"
7 #include "noncopyable.h"
8
9 namespace Msp {
10
11 /**
12 Associates types with keywords for invoking an action.  The action must be
13 a template struct or class with operator() taking two parameters.  The first
14 parameter is the keyword of the type and the second is data passed in to the
15 invoke function.  The type of the data is specified as the second template
16 parameter to TypeRegistry.  Note that the type is used as is; if you want to
17 pass a reference, it must be explicit in the template argument.
18 */
19 template<template<typename> class A, typename T>
20 class TypeRegistry: private NonCopyable
21 {
22 private:
23         class TypeBase
24         {
25         protected:
26                 std::string keyword;
27
28                 TypeBase(const std::string &kw): keyword(kw) { }
29         public:
30                 virtual ~TypeBase() { }
31
32                 virtual void invoke(T) const = 0;
33         };
34
35         template<typename R>
36         class RegisteredType: public TypeBase
37         {
38         public:
39                 A<R> action;
40
41                 RegisteredType(const std::string &kw): TypeBase(kw) { }
42
43                 virtual void invoke(T arg) const { action(this->keyword, arg); }
44         };
45
46         std::map<std::string, TypeBase *> types;
47
48 public:
49         ~TypeRegistry();
50
51         /** Registers a type. */
52         template<typename R>
53         void register_type(const std::string &);
54
55         /** Invokes the action for a specific type, which must have been registered
56         before. */
57         void invoke(const std::string &, T) const;
58
59         /** Invokes the action for all registered types. */
60         void invoke_all(T) const;
61 };
62
63 template<template<typename> class A, typename T>
64 TypeRegistry<A, T>::~TypeRegistry()
65 {
66         for(auto &kvp: types)
67                 delete kvp.second;
68 }
69
70 template<template<typename> class A, typename T>
71 template<typename R>
72 void TypeRegistry<A, T>::register_type(const std::string &kw)
73 {
74         if(types.count(kw))
75                 throw key_error(kw);
76
77         types[kw] = new RegisteredType<R>(kw);
78 }
79
80 template<template<typename> class A, typename T>
81 void TypeRegistry<A, T>::invoke(const std::string &kw, T arg) const
82 {
83         get_item(types, kw)->invoke(arg);
84 }
85
86 template<template<typename> class A, typename T>
87 void TypeRegistry<A, T>::invoke_all(T arg) const
88 {
89         for(auto &kvp: types)
90                 kvp.second->invoke(arg);
91 }
92
93 } // namespace Msp
94
95 #endif