cpp26-reflection
Part of the wro.cpp cpp26-reflection series — 12 of 25 posts published so far.
C++26 Reflection: What changes, and why it matters
Part 1 of the C++26 reflection series. A 40-line JSON serializer nobody could write in C++ before 2026 — plus the strategic story of why static reflection changes the ecosystem.
Your first ^^: reflecting types and walking members
Hands-on introduction to C++26 reflection: the ^^ operator, std::meta::info, and walking struct members. We take the post-1 teaser apart and rebuild it from primitives.
Splicing: [: r :] and putting reflections back into code
Splicing is the inverse of ^^: it takes a std::meta::info and drops the referred entity back into your source. Types, expressions, template arguments, member accesses — all round-trippable.
template for: iterating reflections at compile time
Expansion statements (proposal P1306) unroll a loop at compile time, instantiating the body once per element. They are the natural partner of reflection — one loop, N specialisations.
Goodbye magic_enum: enum reflection done right
A reflection-driven enum↔string library in 30 lines. No __PRETTY_FUNCTION__ tricks, no compile-time range knob, no compiler-specific behaviour — and unbounded, including enum values beyond 128.
Auto-generating std::formatter<T> for any aggregate
Rust's #[derive(Debug)] in C++: make any struct printable via std::format and std::println by dropping in one partial specialisation of std::formatter. Nested types, containers, enum names — all handled.
reflect_llmschema: C++ functions to LLM tool-use schemas, at compile time
In the AI agent era every tool you expose to Claude/GPT needs a JSON-Schema description. Today you write it by hand next to the C++ function. With C++26 reflection, a single consteval call emits the tool-use JSON at compile time — parameter names, types, docstrings, dispatch, done.
reflect_arbitrary: property-based test generators, inferred from your types
QuickCheck in Haskell, mockall in Rust, jqwik in Java — every major language auto-derives Arbitrary<T> from a struct declaration. C++ was last. Reflection fixes that: reflect the struct, recurse into field types, emit a generator. RapidCheck and FuzzTest adapters included.
reflect_optics: Haskell-style lenses for C++26
Haskell's lens library has been the gold standard for nested data access for fifteen years. Ports to C++ needed macro hell and never felt right. Reflection makes the pattern genuinely tractable. field<"address.city">(person) is now a first-class, zero-overhead, type-safe, composable lens.
reflect_dx: auto-generated debugger pretty-printers and docs
Every C++ shop writes .natvis files by hand and they go stale. Every C++ shop wishes their headers were documented but can't face Doxygen XML. reflect_dx ships as a build-step tool: walk your headers with reflection, emit LLDB / GDB / Visual Studio pretty-printers + markdown docs. Your struct is your documentation and its debugger visualisation.
reflect_telemetry: compile-time Prometheus metrics from annotated fields
Every microservice has hand-registered counter() lines that drift from the variable they count. Annotate a field [[=metric(counter)]] and let reflection emit the Prometheus exposition + OpenTelemetry OTLP exporter, keeping names in lockstep with code. Genuinely novel — nobody is doing this yet.
reflect_tracing: zero-overhead spans on Maciek Gajewski's ring-buffer engine
Tracing and metrics split into sibling libraries: reflect_telemetry for aggregates over time, reflect_tracing for spans at microsecond resolution. The engine is Maciek Gajewski's 2021 Wro.cpp technique — thread-local ring buffers, ~200 ns per span, function address as payload, DWARF resolution at dump time. Reflection contributes the instrumentation layer, which today is one explicit scope-guard line per function and tomorrow (C++29, P3294/P3157) becomes a pure annotation.