LDMX Software
Factory.h
Go to the documentation of this file.
1
6#ifndef FRAMEWORK_FACTORY_H
7#define FRAMEWORK_FACTORY_H
8
9#include <algorithm>
10#include <cstdint>
11#include <memory>
12#include <optional>
13#include <string>
14#include <unordered_map>
15#include <vector>
16
17#include "Framework/Exception/Exception.h"
18
19namespace framework {
20
179template <typename Prototype, typename PrototypePtr,
180 typename... PrototypeConstructorArgs>
181class Factory {
182 public:
189 using PrototypeMaker = PrototypePtr (*)(PrototypeConstructorArgs...);
190
191 public:
210 template <typename DerivedType>
211 uint64_t declare(const std::string& derived_type_name) {
212 library_[derived_type_name] = &maker<DerivedType>;
213 return reinterpret_cast<std::uintptr_t>(&library_);
214 }
215
233 [[nodiscard]] virtual std::optional<PrototypePtr> make(
234 const std::string& full_name, PrototypeConstructorArgs... maker_args) {
235 auto lib_it{library_.find(full_name)};
236 if (lib_it == library_.end()) {
237 return std::nullopt;
238 }
239 return lib_it->second(maker_args...);
240 }
241
243 Factory(Factory const&) = delete;
244
246 void operator=(Factory const&) = delete;
247
249 Factory() = default;
250
252 virtual ~Factory() = default;
253
254 private:
274 template <typename DerivedType>
275 static PrototypePtr maker(PrototypeConstructorArgs... args) {
276 return PrototypePtr(
277 new DerivedType(std::forward<PrototypeConstructorArgs>(args)...));
278 }
279
281 std::unordered_map<std::string, PrototypeMaker> library_;
282}; // Factory
283
297template <typename Prototype, typename PrototypePtr,
298 typename... PrototypeConstructorArgs>
300 : public Factory<Prototype, PrototypePtr, PrototypeConstructorArgs...> {
301 public:
302 using FactoryNoWarehouse =
303 Factory<Prototype, PrototypePtr, PrototypeConstructorArgs...>;
304
323 [[nodiscard]] std::optional<PrototypePtr> make(
324 const std::string& full_name,
325 PrototypeConstructorArgs... maker_args) override {
326 auto obj{FactoryNoWarehouse::make(full_name, maker_args...)};
327 if (obj) {
328 warehouse_.emplace_back(obj.value());
329 }
330 return obj;
331 }
332
343 template <class UnaryFunction>
344 void apply(UnaryFunction f) const {
345 std::for_each(warehouse_.begin(), warehouse_.end(), f);
346 }
347
350
352 void operator=(FactoryWithWarehouse const&) = delete;
353
356
357 private:
359 std::vector<PrototypePtr> warehouse_;
360}; // FactoryWithWarehouse
361
362} // namespace framework
363
377#define DECLARE_FACTORY(...) \
378 struct Factory : public ::framework::Factory<__VA_ARGS__> { \
379 static Factory& get(); \
380 }
381
395#define DECLARE_FACTORY_WITH_WAREHOUSE(...) \
396 struct Factory : public ::framework::FactoryWithWarehouse<__VA_ARGS__> { \
397 static Factory& get(); \
398 }
399
411#define DEFINE_FACTORY(classtype) \
412 classtype::Factory& classtype::Factory::get() { \
413 static classtype::Factory the_factory; \
414 return the_factory; \
415 }
416
425#define _CONCAT_INTERNAL(a, b) a##b
426
435#define _CONCAT(a, b) _CONCAT_INTERNAL(a, b)
436
444#define UNIQUE(a) _CONCAT(a, __COUNTER__)
445
469#define FACTORY_REGISTRATION(prototype, derived) \
470 namespace { \
471 auto UNIQUE(v) = ::prototype::Factory::get().declare<::derived>(#derived); \
472 }
473
474#endif
A Factory with a warehouse to hold created objects.
Definition Factory.h:300
FactoryWithWarehouse(FactoryWithWarehouse const &)=delete
delete the copy constructor
FactoryWithWarehouse()=default
default constructor that does nothing
void operator=(FactoryWithWarehouse const &)=delete
delete the assignment operator
void apply(UnaryFunction f) const
Apply the input UnaryFunction to each entry in the warehouse.
Definition Factory.h:344
std::optional< PrototypePtr > make(const std::string &full_name, PrototypeConstructorArgs... maker_args) override
make a new object by name
Definition Factory.h:323
std::vector< PrototypePtr > warehouse_
warehouse of objects that have already been created
Definition Factory.h:359
Factory to dynamically create objects derived from a specific prototype class.
Definition Factory.h:181
void operator=(Factory const &)=delete
delete the assignment operator
PrototypePtr(*)(PrototypeConstructorArgs...) PrototypeMaker
the signature of a function that can be used by this factory to dynamically create a new object.
Definition Factory.h:189
Factory(Factory const &)=delete
delete the copy constructor
std::unordered_map< std::string, PrototypeMaker > library_
library of possible objects to create
Definition Factory.h:281
virtual ~Factory()=default
default destructor that is virtual for Warehouse override
uint64_t declare(const std::string &derived_type_name)
register a new object to be constructible
Definition Factory.h:211
virtual std::optional< PrototypePtr > make(const std::string &full_name, PrototypeConstructorArgs... maker_args)
make a new object by name
Definition Factory.h:233
static PrototypePtr maker(PrototypeConstructorArgs... args)
make a new DerivedType returning a PrototypePtr
Definition Factory.h:275
Factory()=default
default constructor that does nothing
All classes in the ldmx-sw project use this namespace.