Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
112 commits
Select commit Hold shift + click to select a range
d0aed6e
Merge pull request #95 from ReflectCxx/develop
cpphighnrj Jan 17, 2026
e0b96b3
Merge pull request #96 from ReflectCxx/develop
cpphighnrj Jan 17, 2026
9025d96
Merge pull request #97 from ReflectCxx/develop
cpphighnrj Jan 17, 2026
cb59ab4
Merge pull request #98 from ReflectCxx/develop
cpphighnrj Jan 18, 2026
60bfd92
Merge pull request #99 from ReflectCxx/develop
cpphighnrj Jan 18, 2026
33465ee
Merge pull request #100 from ReflectCxx/develop
cpphighnrj Jan 18, 2026
0018274
readme update.
cpphighnrj Jan 18, 2026
8e492a6
Readme update.
cpphighnrj Jan 19, 2026
28b662b
Readme update.
cpphighnrj Jan 19, 2026
4b49812
Design doc update.
cpphighnrj Jan 19, 2026
2a2f895
Design doc update.
cpphighnrj Jan 19, 2026
73bee76
Design doc update.
cpphighnrj Jan 19, 2026
07f6f23
Design doc update.
cpphighnrj Jan 19, 2026
c21e351
Update README.md
cpphighnrj Jan 19, 2026
25950ae
design doc update.
cpphighnrj Jan 19, 2026
079bbc2
string_view: benchmark logs added.
cpphighnrj Jan 19, 2026
f5d2a89
string: benchmark logs added.
cpphighnrj Jan 19, 2026
9e84b27
added benchmark summary.
cpphighnrj Jan 20, 2026
257c7ac
Merge branch 'release' of https://github.com/ReflectCxx/ReflectionTem…
cpphighnrj Jan 20, 2026
1d12664
bm-summary corrections.
cpphighnrj Jan 20, 2026
1997f65
corrections.
cpphighnrj Jan 20, 2026
7f39473
Readme update.
cpphighnrj Jan 20, 2026
8e292ac
Readme update.
cpphighnrj Jan 20, 2026
f70895e
Readme update.
cpphighnrj Jan 20, 2026
a941ff3
Readme update.
cpphighnrj Jan 20, 2026
d31b0c1
adding benchmark images.
cpphighnrj Jan 20, 2026
614d774
better res bm images.
cpphighnrj Jan 20, 2026
d7bf260
visual bms added.
cpphighnrj Jan 20, 2026
28a8bd8
image adjustment
cpphighnrj Jan 20, 2026
e14d8ce
Update benchmark_summary.md
cpphighnrj Jan 20, 2026
58bdf2a
Update benchmark_summary.md
cpphighnrj Jan 20, 2026
0f9cc72
docs correction, updates.
cpphighnrj Jan 20, 2026
edfecc0
Merge branch 'release' of https://github.com/ReflectCxx/ReflectionTem…
cpphighnrj Jan 20, 2026
480fa84
docs correction.
cpphighnrj Jan 20, 2026
5e0dd9e
perf. summary edits.
cpphighnrj Jan 20, 2026
6b444f8
Update benchmark_summary.md
cpphighnrj Jan 20, 2026
a132a45
Update README.md
cpphighnrj Jan 20, 2026
7b1a374
Update benchmark_summary.md
cpphighnrj Jan 20, 2026
a4204d3
Update benchmark_summary.md
cpphighnrj Jan 20, 2026
bc52a49
Update README.md
cpphighnrj Jan 20, 2026
f1de6f3
design doc update.
cpphighnrj Jan 21, 2026
e30e5c6
doc: Syntax-n-Semantics update.
cpphighnrj Jan 21, 2026
fe1159a
doc: Syntax-n-Semantics update.
cpphighnrj Jan 21, 2026
f19ded6
doc: registration syns-n-sems.
cpphighnrj Jan 21, 2026
c49572e
doc: syns-n-sems, queries.
cpphighnrj Jan 21, 2026
beb4646
doc: syns-n-sems, callables.
cpphighnrj Jan 21, 2026
7e4587c
Update RTL_SYNTAX_AND_SEMANTICS.md
cpphighnrj Jan 21, 2026
88e4e49
doc: syns-n-sems, metadata-query.
cpphighnrj Jan 21, 2026
59a07dc
doc: syns-n-sems, correction.
cpphighnrj Jan 21, 2026
fe885d9
doc: syns-n-sems, materialize, intro.
cpphighnrj Jan 21, 2026
7105432
doc: syns-n-sems, ctors.
cpphighnrj Jan 21, 2026
b6f8a9b
doc: syns-n-sems, corrections.
cpphighnrj Jan 21, 2026
297f7a8
doc: syns-n-sems, spacing.
cpphighnrj Jan 21, 2026
0bcc50e
Readme update.
cpphighnrj Jan 21, 2026
2f75a2a
Update README.md
cpphighnrj Jan 21, 2026
af520d3
Update README.md
cpphighnrj Jan 21, 2026
573a74f
Update README.md
cpphighnrj Jan 21, 2026
e55d2bc
Update RTL_SYNTAX_AND_SEMANTICS.md
cpphighnrj Jan 21, 2026
c6f7f92
Update RTL_SYNTAX_AND_SEMANTICS.md
cpphighnrj Jan 21, 2026
fc78b26
Readme update.
cpphighnrj Jan 22, 2026
0ae8886
Readme update.
cpphighnrj Jan 22, 2026
f2ab77b
Readme update.
cpphighnrj Jan 22, 2026
d246951
doc corrections.
cpphighnrj Jan 22, 2026
3bfb71a
Update README.md
cpphighnrj Jan 22, 2026
ac81d38
doc: syns-n-sems, rtl::function.
cpphighnrj Jan 22, 2026
b143712
Merge branch 'release' of https://github.com/ReflectCxx/ReflectionTem…
cpphighnrj Jan 22, 2026
b905fd5
doc: syns-n-sems, rtl::method.
cpphighnrj Jan 22, 2026
99d2801
doc: syns-n-sems, rtl::method.
cpphighnrj Jan 22, 2026
8a80042
doc: syns-n-sems, rtl::method.
cpphighnrj Jan 22, 2026
3560ab3
doc: syns-n-sems, rtl::method done.
cpphighnrj Jan 22, 2026
63ad3ee
doc: syns-n-sems, rtl::RObject.
cpphighnrj Jan 22, 2026
1618d26
doc: correction.
cpphighnrj Jan 22, 2026
9ee99be
doc: move semantics.
cpphighnrj Jan 22, 2026
c2fbeb5
doc: corrections.
cpphighnrj Jan 22, 2026
60c95ae
doc: perfect forwarding.
cpphighnrj Jan 22, 2026
a94a2fe
doc: index updated.
cpphighnrj Jan 22, 2026
7b5c740
doc: index correction.
cpphighnrj Jan 22, 2026
2c8d26e
undo last commit.
cpphighnrj Jan 22, 2026
b1757f4
doc: improvements.
cpphighnrj Jan 23, 2026
608eb00
doc: improvements.
cpphighnrj Jan 23, 2026
b3291f8
doc: improvements.
cpphighnrj Jan 23, 2026
62b0e02
doc: improvements.
cpphighnrj Jan 23, 2026
b6a1607
doc: improvements.
cpphighnrj Jan 23, 2026
5e23073
doc: improvements.
cpphighnrj Jan 23, 2026
0110db4
doc: corrections.
cpphighnrj Jan 23, 2026
442c53c
doc: corrections.
cpphighnrj Jan 23, 2026
f5cf78b
doc: ref-binding done.
cpphighnrj Jan 23, 2026
0400ef9
doc: corrections.
cpphighnrj Jan 23, 2026
5b2c0a0
doc: ploishing
cpphighnrj Jan 23, 2026
5eaab58
doc: rtl::errors
cpphighnrj Jan 23, 2026
15da052
Update RTL_SYNTAX_AND_SEMANTICS.md
cpphighnrj Jan 23, 2026
2386223
Update RTL_SYNTAX_AND_SEMANTICS.md
cpphighnrj Jan 23, 2026
44d2e41
docs: rtl::view
cpphighnrj Jan 24, 2026
80bf3cd
docs: rtl::view
cpphighnrj Jan 24, 2026
43647ee
docs: rtl::view corrections
cpphighnrj Jan 24, 2026
6fe7b59
docs: rtl::view corrections
cpphighnrj Jan 24, 2026
f02593d
docs: rtl::view update.
cpphighnrj Jan 24, 2026
517dd14
docs: rtl::view update.
cpphighnrj Jan 24, 2026
3ca464a
docs: correction.
cpphighnrj Jan 24, 2026
c324f97
doc update.
cpphighnrj Jan 24, 2026
86a3feb
Update README.md
cpphighnrj Jan 24, 2026
8c07786
Readme update.
cpphighnrj Jan 24, 2026
c4fac7a
Readme update.
cpphighnrj Jan 24, 2026
91b9983
Readme update.
cpphighnrj Jan 24, 2026
a9a8e5f
Merge pull request #101 from ReflectCxx/develop
cpphighnrj Jan 24, 2026
52e60e5
Update badge color for Design Traits in README
cpphighnrj Jan 25, 2026
76286ce
Update badge color for RTL Syntax & Semantics
cpphighnrj Jan 25, 2026
180c1c8
Revise documentation badges in README.md
cpphighnrj Jan 25, 2026
36fdc32
Update demo code link formatting in README
cpphighnrj Jan 25, 2026
8efb9a2
Add 'Try RTL Online' badge to README
cpphighnrj Jan 25, 2026
90fb07f
Remove 'Try RTL Online' badge from README
cpphighnrj Jan 25, 2026
d178307
Update demo code link in README.md
cpphighnrj Jan 27, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
100 changes: 40 additions & 60 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,11 @@

