LDMX Software
Factory.h
1#ifndef SIMCORE_FACTORY_H
2#define SIMCORE_FACTORY_H
3
4#include <algorithm> // for for_each call in apply
5#include <boost/core/demangle.hpp> // for demangling
6#include <memory> // for the unique_ptr default
7#include <string> // for the keys in the library map
8#include <unordered_map> // for the library of prototypes
9
10#include "Framework/Exception/Exception.h"
11
12namespace simcore {
13
195template <typename Prototype, typename PrototypePtr,
196 typename... PrototypeConstructorArgs>
197class Factory {
198 public:
205 using PrototypeMaker = PrototypePtr (*)(PrototypeConstructorArgs...);
206
207 public:
217 static Factory& get() {
218 static Factory the_factory;
219 return the_factory;
220 }
221
240 template <typename DerivedType>
241 uint64_t declare() {
242 std::string full_name{boost::core::demangle(typeid(DerivedType).name())};
243 library_[full_name] = &maker<DerivedType>;
244 return reinterpret_cast<std::uintptr_t>(&library_);
245 }
246
265 PrototypePtr make(const std::string& full_name,
266 PrototypeConstructorArgs... maker_args) {
267 auto lib_it{library_.find(full_name)};
268 if (lib_it == library_.end()) {
269 EXCEPTION_RAISE("SimFactory", "An object named " + full_name +
270 " has not been declared.");
271 }
272 warehouse_.emplace_back(lib_it->second(maker_args...));
273 return warehouse_.back();
274 }
275
282 template <class UnaryFunction>
283 void apply(UnaryFunction f) const {
284 std::for_each(warehouse_.begin(), warehouse_.end(), f);
285 }
286
288 Factory(Factory const&) = delete;
289
291 void operator=(Factory const&) = delete;
292
293 private:
313 template <typename DerivedType>
314 static PrototypePtr maker(PrototypeConstructorArgs... args) {
315 return PrototypePtr(
316 new DerivedType(std::forward<PrototypeConstructorArgs>(args)...));
317 }
318
320 Factory() = default;
321
323 std::unordered_map<std::string, PrototypeMaker> library_;
324
326 std::vector<PrototypePtr> warehouse_;
327}; // Factory
328
329} // namespace simcore
330#endif // SIMCORE_FACTORY_H
Factory to dynamically create objects derived from a specific prototype class.
Definition Factory.h:197
uint64_t declare()
register a new object to be constructible
Definition Factory.h:241
void operator=(Factory const &)=delete
delete the assignment operator
std::vector< PrototypePtr > warehouse_
warehouse of objects that have already been created
Definition Factory.h:326
PrototypePtr(*)(PrototypeConstructorArgs...) PrototypeMaker
the signature of a function that can be used by this factory to dynamically create a new object.
Definition Factory.h:205
void apply(UnaryFunction f) const
Apply the input UnaryFunction to each entry in the inventory.
Definition Factory.h:283
static PrototypePtr maker(PrototypeConstructorArgs... args)
make a new DerivedType returning a PrototypePtr
Definition Factory.h:314
static Factory & get()
get the factory instance
Definition Factory.h:217
Factory(Factory const &)=delete
delete the copy constructor
PrototypePtr make(const std::string &full_name, PrototypeConstructorArgs... maker_args)
make a new object by name
Definition Factory.h:265
Factory()=default
private constructor to prevent creation
std::unordered_map< std::string, PrototypeMaker > library_
library of possible objects to create
Definition Factory.h:323