Icarus
Vehicle Simulation as a Transformable Computational Graph, built on Vulcan and Janus
Loading...
Searching...
No Matches
ComponentFactory.hpp
Go to the documentation of this file.
1#pragma once
2
13
16#include <icarus/core/Error.hpp>
17
18#include <janus/core/JanusTypes.hpp>
19
20#include <functional>
21#include <memory>
22#include <string>
23#include <unordered_map>
24#include <vector>
25
26namespace icarus {
27
44template <typename Scalar> class ComponentFactory {
45 public:
47 using Creator = std::function<std::unique_ptr<Component<Scalar>>(const ComponentConfig &)>;
48
55 void Register(const std::string &type_name, Creator creator) {
56 creators_[type_name] = std::move(creator);
57 }
58
73 [[nodiscard]] std::unique_ptr<Component<Scalar>> Create(const ComponentConfig &config) {
74 auto it = creators_.find(config.type);
75 if (it == creators_.end()) {
76 throw ConfigError("Unknown component type: '" + config.type +
77 "'. Registered types: " + ListTypesString());
78 }
79 return it->second(config);
80 }
81
85 [[nodiscard]] bool HasType(const std::string &type_name) const {
86 return creators_.count(type_name) > 0;
87 }
88
92 [[nodiscard]] std::vector<std::string> GetRegisteredTypes() const {
93 std::vector<std::string> types;
94 types.reserve(creators_.size());
95 for (const auto &pair : creators_) {
96 types.push_back(pair.first);
97 }
98 return types;
99 }
100
104 [[nodiscard]] std::size_t NumRegistered() const { return creators_.size(); }
105
109 static ComponentFactory &Instance() {
110 static ComponentFactory instance;
111 return instance;
112 }
113
117 void Clear() { creators_.clear(); }
118
119 private:
120 ComponentFactory() = default;
121
122 [[nodiscard]] std::string ListTypesString() const {
123 std::string result;
124 for (const auto &pair : creators_) {
125 if (!result.empty())
126 result += ", ";
127 result += pair.first;
128 }
129 return result.empty() ? "(none)" : result;
130 }
131
132 std::unordered_map<std::string, Creator> creators_;
133};
134
135// =============================================================================
136// Registration Macros
137// =============================================================================
138
156#define ICARUS_REGISTER_COMPONENT(ComponentType) \
157 namespace { \
158 static bool _reg_numeric_##ComponentType = []() { \
159 ::icarus::ComponentFactory<janus::NumericScalar>::Instance().Register( \
160 #ComponentType, [](const ::icarus::ComponentConfig &config) { \
161 auto comp = std::make_unique<ComponentType<janus::NumericScalar>>(config.name, \
162 config.entity); \
163 comp->SetConfig(config); \
164 return comp; \
165 }); \
166 return true; \
167 }(); \
168 static bool _reg_symbolic_##ComponentType = []() { \
169 ::icarus::ComponentFactory<janus::SymbolicScalar>::Instance().Register( \
170 #ComponentType, [](const ::icarus::ComponentConfig &config) { \
171 auto comp = std::make_unique<ComponentType<janus::SymbolicScalar>>(config.name, \
172 config.entity); \
173 comp->SetConfig(config); \
174 return comp; \
175 }); \
176 return true; \
177 }(); \
178 }
179
190#define ICARUS_REGISTER_COMPONENT_IMPL2(ComponentType, TypeName, Counter) \
191 namespace { \
192 static const bool _icarus_reg_numeric_##Counter = []() { \
193 ::icarus::ComponentFactory<janus::NumericScalar>::Instance().Register( \
194 TypeName, [](const ::icarus::ComponentConfig &config) { \
195 auto comp = std::make_unique<ComponentType<janus::NumericScalar>>(config.name, \
196 config.entity); \
197 comp->SetConfig(config); \
198 return comp; \
199 }); \
200 return true; \
201 }(); \
202 static const bool _icarus_reg_symbolic_##Counter = []() { \
203 ::icarus::ComponentFactory<janus::SymbolicScalar>::Instance().Register( \
204 TypeName, [](const ::icarus::ComponentConfig &config) { \
205 auto comp = std::make_unique<ComponentType<janus::SymbolicScalar>>(config.name, \
206 config.entity); \
207 comp->SetConfig(config); \
208 return comp; \
209 }); \
210 return true; \
211 }(); \
212 }
213
214#define ICARUS_REGISTER_COMPONENT_IMPL(ComponentType, TypeName, Counter) \
215 ICARUS_REGISTER_COMPONENT_IMPL2(ComponentType, TypeName, Counter)
216
217#define ICARUS_REGISTER_COMPONENT_AS(ComponentType, TypeName) \
218 ICARUS_REGISTER_COMPONENT_IMPL(ComponentType, TypeName, __COUNTER__)
219
240#define ICARUS_REGISTER_COMPONENT_WITH_CREATOR_IMPL2(TypeName, CreatorLambda, Counter) \
241 namespace { \
242 static bool _icarus_reg_creator_##Counter = []() { \
243 ::icarus::ComponentFactory<janus::NumericScalar>::Instance().Register(TypeName, \
244 CreatorLambda); \
245 return true; \
246 }(); \
247 }
248
249#define ICARUS_REGISTER_COMPONENT_WITH_CREATOR_IMPL(TypeName, CreatorLambda, Counter) \
250 ICARUS_REGISTER_COMPONENT_WITH_CREATOR_IMPL2(TypeName, CreatorLambda, Counter)
251
252#define ICARUS_REGISTER_COMPONENT_WITH_CREATOR(TypeName, CreatorLambda) \
253 ICARUS_REGISTER_COMPONENT_WITH_CREATOR_IMPL(TypeName, CreatorLambda, __COUNTER__)
254
255} // namespace icarus
Configuration container for components with typed accessors.
Base class for all simulation components.
Consolidated error handling for Icarus.
Factory for creating components from configuration.
Definition ComponentFactory.hpp:44
std::unique_ptr< Component< Scalar > > Create(const ComponentConfig &config)
Create a component from config.
Definition ComponentFactory.hpp:73
void Register(const std::string &type_name, Creator creator)
Register a component type with custom creator.
Definition ComponentFactory.hpp:55
static ComponentFactory & Instance()
Get singleton instance.
Definition ComponentFactory.hpp:109
void Clear()
Clear all registrations (for testing).
Definition ComponentFactory.hpp:117
std::size_t NumRegistered() const
Get number of registered types.
Definition ComponentFactory.hpp:104
std::function< std::unique_ptr< Component< Scalar > >(const ComponentConfig &)> Creator
Creator function type: takes full ComponentConfig, returns component.
Definition ComponentFactory.hpp:47
bool HasType(const std::string &type_name) const
Check if a type is registered.
Definition ComponentFactory.hpp:85
std::vector< std::string > GetRegisteredTypes() const
Get list of registered type names.
Definition ComponentFactory.hpp:92
Configuration/parsing errors with optional file context.
Definition Error.hpp:185
Definition AggregationTypes.hpp:13
Configuration container for components.
Definition ComponentConfig.hpp:37
std::string type
Component type name.
Definition ComponentConfig.hpp:44