RTL provides type-safe run-time reflection for C++, combining compile-time guarantees with run-time flexibility.

It enables name-based discovery and invocation of functions, constructors, and object members through a non-intrusive, type-safe reflection system that follows modern C++ idioms. For example, consider the following function
It enables name-based discovery and invocation of functions, constructors, and object members through a non-intrusive, type-safe reflection system that follows modern C++ idioms. For example, consider the following function:
```c++
std::string complexToStr(float real, float img);
```
Using RTL, you can discover this function by name and invoke it dynamically
Using RTL, you can discover this function by name and call it dynamically:
```c++
rtl::function<std::string(float, float)> cToStr = cxx::mirror().getFunction("complexToStr")
->argsT<float, float>()
Expand All @@ -32,7 +32,7 @@ if(cToStr) { // Function materialized?

⚡ **Performance**

RTL’s reflective calls are comparable to `std::function` for fully type-erased dispatch, and achieve lower call overhead *(just a function-pointer hop)* when argument and return types are known.
RTL’s reflective calls are comparable to `std::function`, and achieve lower overhead when argument and return types are fully specified.

## Design Highlights

Expand All @@ -42,32 +42,25 @@ RTL’s reflective calls are comparable to `std::function` for fully type-erased

* ***Zero-Overhead by Design*** – Metadata can be registered and resolved lazily. Reflection introduces no runtime cost beyond the features explicitly exercised by the user.

* ***Cross-Compiler Consistency*** – Implemented entirely in standard C++20, with no compiler extensions or compiler-specific conditional behavior.
* ***Hot-Loop Ready*** – Typed reflection calls exhibit near-zero overhead and scale like direct calls, making RTL suitable for performance-critical and tight-loop workloads. *([Performance Summary](docs/benchmark_summary.md))*

* ***Tooling-Friendly Architecture*** – Reflection data is encapsulated in a single immutable, lazily-initialized structure that can be shared with external tools and frameworks without compile-time type knowledge – suitable for serializers, debuggers, test frameworks, scripting engines, and editors.


[![Design Features](https://img.shields.io/badge/Doc-Design%20Features-blue)](./text-design-docs/DESIGN_PRINCIPLES_AND_FEATURES.md)
[![RTL Syntax & Semantics](https://img.shields.io/badge/Doc-Syntax_&_Semantics-blueviolet)](./text-design-docs/RTL_SYNTAX_AND_SEMANTICS.md)
* ***Tooling-Friendly Architecture*** – Reflection metadata is encapsulated in a single immutable, lazily-initialized structure that can be shared with external tools and frameworks without compile-time type knowledge – suitable for serializers, debuggers, test frameworks, scripting engines, and editors.

## A Quick Preview: Reflection That Looks and Feels Like C++

First, create an instance of `rtl::CxxMirror`
First, create an instance of `rtl::CxxMirror`:
```c++
auto cxx_mirror = rtl::CxxMirror({ /* ...register all types here... */ });
```
The `cxx_mirror` object provides access to the runtime reflection system. It enables querying, introspection, and instantiation of registered types without requiring compile-time type knowledge at the call site.
It can reside in any translation unit. To make it globally accessible and ensure it is initialized only when needed, a singleton access interface can be used –
The `cxx_mirror` object provides access to the runtime reflection system. It references metadata for all registered entities and supports name-based lookup. The object may reside in any translation unit. To make it globally accessible while ensuring lazy initialization, a singleton access interface can be used:
```c++
// MyReflection.h
namespace rtl { class CxxMirror; } // Forward declaration, no includes here!
struct cxx { static rtl::CxxMirror& mirror(); }; // The Singleton.
namespace rtl { class CxxMirror; } // Forward declaration, no includes here.
struct cxx { static rtl::CxxMirror& mirror(); }; // The singleton interface.
```
define and register everything in an isolated translation unit
define and register everything in an isolated translation unit:
```c++
// MyReflection.cpp
#include <rtl_builder.h> // Reflection builder interface.

