microfmt
Zero-allocation C++ formatting for constrained environments
Loading...
Searching...
No Matches
reflection.hpp
Go to the documentation of this file.
1// SPDX-FileCopyrightText: 2026 Jarosław Pelczar <jarek@jpelczar.com>
2//
3// SPDX-License-Identifier: BSD-2-Clause
4
5#pragma once
6
56#include "../microfmt.hpp"
57#include "reflect_annotate.hpp"
58
59#if RELOCO_HAS_REFLECTION
60
61#include <meta>
62#include <string_view>
63#include <type_traits>
64
65namespace microfmt::detail {
66
67template <typename E> inline constexpr bool is_reflect_formattable_enum_v = std::is_enum_v<E>;
68
69template <typename T>
70inline constexpr bool is_reflect_formattable_struct_v = std::is_class_v<T> && enable_reflect_format<T>::value;
71
72} // namespace microfmt::detail
73
74namespace microfmt {
75
76// ============================================================================
77// Formatter for reflected enums (automatic, no opt-in required)
78// ============================================================================
79template <typename E> struct formatter<E, std::enable_if_t<detail::is_reflect_formattable_enum_v<E>>> {
80 constexpr void parse(format_parse_context &ctx) noexcept { (void)ctx; }
81
82 void format(E val, const sink &out) const noexcept {
83 template for (constexpr auto e : define_static_array(std::meta::enumerators_of(^^E))) {
84 constexpr auto enumerator_value = [:e:];
85 if (val == enumerator_value) {
86 constexpr std::string_view name = std::meta::identifier_of(e);
87 out.write(microfmt::string_view(name.data(), name.size()));
88 return;
89 }
90 }
91
92 // Fallback: format raw underlying integer if value is unmapped/invalid.
93 format_to(out, "{}", static_cast<std::underlying_type_t<E>>(val));
94 }
95};
96
97// ============================================================================
98// Formatter for reflected structs & classes (opt-in via enable_reflect_format)
99// ============================================================================
100template <typename T> struct formatter<T, std::enable_if_t<detail::is_reflect_formattable_struct_v<T>>> {
101 constexpr void parse(format_parse_context &ctx) noexcept { (void)ctx; }
102
103 void format(const T &val, const sink &out) const noexcept {
104 out.put('{');
105 bool first = true;
106
107 template for (constexpr auto member : define_static_array(
108 std::meta::nonstatic_data_members_of(^^T, std::meta::access_context::current()))) {
109 if (!first) {
110 out.write(", ");
111 }
112 first = false;
113
114 constexpr std::string_view name = std::meta::identifier_of(member);
115 out.write(microfmt::string_view(name.data(), name.size()));
116 out.write(": ");
117
118 // Format member value recursively via microfmt.
119 format_to(out, "{}", val.[:member:]);
120 }
121
122 out.put('}');
123 }
124};
125
126} // namespace microfmt
127
128#endif // RELOCO_HAS_REFLECTION
Definition bintime.hpp:22
Definition assert.hpp:19
reloco::sink sink
Type-erased, zero-allocation output sink.
Definition microfmt.hpp:46
RELOCO_CONSTEXPR20 void format_to(const sink &out, microfmt::string_view fmt, const Args &...args) noexcept
Definition microfmt.hpp:1766
RELOCO_CONSTEXPR20 buffer_sink< N > format(microfmt::string_view fmt, const Args &...args) noexcept
Definition microfmt.hpp:1786
Always-safe reflection opt-in markers: MICROFMT_REFLECT_FORMAT, MICROFMT_REFLECT_DUMP_ENUM,...