mimic++ v10.0.1
Loading...
Searching...
No Matches
Format.hpp
Go to the documentation of this file.
1// Copyright Dominic (DNKpp) Koepke 2024-2026.
2// Distributed under the Boost Software License, Version 1.0.
3// (See accompanying file LICENSE_1_0.txt or copy at
4// https://www.boost.org/LICENSE_1_0.txt)
5
6#ifndef MIMICPP_PRINTING_FORMAT_HPP
7#define MIMICPP_PRINTING_FORMAT_HPP
8
9#pragma once
10
11#include "mimic++/Fwd.hpp"
14
15#ifndef MIMICPP_DETAIL_IS_MODULE
16 #include <concepts>
17 #include <functional>
18 #include <iterator>
19 #include <sstream>
20 #include <type_traits>
21 #include <utility>
22
23 #ifndef MIMICPP_CONFIG_USE_FMT
24 #include <format>
25 #else
26
27 #if __has_include(<fmt/format.h>)
28 #include <fmt/format.h>
29 #else
30 #error "The fmt formatting backend is explicitly enabled, but the include <fmt/format.h> can not be found."
31 #endif
32
33 #endif
34#endif
35
37{
38 using StringStreamT = std::basic_ostringstream<CharT, CharTraitsT>;
39
40#if MIMICPP_DETAIL_IS_GCC \
41 && __GNUC__ <= 10
42 namespace detail
43 {
55 template <typename Iter, typename T>
56 concept output_iterator = std::movable<Iter>
57 && std::indirectly_writable<Iter, T>
58 && requires(Iter iter) {
59 typename std::iter_difference_t<Iter>;
60 { ++iter } -> std::same_as<Iter&>;
61 iter++;
62 } && requires(Iter iter, T&& value) {
63 *iter++ = std::forward<T>(value);
64 };
65 }
66
67 template <typename T>
68 concept print_iterator = detail::output_iterator<T, CharT const&>;
69#else
70 template <typename T>
71 concept print_iterator = std::output_iterator<T, CharT const&>;
72#endif
73
74 template <typename Printer, typename OutIter, typename T>
76 && requires(OutIter out) {
77 {
78 Printer::print(out, std::declval<T&>())
79 } -> std::convertible_to<OutIter>;
80 };
81}
82
83#ifndef MIMICPP_CONFIG_USE_FMT
84
85MIMICPP_DETAIL_MODULE_EXPORT namespace mimicpp::format::detail::fmt
86{
87 template <typename... Args>
88 using format_string = std::basic_format_string<CharT, std::type_identity_t<Args>...>;
89 using vformat_string = StringViewT;
90 using std::format_args;
91 using std::formatter;
92 using std::make_format_args;
93 using std::vformat;
94 using std::vformat_to;
95
96 template <typename Char>
97 struct format_context;
98
99 template <typename Char>
100 using format_context_t = typename format_context<Char>::type;
101
102 template <>
103 struct format_context<char>
104 {
105 using type = std::format_context;
106 };
107
108 template <>
109 struct format_context<wchar_t>
110 {
111 using type = std::wformat_context;
112 };
113
124 template <class T, class Char>
125 concept formattable =
126 std::semiregular<std::formatter<std::remove_cvref_t<T>, Char>>
127 && requires(
128 std::formatter<std::remove_cvref_t<T>, Char> formatter,
129 T t,
130 format_context_t<Char> formatContext,
131 std::basic_format_parse_context<Char> parseContext) {
132 { formatter.parse(parseContext) } -> std::same_as<typename std::basic_format_parse_context<Char>::iterator>;
133 {
134 std::as_const(formatter).format(t, formatContext)
135 } -> std::same_as<typename std::remove_reference_t<decltype(formatContext)>::iterator>;
136 };
137}
138
139 // use fmt format
140#else
141
142MIMICPP_DETAIL_MODULE_EXPORT namespace mimicpp::format::detail::fmt
143{
144 template <typename... Args>
145 using format_string = ::fmt::format_string<Args...>;
146 using vformat_string = ::fmt::basic_string_view<CharT>;
147 using ::fmt::format_args;
148 using ::fmt::formatter;
149 using ::fmt::make_format_args;
150 using ::fmt::vformat;
151 using ::fmt::vformat_to;
152
153 template <class T, class Char>
154 concept formattable = requires {
155 requires ::fmt::is_formattable<std::remove_reference_t<T>, Char>::value;
156 };
157}
158
159#endif
160
162{
163 template <class T, typename Char = CharT>
164 concept formattable = detail::fmt::formattable<T, Char>;
165
166 using detail::fmt::format_args;
167 using detail::fmt::format_string;
168 using detail::fmt::vformat_string;
169 using detail::fmt::formatter;
170 using detail::fmt::make_format_args;
171 using detail::fmt::vformat_to;
172 using detail::fmt::vformat;
173
174 template <print_iterator OutIter, typename... Args>
175 OutIter format_to(OutIter out, format_string<Args...> const fmt, Args&&... args)
176 {
177 return detail::fmt::vformat_to(
178 std::move(out),
179 fmt.get(),
180 format::make_format_args(args...));
181 }
182
183 template <typename... Args>
184 StringT format(format_string<Args...> const fmt, Args && ... args)
185 {
186 return detail::fmt::vformat(
187 fmt.get(),
188 format::make_format_args(args...));
189 }
190}
191
193{
194 namespace detail
195 {
196 template <typename T>
198 {
199 using printer_type = printing::PrintFn;
200 std::remove_reference_t<T> value;
201
202 [[nodiscard]]
203 constexpr auto& get() const noexcept
204 {
205 return value;
206 }
207 };
208
209 template <typename T>
210 requires std::is_lvalue_reference_v<T>
211 struct fallback_formattable<T>
212 {
213 using printer_type = printing::PrintFn;
214 std::reference_wrapper<std::remove_reference_t<T>> ref;
215
216 [[nodiscard]]
217 constexpr auto& get() const noexcept
218 {
219 return ref.get();
220 }
221 };
222 }
223
224 template <typename T>
225 constexpr decltype(auto) fallback_formattable(T&& target)
226 {
227 if constexpr (formattable<T&>)
228 {
229 return std::forward<T>(target);
230 }
231 else
232 {
233 return detail::fallback_formattable<T>{std::forward<T>(target)};
234 }
235 }
236
237 template <typename T>
238 using fallback_formattable_t = decltype(fallback_formattable(std::declval<T>()));
239}
240
241template <typename T>
242struct mimicpp::format::formatter<mimicpp::format::detail::fallback_formattable<T>, mimicpp::CharT>
243{
244 using Target = mimicpp::format::detail::fallback_formattable<T>;
245 using Printer = typename Target::printer_type;
246
247 static constexpr auto parse(auto& ctx)
248 {
249 return ctx.begin();
250 }
251
252 static constexpr auto format(Target const& target, auto& ctx)
253 {
254 return std::invoke(Printer{}, ctx.out(), target.get());
255 }
256};
257
258#endif
#define MIMICPP_DETAIL_MODULE_EXPORT
Definition Config.hpp:19
Definition Format.hpp:164
Definition Format.hpp:71
Definition Format.hpp:75
Definition Format.hpp:86
constexpr decltype(auto) fallback_formattable(T &&target)
Definition Format.hpp:225
OutIter format_to(OutIter out, format_string< Args... > const fmt, Args &&... args)
Definition Format.hpp:175
StringT format(format_string< Args... > const fmt, Args &&... args)
Definition Format.hpp:184
decltype(fallback_formattable(std::declval< T >())) fallback_formattable_t
Definition Format.hpp:238
Definition Call.hpp:24
char CharT
Definition Fwd.hpp:395
std::basic_ostringstream< CharT, CharTraitsT > StringStreamT
Definition Format.hpp:38
std::basic_string_view< CharT, CharTraitsT > StringViewT
Definition Fwd.hpp:398
std::basic_string< CharT, CharTraitsT > StringT
Definition Fwd.hpp:397