16#ifndef GMP_DP_OBJECT_FACTORY_HPP_
17#define GMP_DP_OBJECT_FACTORY_HPP_
29#if GMP_CPP_AT_LEAST(20)
72#if GMP_CPP_AT_LEAST(20)
73 requires std::derived_from<T, AbstractProduct>
83 this_type::instance().map_.emplace(key,
97 this_type::instance().map_.erase(key);
104 return this_type::instance().map_.find(key) != this_type::instance().map_.end();
111 std::vector<std::string> keys;
112 keys.reserve(this_type::instance().map_.size());
113 for (
const auto&
entry : this_type::instance().map_) {
114 keys.push_back(
entry.first);
138 throw std::invalid_argument(
"Unknown object type passed to factory!");
154 return std::shared_ptr<AbstractProduct>(
create(key,
args...));
168 return std::unique_ptr<AbstractProduct>(
create(key,
args...));
176 const auto& map = this_type::instance().map_;
177 const auto found = map.find(key);
178 if (
found == map.end()) {
181 return std::unique_ptr<AbstractProduct>(
found->second(
args...));
196#define _GMP_GET_CONCRETE_PRODUCT_CLASS(ConcreteProduct) GMP_IF_THEN_ELSE(GMP_IS_TUPLE(ConcreteProduct), GMP_TUPLE_GET, ConcreteProduct)GMP_IF(GMP_IS_TUPLE(ConcreteProduct), (1, ConcreteProduct))
197#define _GMP_GET_CONSTRUCTOR_TYPES(ConstructorArgs) GMP_IF_THEN_ELSE(GMP_IS_TUPLE(ConstructorArgs), GMP_REMOVE_PARENS, ConstructorArgs)GMP_IF(GMP_IS_TUPLE(ConstructorArgs), (ConstructorArgs))
198#define GMP_FACTORY_REGISTER_WITH_ARGS(AbstractProduct, ConstructorArgs, ConcreteProduct) \
199 static gmp::object_factory<AbstractProduct, _GMP_GET_CONSTRUCTOR_TYPES(ConstructorArgs)>::register_type<_GMP_GET_CONCRETE_PRODUCT_CLASS(ConcreteProduct)> \
200 GMP_CONCAT(gmp_reg_, __COUNTER__)(GMP_IF_THEN_ELSE(GMP_IS_TUPLE(ConcreteProduct), GMP_TUPLE_GET(0, ConcreteProduct), GMP_STRINGIFY(ConcreteProduct)));
201#define GMP_FACTORY_REGISTER_NO_ARGS(AbstractProduct, ConcreteProduct) \
202 static gmp::object_factory<AbstractProduct>::register_type<_GMP_GET_CONCRETE_PRODUCT_CLASS(ConcreteProduct)> \
203 GMP_CONCAT(gmp_reg_, __COUNTER__)(GMP_IF_THEN_ELSE(GMP_IS_TUPLE(ConcreteProduct), GMP_TUPLE_GET(0, ConcreteProduct), GMP_STRINGIFY(ConcreteProduct)));
227#define GMP_FACTORY_REGISTER(AbstractProduct, ConstructorArgs, ...) \
228 GMP_EVAL( _GMP_FACTORY_REGISTER_IMPL(AbstractProduct, ConstructorArgs, __VA_ARGS__) )
229#define _GMP_FACTORY_REGISTER_IMPL(AbstractProduct, ConstructorArgs, ...) \
230 _GMP_FACTORY_REGISTER_IMPL_COMPAT_MSVC(AbstractProduct, ConstructorArgs, GMP_IS_EMPTY(__VA_ARGS__), GMP_TUPLE_EMPTY(ConstructorArgs), __VA_ARGS__)
231#if GMP_STANDARD_PREPROCESSOR
232#define _GMP_FACTORY_REGISTER_IMPL_COMPAT_MSVC(AbstractProduct, ConstructorArgs, _0, _1, ...) \
233 GMP_OVERLOAD_INVOKE(_GMP_FACTORY_REGISTER_WHEN, _0, _1)(AbstractProduct, ConstructorArgs, __VA_ARGS__)
235#define _GMP_FACTORY_REGISTER_IMPL_COMPAT_MSVC(AbstractProduct, ConstructorArgs, _0, _1, ...) \
236 GMP_EXPAND( GMP_OVERLOAD_INVOKE(_GMP_FACTORY_REGISTER_WHEN, _0, _1)(AbstractProduct, ConstructorArgs, __VA_ARGS__) )
238#define _GMP_FACTORY_REGISTER_WHEN_1(...)
239#define _GMP_FACTORY_REGISTER_WHEN_0_1(AbstractProduct, ConstructorArgs, ConcreteProduct, ...) \
240 GMP_FACTORY_REGISTER_NO_ARGS(AbstractProduct, ConcreteProduct) \
241 GMP_IF(GMP_BOOL(GMP_SIZE_OF_VAARGS(__VA_ARGS__)), _GMP_FACTORY_REGISTER_WHEN_1_CONTINUE) GMP_IF(GMP_BOOL(GMP_SIZE_OF_VAARGS(__VA_ARGS__)), (AbstractProduct, ConstructorArgs, __VA_ARGS__))
242#define _GMP_FACTORY_REGISTER_WHEN_0_0(AbstractProduct, ConstructorArgs, ConcreteProduct, ...) \
243 GMP_FACTORY_REGISTER_WITH_ARGS(AbstractProduct, ConstructorArgs, ConcreteProduct) \
244 GMP_IF(GMP_BOOL(GMP_SIZE_OF_VAARGS(__VA_ARGS__)), _GMP_FACTORY_REGISTER_WHEN_1_CONTINUE) GMP_IF(GMP_BOOL(GMP_SIZE_OF_VAARGS(__VA_ARGS__)), (AbstractProduct, ConstructorArgs, __VA_ARGS__))
245#define _GMP_FACTORY_REGISTER_WHEN_1_CONTINUE(AbstractProduct, ConstructorArgs, ...) \
246 GMP_DEFER(_GMP_FACTORY_REGISTER_INDIRECT)()(AbstractProduct, ConstructorArgs, __VA_ARGS__)
247#define _GMP_FACTORY_REGISTER_INDIRECT() _GMP_FACTORY_REGISTER_IMPL
A singleton-backed runtime factory that creates products by string key.
void unregister_type(const std::string &key)
Remove a previously registered product key from the factory.
std::shared_ptr< AbstractProduct > try_create_shared(const std::string &key, const ConstructorArgs &... args) const
Try to create a shared product, returning an empty pointer for an unknown key.
AbstractProduct * create(const std::string &key, const ConstructorArgs &... args) const
Create a concrete product with raw new semantics.
std::unique_ptr< AbstractProduct > create_unique(const std::string &key, const ConstructorArgs &... args) const
Create a concrete product and return it as std::unique_ptr.
std::unique_ptr< AbstractProduct > try_create_unique(const std::string &key, const ConstructorArgs &... args) const
Try to create a product, returning an empty pointer for an unknown key.
bool contains(const std::string &key) const
Test whether a product key is registered.
std::shared_ptr< AbstractProduct > create_shared(const std::string &key, const ConstructorArgs &... args) const
Create a concrete product and return it as std::shared_ptr.
std::vector< std::string > registered_keys() const
Return all registered product keys.
CRTP-based singleton helper with optional dead-reference recovery.
Register a concrete product type under a string key.
register_type(const std::string &key)
Register T with the specified lookup key.