From: Mikko Rasa Date: Mon, 12 Apr 2021 11:36:12 +0000 (+0300) Subject: Add TypeRegistry class X-Git-Url: http://git.tdb.fi/?a=commitdiff_plain;h=47ce9e396aca83fbf90b7130263aaa4c8439af9c;p=libs%2Fcore.git Add TypeRegistry class This is basically a generalization of DataFile::LoadableTypeRegistry, formulated so it isn't associated specifically with Loaders. --- diff --git a/source/core/typeregistry.h b/source/core/typeregistry.h new file mode 100644 index 0000000..2761085 --- /dev/null +++ b/source/core/typeregistry.h @@ -0,0 +1,97 @@ +#ifndef MSP_CORE_TYPEREGISTRY_H_ +#define MSP_CORE_TYPEREGISTRY_H_ + +#include +#include +#include "maputils.h" +#include "noncopyable.h" + +namespace Msp { + +/** +Associates types with keywords for invoking an action. The action must be +a template struct or class with operator() taking two parameters. The first +parameter is the keyword of the type and the second is data passed in to the +invoke function. The type of the data is specified as the second template +parameter to TypeRegistry. Note that the type is used as is; if you want to +pass a reference, it must be explicit in the template argument. +*/ +template class A, typename T> +class TypeRegistry: private NonCopyable +{ +private: + class TypeBase + { + protected: + std::string keyword; + + TypeBase(const std::string &kw): keyword(kw) { } + public: + virtual ~TypeBase() { } + + virtual void invoke(T) const = 0; + }; + + template + class RegisteredType: public TypeBase + { + public: + A action; + + RegisteredType(const std::string &kw): TypeBase(kw) { } + + virtual void invoke(T arg) const { action(this->keyword, arg); } + }; + + typedef std::map TypeMap; + + TypeMap types; + +public: + ~TypeRegistry(); + + /** Registers a type. */ + template + void register_type(const std::string &); + + /** Invokes the action for a specific type, which must have been registered + before. */ + void invoke(const std::string &, T) const; + + /** Invokes the action for all registered types. */ + void invoke_all(T) const; +}; + +template class A, typename T> +TypeRegistry::~TypeRegistry() +{ + for(typename TypeMap::iterator i=types.begin(); i!=types.end(); ++i) + delete i->second; +} + +template class A, typename T> +template +void TypeRegistry::register_type(const std::string &kw) +{ + if(types.count(kw)) + throw key_error(kw); + + types[kw] = new RegisteredType(kw); +} + +template class A, typename T> +void TypeRegistry::invoke(const std::string &kw, T arg) const +{ + get_item(types, kw)->invoke(arg); +} + +template class A, typename T> +void TypeRegistry::invoke_all(T arg) const +{ + for(typename TypeMap::const_iterator i=types.begin(); i!=types.end(); ++i) + i->second->invoke(arg); +} + +} // namespace Msp + +#endif