mirror of
https://github.com/scylladb/scylladb.git
synced 2026-04-21 17:10:35 +00:00
In Java it is possible to create an object by knowing its class name in runtime. Replication strategies are created this way (I presume class name comes from configuration somehow), so when I translated the code to urchin I wrote replication_strategy_registry class to map a class name to a factory function. Now I see that this is used in other places too (I see that snitch class created in the same way), so instead of repeating the same code for each class hierarchy that is created from its name in origin this patch tries to introduce an infrastructure to do that easily. Signed-off-by: Avi Kivity <avi@cloudius-systems.com>
56 lines
2.0 KiB
C++
56 lines
2.0 KiB
C++
/*
|
|
* Copyright (C) 2015 Cloudius Systems, Ltd.
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
// BaseType is a base type of a type hierarchy that this registry will hold
|
|
// Args... are parameters for object's constructor
|
|
template<typename BaseType, typename... Args>
|
|
class class_registry {
|
|
using creator_type = std::function<std::unique_ptr<BaseType>(Args...)>;
|
|
static std::unordered_map<sstring, creator_type> _classes;
|
|
public:
|
|
static void register_class(sstring name, creator_type creator);
|
|
template<typename T>
|
|
static void register_class(sstring name);
|
|
static std::unique_ptr<BaseType> create(const sstring& name, Args...);
|
|
};
|
|
|
|
template<typename BaseType, typename... Args>
|
|
std::unordered_map<sstring, typename class_registry<BaseType, Args...>::creator_type> class_registry<BaseType, Args...>::_classes;
|
|
|
|
template<typename BaseType, typename... Args>
|
|
void class_registry<BaseType, Args...>::register_class(sstring name, class_registry<BaseType, Args...>::creator_type creator) {
|
|
_classes.emplace(name, std::move(creator));
|
|
}
|
|
|
|
template<typename BaseType, typename... Args>
|
|
template<typename T>
|
|
void class_registry<BaseType, Args...>::register_class(sstring name) {
|
|
register_class(name, [](Args&&... args) {
|
|
return std::make_unique<T>(std::forward<Args>(args)...);
|
|
});
|
|
}
|
|
|
|
template<typename BaseType, typename T, typename... Args>
|
|
struct class_registrator {
|
|
class_registrator(const sstring& name) {
|
|
class_registry<BaseType, Args...>::template register_class<T>(name);
|
|
}
|
|
class_registrator(const sstring& name, std::function<std::unique_ptr<T>(Args...)> creator) {
|
|
class_registry<BaseType, Args...>::register_class(name, creator);
|
|
}
|
|
};
|
|
|
|
template<typename BaseType, typename... Args>
|
|
std::unique_ptr<BaseType> class_registry<BaseType, Args...>::create(const sstring& name, Args... args) {
|
|
return _classes[name](args...);
|
|
}
|
|
|
|
template<typename BaseType, typename... Args>
|
|
std::unique_ptr<BaseType> create_object(const sstring& name, Args&&... args) {
|
|
return class_registry<BaseType, Args...>::create(name, std::forward<Args>(args)...);
|
|
}
|
|
|