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 <optional>
12#include <string>
13#include <unordered_map>
14#include <vector>
15
16namespace framework {
17
176template <typename Prototype, typename PrototypePtr,
177 typename... PrototypeConstructorArgs>
178class Factory {
179 public:
186 using PrototypeMaker = PrototypePtr (*)(PrototypeConstructorArgs...);
187
188 public:
207 template <typename DerivedType>
208 uint64_t declare(const std::string& derived_type_name) {
209 library_[derived_type_name] = &maker<DerivedType>;
210 return reinterpret_cast<std::uintptr_t>(&library_);
211 }
212
230 [[nodiscard]] virtual std::optional<PrototypePtr> make(
231 const std::string& full_name, PrototypeConstructorArgs... maker_args) {
232 auto lib_it{library_.find(full_name)};
233 if (lib_it == library_.end()) {
234 return std::nullopt;
235 }
236 return lib_it->second(maker_args...);
237 }
238
240 Factory(Factory const&) = delete;
241
243 void operator=(Factory const&) = delete;
244
246 Factory() = default;
247
249 virtual ~Factory() = default;
250
251 private:
271 template <typename DerivedType>
272 static PrototypePtr maker(PrototypeConstructorArgs... args) {
273 return PrototypePtr(
274 new DerivedType(std::forward<PrototypeConstructorArgs>(args)...));
275 }
276
278 std::unordered_map<std::string, PrototypeMaker> library_;
279}; // Factory
280
294template <typename Prototype, typename PrototypePtr,
295 typename... PrototypeConstructorArgs>
297 : public Factory<Prototype, PrototypePtr, PrototypeConstructorArgs...> {
298 public:
299 using FactoryNoWarehouse =
300 Factory<Prototype, PrototypePtr, PrototypeConstructorArgs...>;
301
320 [[nodiscard]] std::optional<PrototypePtr> make(
321 const std::string& full_name,
322 PrototypeConstructorArgs... maker_args) override {
323 auto obj{FactoryNoWarehouse::make(full_name, maker_args...)};
324 if (obj) {
325 warehouse_.emplace_back(obj.value());
326 }
327 return obj;
328 }
329
340 template <class UnaryFunction>
341 void apply(UnaryFunction f) const {
342 std::for_each(warehouse_.begin(), warehouse_.end(), f);
343 }
344
347
349 void operator=(FactoryWithWarehouse const&) = delete;
350
353
354 private:
356 std::vector<PrototypePtr> warehouse_;
357}; // FactoryWithWarehouse
358
359} // namespace framework
360
374#define DECLARE_FACTORY(...) \
375 struct Factory : public ::framework::Factory<__VA_ARGS__> { \
376 static Factory& get(); \
377 }
378
392#define DECLARE_FACTORY_WITH_WAREHOUSE(...) \
393 struct Factory : public ::framework::FactoryWithWarehouse<__VA_ARGS__> { \
394 static Factory& get(); \
395 }
396
408#define DEFINE_FACTORY(classtype) \
409 classtype::Factory& classtype::Factory::get() { \
410 static classtype::Factory the_factory; \
411 return the_factory; \
412 }
413
422#define _CONCAT_INTERNAL(a, b) a##b
423
432#define _CONCAT(a, b) _CONCAT_INTERNAL(a, b)
433
441#define UNIQUE(a) _CONCAT(a, __COUNTER__)
442
466#define FACTORY_REGISTRATION(prototype, derived) \
467 namespace { \
468 auto UNIQUE(v) = ::prototype::Factory::get().declare<::derived>(#derived); \
469 }
470
471#endif
A Factory with a warehouse to hold created objects.
Definition Factory.h:297
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:341
std::optional< PrototypePtr > make(const std::string &full_name, PrototypeConstructorArgs... maker_args) override
make a new object by name
Definition Factory.h:320
std::vector< PrototypePtr > warehouse_
warehouse of objects that have already been created
Definition Factory.h:356
Factory to dynamically create objects derived from a specific prototype class.
Definition Factory.h:178
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:186
Factory(Factory const &)=delete
delete the copy constructor
std::unordered_map< std::string, PrototypeMaker > library_
library of possible objects to create
Definition Factory.h:278
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:208
virtual std::optional< PrototypePtr > make(const std::string &full_name, PrototypeConstructorArgs... maker_args)
make a new object by name
Definition Factory.h:230
static PrototypePtr maker(PrototypeConstructorArgs... args)
make a new DerivedType returning a PrototypePtr
Definition Factory.h:272
Factory()=default
default constructor that does nothing
All classes in the ldmx-sw project use this namespace.