# TypeFactory A lightweight registry-based factory for creating objects by runtime identifier. `TypeFactory` is a small header-only C++ utility for situations where the exact object type must be selected dynamically at runtime using an ID. Typical use cases include: - protocol command dispatch - vehicle type identification - runtime parser or handler selection - plugin-like object creation - configuration-based object instantiation The implementation is intentionally simple and follows the KISS principle. ## Features - header-only implementation - C++17 compatible - compile-time validation of registered types - fast lookup using `std::unordered_map` - optional access to creator function for advanced use - predictable and compact API - suitable for both commercial and open-source projects ## Requirements - C++17 or newer - `ClassId` must be hashable (`std::hash` must be available) ## Basic Idea The factory stores a mapping: - **runtime ID** -> **creator function** A derived type is registered once, then can be created later by its ID. ## Example ```cpp #include "typefactory.h" #include #include struct Base { virtual ~Base() = default; virtual int get() = 0; }; struct Derived1 : Base { explicit Derived1(int start) : m_start(start) {} int get() override { return m_start + 1; } private: int m_start = 0; }; struct Derived2 : Base { explicit Derived2(int start) : m_start(start) {} int get() override { return m_start + 2; } private: int m_start = 0; }; int main() { TypeFactory factory; factory.registerType("one"); factory.registerType("two"); auto d1 = factory.create("one", 10); auto d2 = factory.create("two", 10); return d1->get() + d2->get(); } ``` ## Advanced Usage The factory also provides direct access to the creator function: ```cpp auto fn = factory.creator("one"); auto obj = fn(10); ``` This can be useful when integrating with dispatch tables or higher-level runtime logic. ## API Overview ### `registerType` Registers a derived type for a given runtime ID. ```cpp factory.registerType("id"); ``` Compile-time checks ensure that: - `Derived` inherits from `BaseClass` - `Derived` is constructible from `Args...` If the same ID is registered again, the previous registration is overwritten. This is intentional: **last registration wins**. ### `creator` Returns the creator function associated with the given ID. ```cpp auto fn = factory.creator("id"); ``` Throws `std::out_of_range` if the ID is not registered. ### `create` Creates an object directly by ID. ```cpp auto obj = factory.create("id", args...); ``` Throws `std::out_of_range` if the ID is not registered. ### `contains` Checks whether an ID is registered. ```cpp if (factory.contains("id")) { // safe to create } ``` ## Design Notes - `TypeFactory` is not thread-safe during registration. - Types should normally be registered during initialization. - Lookup and creation are lightweight and predictable. - The class is designed to be reusable as a low-level infrastructure utility. - The registry is stored in a protected `std::unordered_map`, so derived factories can extend the design if needed. ## Why Not Abstract Factory? This utility is not a classic *Abstract Factory* pattern. A classic Abstract Factory typically creates **families of related objects**. `TypeFactory` is closer to a: - registry-based factory - type factory - runtime creator map It focuses on selecting one concrete type by runtime ID. ## Example Use Cases ### Vehicle Identification A controller returns a vehicle ID. The system uses that ID to create the matching parameter or settings object. ### Protocol Command Handling A command ID is received over the network. The system selects and creates the correct handler object for that command. ### Runtime Format Selection A parser or converter is selected dynamically depending on file type, message type, or configuration. ## License This project is licensed under the MIT License. For source files, it is recommended to use SPDX headers such as: ```cpp // SPDX-License-Identifier: MIT // Copyright (c) 2025 Dim Himro ```