diff --git a/README.md b/README.md index ebf7bef..af6be47 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,190 @@ -# cpp-templates +# TypeFactory -generic actual cpp-templates \ No newline at end of file +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 +```