microfmt
Zero-allocation C++ formatting for constrained environments
Loading...
Searching...
No Matches
monad.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
7// std-interop-file: opt-in formatter for std::optional, for interop with APIs that already speak it.
8
12#include "../microfmt.hpp"
13#include "../reloco.hpp"
14#include <optional>
15#include <reloco/optional.hpp>
16#include <string_view>
17#include <type_traits>
18
19namespace microfmt {
20
21// ============================================================================
22// std::optional Formatter (C++17 / C++20)
23// ============================================================================
24
25template <typename T> struct formatter<std::optional<T>> {
26 microfmt::string_view forwarded_spec{""};
27
28 constexpr void parse(format_parse_context &ctx) noexcept { forwarded_spec = ctx.spec(); }
29
30 void format(const std::optional<T> &opt, const sink &out) const noexcept {
31 if (opt.has_value()) {
32 out.write("Some(");
33 formatter<T> inner_fmt;
34 format_parse_context inner_ctx(forwarded_spec);
35 inner_fmt.parse(inner_ctx);
36 inner_fmt.format(*opt, out);
37 out.put(')');
38 } else {
39 out.write("None");
40 }
41 }
42};
43
44// ============================================================================
45// reloco::optional Formatter (C++17+)
46// ============================================================================
47
56template <typename T> struct formatter<reloco::optional<T>> {
57 microfmt::string_view forwarded_spec{""};
58
59 constexpr void parse(format_parse_context &ctx) noexcept { forwarded_spec = ctx.spec(); }
60
61 void format(const reloco::optional<T> &opt, const sink &out) const noexcept {
62 if (opt.has_value()) {
63 out.write("Some(");
64 formatter<T> inner_fmt;
65 format_parse_context inner_ctx(forwarded_spec);
66 inner_fmt.parse(inner_ctx);
67 inner_fmt.format(opt.value(), out);
68 out.put(')');
69 } else {
70 out.write("None");
71 }
72 }
73};
74
75// ============================================================================
76// microfmt::checked_value Formatter (C++17+)
77// ============================================================================
78
88template <typename T> struct formatter<checked_value<T>> {
89 microfmt::string_view forwarded_spec{""};
90
91 constexpr void parse(format_parse_context &ctx) noexcept { forwarded_spec = ctx.spec(); }
92
93 void format(const checked_value<T> &val, const sink &out) const noexcept {
94 if (val.is_moved_from()) {
95 out.write("<moved-from>");
96 return;
97 }
98 formatter<T> inner_fmt;
99 format_parse_context inner_ctx(forwarded_spec);
100 inner_fmt.parse(inner_ctx);
101 inner_fmt.format(val.as_known().get(), out);
102 }
103};
104
105// ============================================================================
106// microfmt::expected Formatter (C++17+)
107// ============================================================================
108
109template <typename T, typename E> struct formatter<expected<T, E>> {
110 microfmt::string_view forwarded_spec{""};
111
112 constexpr void parse(format_parse_context &ctx) noexcept { forwarded_spec = ctx.spec(); }
113
114 void format(const expected<T, E> &exp, const sink &out) const noexcept {
115 if (exp.has_value()) {
116 out.write("Ok(");
117 if constexpr (!std::is_void_v<T>) {
118 formatter<T> val_fmt;
119 format_parse_context val_ctx(forwarded_spec);
120 val_fmt.parse(val_ctx);
121 val_fmt.format(exp.value(), out);
122 }
123 out.put(')');
124 } else {
125 out.write("Err(");
126 formatter<E> err_fmt;
127 format_parse_context err_ctx(forwarded_spec);
128 err_fmt.parse(err_ctx);
129 err_fmt.format(exp.error(), out);
130 out.put(')');
131 }
132 }
133};
134
135// ============================================================================
136// std::expected Formatter (C++23 conditional)
137// ============================================================================
138
139#if MICROFMT_HAS_STD_EXPECTED
140
141template <typename T, typename E> struct formatter<std::expected<T, E>> {
142 microfmt::string_view forwarded_spec{""};
143
144 constexpr void parse(format_parse_context &ctx) noexcept { forwarded_spec = ctx.spec(); }
145
146 void format(const std::expected<T, E> &exp, const sink &out) const noexcept {
147 if (exp.has_value()) {
148 out.write("Ok(");
149 if constexpr (!std::is_void_v<T>) {
150 formatter<T> val_fmt;
151 format_parse_context val_ctx(forwarded_spec);
152 val_fmt.parse(val_ctx);
153 val_fmt.format(exp.value(), out);
154 }
155 out.put(')');
156 } else {
157 out.write("Err(");
158 formatter<E> err_fmt;
159 format_parse_context err_ctx(forwarded_spec);
160 err_fmt.parse(err_ctx);
161 err_fmt.format(exp.error(), out);
162 out.put(')');
163 }
164 }
165};
166
167#endif // MICROFMT_HAS_STD_EXPECTED
168
169} // namespace microfmt
Definition microfmt.hpp:881
Definition assert.hpp:19
reloco::sink sink
Type-erased, zero-allocation output sink.
Definition microfmt.hpp:46
RELOCO_CONSTEXPR20 buffer_sink< N > format(microfmt::string_view fmt, const Args &...args) noexcept
Definition microfmt.hpp:1786
Definition debug_float.hpp:36
void format(const checked_value< T > &val, const sink &out) const noexcept
Definition monad.hpp:93
constexpr void parse(format_parse_context &ctx) noexcept
Definition monad.hpp:91
constexpr void parse(format_parse_context &ctx) noexcept
Definition monad.hpp:112
void format(const expected< T, E > &exp, const sink &out) const noexcept
Definition monad.hpp:114
void format(const reloco::optional< T > &opt, const sink &out) const noexcept
Definition monad.hpp:61
constexpr void parse(format_parse_context &ctx) noexcept
Definition monad.hpp:59
void format(const std::optional< T > &opt, const sink &out) const noexcept
Definition monad.hpp:30
constexpr void parse(format_parse_context &ctx) noexcept
Definition monad.hpp:28
Definition microfmt.hpp:985