rtl::CxxMirror& cxx::mirror() {
static auto cxx_mirror = rtl::CxxMirror({ // Inherently thread safe.
// Register free(C-Style) function -
Expand All @@ -82,95 +75,82 @@ rtl::CxxMirror& cxx::mirror() {
return cxx_mirror;
}
```
`cxx_mirror` is an immutable, stack-allocated, value-type object and is safe to copy, but when used as a singleton (as shown above), implicit copies (e.g., `auto mirror = cxx::mirror();`) can unintentionally violate the singleton semantics, so `rtl::CxxMirror` restricts such copy construction.

### RTL in action:

**[Explore the demo code](https://github.com/ReflectCxx/RTL-Demo)**

Lookup the `Person` class by its registered name –
Lookup the `Person` class by its registered name:
```c++
std::optional<rtl::Record> classPerson = cxx::mirror().getRecord("Person");
if (!classPerson) { /* Class not registered. */ }
```
`rtl::CxxMirror` provides two lookup APIs that return reflection metadata objects: `rtl::Record` for any registered type (class, struct or pod) and `rtl::Function` for non-member functions.
`rtl::CxxMirror` returns two reflection metadata objects: `rtl::Record` for any registered type (class, struct, or POD) and `rtl::Function` for non-member functions.

From `rtl::Record`, registered member functions can be queried as `rtl::Method`. These are metadata descriptors (not callables) and are returned as `std::optional`, which will be empty if the requested entity is not found.
From `rtl::Record`, registered member functions can be obtained as `rtl::Method`. These are metadata descriptors (not callables). Callable entities are materialized by explicitly providing the argument types we intend to pass.

Callables are materialized by explicitly providing the argument types we intend to pass. If the signature is valid, the resulting callable can be invoked safely.
For example, the overloaded constructor `Person(std::string, int)` –
For example, the overloaded constructor `Person(std::string, int)`:
```c++
rtl::constructor<std::string, int> personCtor = classPerson->ctorT<std::string, int>();
if (!personCtor) { /* Constructor with expected signature not found. */ }
```
Or the default constructor
Or the default constructor:
```c++
rtl::constructor<> personCtor = classPerson->ctorT<>();
```
Instances can be created on the `Heap` or `Stack` with automatic lifetime management
Instances can be created on the `Heap` or `Stack` with automatic lifetime management:
```c++
auto [err, robj] = personCtor(rtl::alloc::Stack, "John", 42);
if (err != rtl::error::None) { std::cerr << rtl::to_string(err); } // Construction failed.
```
The constructed object is returned wrapped in `rtl::RObject`. Heap-allocated objects are internally managed via `std::unique_ptr`, while stack-allocated objects are stored directly in `std::any`.
The constructed object is returned as an `rtl::RObject` in the variable `robj`.

Now, Lookup a member-function by name
Looking up a member function by name:
```c++
std::optional<rtl::Method> oGetName = classPerson->getMethod("getName");
if (!oGetName) { /* Member function not registered */ }
```
And materialize a complete type-aware caller
And materialize a complete type-aware caller:
```c++
rtl::method<Person, std::string()> getName = oGetName->targetT<Person>()
.argsT().returnT<std::string>();
if (!getName) {
rtl::method<Person, std::string()> getName = oGetName->targetT<Person>().argsT()
.returnT<std::string>();
if (!getName) { // Member function with expected signature not found.
std::cerr << rtl::to_string(getName.get_init_err());
}
else {
Person person("Alex", 23);
std::string nameStr = getName(person)(); // Returns string 'Alex'.
}
```
The above `getName` invocation is effectively a native function-pointer hop, since all types are known at compile time.
The above `getName` invocation is effectively a **native function-pointer hop**, since all types are known at compile time.

If the concrete type `Person` is not accessible at the call site, its member functions can still be invoked by erasing the target type and using `rtl::RObject` instead. The previously constructed instance (`robj`) is passed as the target
If the concrete type `Person` is not accessible at the call site, its member functions can still be invoked by erasing the target type and using `rtl::RObject` instead. The previously constructed instance (`robj`) is passed as the target:
```c++
rtl::method<rtl::RObject, std::string()> getName = oGetName->targetT()
.argsT().returnT<std::string>();
rtl::method<rtl::RObject, std::string()> getName = oGetName->targetT().argsT()
.returnT<std::string>();
auto [err, ret] = getName(robj)(); // Invoke and receive return as std::optional<std::string>.
if (err == rtl::error::None && ret.has_value()) {
std::cout << ret.value();
std::string nameStr = ret.value();
}
```
If the return type is also not known at compile time,`rtl::Return` can be used
If the return type is also not known at compile time,`rtl::Return` can be used:
```c++
rtl::method<rtl::RObject, rtl::Return()> getName = oGetName->targetT()
.argsT().returnT();
rtl::method<rtl::RObject, rtl::Return()> getName = oGetName->targetT().argsT().returnT();

auto [err, ret] = getName(robj)(); // Invoke and receive rtl::RObject as return, wrapping std::string underneath.
if (err == rtl::error::None && ret.canViewAs<std::string>()) {
const std::string& name = ret.view<std::string>()->get();
std::cout << name; // Safely view the returned std::string.
std::string nameStr = ret.view<std::string>()->get(); // Safely view the returned std::string.
}
```
**[Explore the demo code here](https://github.com/ReflectCxx/RTL-Demo)**

### How RTL Fits Together

At a high level, every registered C++ type is encapsulated as an `rtl::Record`. Callable entities (functions, member functions and constructors) are materialized through `rtl::Function`, `rtl::Method` and `rtl::Record`, all of which are discoverable via `rtl::CxxMirror`.

RTL provides the following callable entities, designed to be as lightweight and performant as `std::function` (and in many micro-benchmarks, faster when fully type-aware):

`rtl::function<>` – Free (non-member) functions
👉 Deep Dive

`rtl::constructor<>` – Constructors

`rtl::method<>` – Non-const member functions

`rtl::const_method<>` – Const-qualified member functions

`rtl::static_method<>` – Static member functions

These callable types are regular value types: they can be copied, moved, stored in standard containers, and passed around like any other lightweight object.

When invoked, only type-erased callables return an `rtl::error`, with results provided as `rtl::RObject` *(when both the return and target types are erased)* or as `std::optional<T>` *(when only the target type is erased)*, while fully type-aware callables return `T` directly with no error (by design).
[![Design Traits](https://img.shields.io/badge/Doc-Design%20Traits-blue)](./docs/DESIGN_PRINCIPLES_AND_FEATURES.md)
&nbsp;
[![RTL Syntax & Semantics](https://img.shields.io/badge/Doc-Syntax_&_Semantics-blueviolet)](./docs/RTL_SYNTAX_AND_SEMANTICS.md)
&nbsp;
[![Benchmark Summary](https://img.shields.io/badge/Doc-Benchmark%20Summary-teal)](./docs/benchmark_summary.md)

### How to Build (Windows / Linux)
```sh
Expand Down Expand Up @@ -238,4 +218,4 @@ If you’re interested in advancing practical runtime reflection in C++ and supp

##

***C++ joins the reflection party! – why should Java have all the fun?***
***C++ joins the reflection party! – why should Java have all the fun?***
119 changes: 119 additions & 0 deletions docs/DESIGN_PRINCIPLES_AND_FEATURES.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
### 🪶 Registration Model and Metadata Lifetime

RTL does not use macro-based reflection, implicit static initialization at program startup, or centralized global registries.
All registration is performed lazily and explicitly by user code, and registered metadata persists for the lifetime of the process.

For every registered type, method, or function, RTL creates a **dedicated dispatch object** that encapsulates:

* The callable function-pointer
* The associated reflection metadata

These dispatch objects are defined in:

```
rtl/dispatch/function_ptr.h
rtl/dispatch/method_ptr.h
```

Each dispatch object is:

* Created **exactly once per unique registration**
* Stored in a process-lifetime (`static std::list`)
* Reused across all `rtl::CxxMirror` instances

Repeated registration attempts always resolve to the same existing object. This ensures deterministic behavior –
metadata identity is stable regardless of initialization order or how many translation units register the same type.

`rtl::CxxMirror` does not own or duplicate this metadata. It encapsulates references to it as a lightweight, ordinary object. Mirrors may be created with different type sets, and the same registration statements can be materialized multiple times.

For example:

```cpp
rtl::type().member<Person>().method("getName").build(&Person::getName);
```

will always yield the same metadata and dispatch object for `Person::getName`.
The lifetime of registered metadata is independent of any individual `rtl::CxxMirror` instance and persists for the duration of the program.

---

### ⚡ Reflective Call Materialization and Performance

RTL employs a two-phase invocation model. Metadata queries return lightweight descriptors such as `rtl::Function` and `rtl::Method`, which must be explicitly **materialized** into callable entity by specifying the expected signature.

This deferred materialization acts as a compile-time contract: the user declares the argument and return types they intend to use, and RTL validates and prepares an optimized invocation path accordingly.

Performance depends on how much type information is provided:

* Fully specified signatures compile to **direct function-pointer calls**, faster than `std::function`.
* Type-erased signatures invoke through a lightweight dispatch layer whose performance **is comparable** to `std::function` under real workloads.

By requiring explicit materialization, RTL produces lightweight, reusable callable entity that behave like ordinary value-type objects and can be stored in standard containers.

At call time, RTL performs no dynamic allocations, no RTTI lookups, no `void*` stuff, and no hidden metadata traversals. The runtime cost is explicit, minimal, and comparable to what a developer would implement manually for equivalent type safety and flexibility.

---

### 🛡 Exception-Free Guarantee

RTL is designed to be exception-free. In practice, any exceptions that occur are almost always introduced by user code and merely propagate through RTL.

For all predictable failure cases, RTL reports errors through explicit error codes(`rtl::error`) rather than throwing exceptions. Critical assumptions are validated before execution, ensuring that failure conditions are detected early and handled in a controlled manner.

This design promotes predictable behavior and avoids unexpected control flow during reflective operations.

> *Exception-handling behavior has not yet been exhaustively stress-tested across all edge cases, but the system is architected to avoid exception-based control flow by design.*

---

### 🎁 Smart Pointer Handling

RTL supports working with objects managed by `std::unique_ptr` and `std::shared_ptr` in a manner consistent with standard C++ usage.

Heap-allocated objects created through RTL are internally managed using smart pointers to ensure safe ownership and lifetime control. These details are not imposed on the user: reflected objects can be accessed either through their smart-pointer representation or through views of the underlying type `T`.

When cloning or transferring reflected objects, RTL preserves the ownership semantics of the original type:

* Objects intended to be shared can be accessed through shared ownership.
* Uniquely owned objects retain their uniqueness.
* Copyable values can be duplicated to produce independent instances.

This design allows developers to work with reflected objects using the same ownership and lifetime expectations they would apply in ordinary C++ code, without requiring special handling for reflection-specific wrappers.

Reflection semantics are aligned with standard C++ object semantics, ensuring consistent behavior regardless of whether an object is accessed directly or through a smart pointer.

---

### 💡 Tooling-Friendly Architecture

**RTL** separates the *generation* of reflection metadata from its *consumption*. This makes it ideal not just for runtime introspection, but also for external tools like:

* Code generators
* Serialization pipelines
* Game or UI editors
* Live scripting or plugin systems

#### ✨ The Mirror & The Reflection

> *A client system hands off a `rtl::CxxMirror` to RTL — and RTL sees its reflection.*

The mirror is a **single object**, typically returned from a function like:

```cpp
extern const rtl::CxxMirror& MyReflection();
```

This function is:

* **Externally linkable** — can live in any translation unit or even dynamic module
* **Lazy** — doesn’t require metadata unless explicitly accessed
* **Pure** — returns a complete, immutable view of reflection metadata

#### 📎 Why This Matters for Tooling

This design turns RTL into a **pluggable, runtime-agnostic consumer** of metadata. You can:

* Reflect types from external libraries
* Link in auto-generated metadata modules
* Expose your reflection system to scripts or tools without tight coupling
* Swap different `rtl::CxxMirror` sources depending on build mode (dev/editor/runtime)
Loading