mimic++ v10.0.1
Loading...
Searching...
No Matches
PrintType.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_TYPE_PRINT_TYPE_HPP
7#define MIMICPP_PRINTING_TYPE_PRINT_TYPE_HPP
8
9#pragma once
10
11#include "mimic++/Fwd.hpp"
17
18#ifndef MIMICPP_DETAIL_IS_MODULE
19 #include <algorithm>
20 #include <concepts>
21 #include <functional>
22 #include <iterator>
23 #include <type_traits>
24 #include <utility>
25#endif
26
28{
29 namespace detail
30 {
31 template <typename T>
32 [[nodiscard]]
33 consteval std::string_view raw_type_name() noexcept
34 {
35 return util::SourceLocation{}.function_name();
36 }
37
38 // GCOVR_EXCL_START
39 inline constexpr auto typeNameConfig = std::invoke([] {
40 auto const rawName = raw_type_name<int>();
41 std::string_view const intName{"int"};
42 std::size_t const prefix = rawName.rfind(intName);
43 MIMICPP_ASSERT(prefix != std::string_view::npos, "Did not find `int` in the type-name string.");
44
45 struct type_name_config
46 {
47 std::size_t prefix{};
48 std::size_t suffix{};
49 };
50
51 return type_name_config{
52 .prefix = prefix,
53 .suffix = rawName.size() - intName.size() - prefix};
54 });
55 // GCOVR_EXCL_STOP
56 }
57
67 template <typename T>
68 [[nodiscard]]
69 consteval std::string_view type_name() noexcept
70 {
71 auto typeName = detail::raw_type_name<T>();
72 typeName.remove_prefix(detail::typeNameConfig.prefix);
73 typeName.remove_suffix(detail::typeNameConfig.suffix);
74
75 return typeName;
76 }
77
97 template <print_iterator OutIter>
98 constexpr OutIter prettify_type(OutIter out, std::string_view name);
99
118 template <print_iterator OutIter>
119 constexpr OutIter prettify_function(OutIter out, std::string_view name);
120}
121
122#ifdef MIMICPP_CONFIG_EXPERIMENTAL_PRETTY_TYPES
123
126
128{
129 template <print_iterator OutIter>
130 constexpr OutIter prettify_type(OutIter out, std::string_view const name)
131 {
132 if (std::optional const typeId = parse_type(name))
133 {
134 parsing::PrintVisitor<OutIter> visitor{std::move(out)};
135 visitor.visit(*typeId);
136
137 return visitor.out();
138 }
139
140 return format::format_to(std::move(out), "{}", name);
141 }
142
143 template <print_iterator OutIter>
144 constexpr OutIter prettify_function(OutIter out, std::string_view const name)
145 {
146 if (std::optional const functionId = parse_function(name))
147 {
148 parsing::PrintVisitor<OutIter> visitor{std::move(out)};
149 visitor.visit(*functionId);
150
151 return visitor.out();
152 }
153
154 return format::format_to(std::move(out), "{}", name);
155 }
156}
157
158#else
159
161{
162 template <print_iterator OutIter>
163 constexpr OutIter prettify_type(OutIter out, std::string_view const name)
164 {
165 return std::ranges::copy(name, std::move(out)).out;
166 }
167
168 template <print_iterator OutIter>
169 constexpr OutIter prettify_function(OutIter out, std::string_view const name)
170 {
171 return std::ranges::copy(name, std::move(out)).out;
172 }
173}
174
175#endif
176
177namespace mimicpp::printing::type::detail
178{
179 template <typename Printer, typename T, typename OutIter>
180 concept type_printer_for = print_iterator<OutIter>
181 && requires(OutIter out) {
182 typename Printer;
183 { Printer::print(out) } -> std::convertible_to<OutIter>;
184 };
185
186 template <typename T, print_iterator OutIter, type_printer_for<T, OutIter> Printer = mimicpp::custom::TypePrinter<T>>
187 constexpr OutIter print_type_to([[maybe_unused]] util::priority_tag<4u> const, OutIter out)
188 {
189 return Printer::print(std::move(out));
190 }
191
192 template <typename T, print_iterator OutIter, type_printer_for<T, OutIter> Printer = common_type_printer<T>>
193 constexpr OutIter print_type_to([[maybe_unused]] util::priority_tag<3u> const, OutIter out)
194 {
195 return Printer::print(std::move(out));
196 }
197
198 template <typename T, print_iterator OutIter, type_printer_for<T, OutIter> Printer = signature_type_printer<T>>
199 constexpr OutIter print_type_to([[maybe_unused]] util::priority_tag<2u> const, OutIter out)
200 {
201 return Printer::print(std::move(out));
202 }
203
204 template <typename T, print_iterator OutIter, type_printer_for<T, OutIter> Printer = template_type_printer<T>>
205 constexpr OutIter print_type_to([[maybe_unused]] util::priority_tag<1u> const, OutIter out)
206 {
207 return Printer::print(std::move(out));
208 }
209
210 template <typename T, print_iterator OutIter>
211 OutIter print_type_to([[maybe_unused]] util::priority_tag<0u> const, OutIter out)
212 {
213 return type::prettify_type(
214 std::move(out),
216 }
217
218 inline constexpr util::priority_tag<4u> maxPrintTypePriority{};
219
220 template <typename T>
221 struct print_type_helper
222 {
223 template <print_iterator OutIter>
224 [[nodiscard]]
225 constexpr OutIter operator()(OutIter out) const
226 {
227 return print_type_to<T>(maxPrintTypePriority, std::move(out));
228 }
229 };
230
231 template <typename T>
232 requires(!std::is_array_v<T>)
233 struct print_type_helper<volatile T>
234 {
235 template <print_iterator OutIter>
236 [[nodiscard]]
237 constexpr OutIter operator()(OutIter out) const
238 {
239 return format::format_to(
240 print_type_helper<T>{}(std::move(out)),
241 " volatile");
242 }
243 };
244
245 template <typename T>
246 requires(!std::is_array_v<T>)
247 struct print_type_helper<const T>
248 {
249 template <print_iterator OutIter>
250 [[nodiscard]]
251 constexpr OutIter operator()(OutIter out) const
252 {
253 return format::format_to(
254 print_type_helper<T>{}(std::move(out)),
255 " const");
256 }
257 };
258
259 template <typename T>
260 requires(!std::is_array_v<T>)
261 struct print_type_helper<const volatile T>
262 {
263 template <print_iterator OutIter>
264 [[nodiscard]]
265 constexpr OutIter operator()(OutIter out) const
266 {
267 return format::format_to(
268 print_type_helper<T>{}(std::move(out)),
269 " const volatile");
270 }
271 };
272
273 template <typename T>
274 struct print_type_helper<T&>
275 {
276 template <print_iterator OutIter>
277 [[nodiscard]]
278 constexpr OutIter operator()(OutIter out) const
279 {
280 return format::format_to(
281 print_type_helper<T>{}(std::move(out)),
282 "&");
283 }
284 };
285
286 template <typename T>
287 struct print_type_helper<T&&>
288 {
289 template <print_iterator OutIter>
290 [[nodiscard]]
291 constexpr OutIter operator()(OutIter out) const
292 {
293 return format::format_to(
294 print_type_helper<T>{}(std::move(out)),
295 "&&");
296 }
297 };
298
299 template <typename T>
300 struct print_type_helper<T*>
301 {
302 template <print_iterator OutIter>
303 [[nodiscard]]
304 constexpr OutIter operator()(OutIter out) const
305 {
306 return format::format_to(
307 print_type_helper<T>{}(std::move(out)),
308 "*");
309 }
310 };
311
312 template <typename T>
313 struct print_type_helper<T[]>
314 {
315 template <print_iterator OutIter>
316 [[nodiscard]]
317 constexpr OutIter operator()(OutIter out) const
318 {
319 return format::format_to(
320 print_type_helper<T>{}(std::move(out)),
321 "[]");
322 }
323 };
324
325 template <typename T, std::size_t n>
326 struct print_type_helper<T[n]>
327 {
328 template <print_iterator OutIter>
329 [[nodiscard]]
330 constexpr OutIter operator()(OutIter out) const
331 {
332 return format::format_to(
333 print_type_helper<T>{}(std::move(out)),
334 "[{}]",
335 n);
336 }
337 };
338
339 // multidimensional arrays are evaluated from left to right,
340 // but we need it from right to left.
341 template <typename T, std::size_t n, std::size_t m>
342 struct print_type_helper<T[n][m]>
343 {
344 template <print_iterator OutIter>
345 [[nodiscard]]
346 constexpr OutIter operator()(OutIter out) const
347 {
348 return format::format_to(
349 print_type_helper<T[n]>{}(std::move(out)),
350 "[{}]",
351 m);
352 }
353 };
354}
355
357{
358 template <typename T>
360 {
361 public:
362 template <print_iterator OutIter>
363 constexpr OutIter operator()(OutIter out) const
364 {
365 return type::detail::print_type_helper<T>{}(std::move(out));
366 }
367
368 [[nodiscard]]
370 {
371 StringStreamT stream{};
372 std::invoke(*this, std::ostreambuf_iterator{stream});
373 return std::move(stream).str();
374 }
375 };
376}
377
379{
426
430 template <typename T>
431 [[maybe_unused]] inline constexpr printing::PrintTypeFn<T> print_type{};
432
436}
437
438#endif
#define MIMICPP_ASSERT(condition, msg)
Definition Config.hpp:54
#define MIMICPP_DETAIL_MODULE_EXPORT
Definition Config.hpp:19
Definition PrintType.hpp:360
constexpr OutIter operator()(OutIter out) const
Definition PrintType.hpp:363
StringT operator()() const
Definition PrintType.hpp:369
constexpr void visit(state::TypeId const &typeId)
Definition PrintVisitor.hpp:40
Definition Format.hpp:71
constexpr OutIter prettify_function(OutIter out, std::string_view name)
Prettifies a function name, generated by e.g. std::source_location::function_name().
Definition PrintType.hpp:169
consteval std::string_view type_name() noexcept
Returns the raw type-name.
Definition PrintType.hpp:69
constexpr printing::PrintTypeFn< T > print_type
Functional object, converting the given type to its textual representation.
Definition PrintType.hpp:431
constexpr OutIter prettify_type(OutIter out, std::string_view name)
Prettifies a typen-name.
Definition PrintType.hpp:163
OutIter format_to(OutIter out, format_string< Args... > const fmt, Args &&... args)
Definition Format.hpp:175
Definition Fwd.hpp:54
MIMICPP_DETAIL_CONSTEXPR_PRETTY_TYPES std::optional< parsing::state::FunctionId > parse_function(std::string_view const text)
Definition Parser.hpp:1399
MIMICPP_DETAIL_CONSTEXPR_PRETTY_TYPES std::optional< parsing::state::TypeId > parse_type(std::string_view const text)
Definition Parser.hpp:1385
Definition Fwd.hpp:31
Definition Call.hpp:24
std::basic_ostringstream< CharT, CharTraitsT > StringStreamT
Definition Format.hpp:38
std::basic_string< CharT, CharTraitsT > StringT
Definition Fwd.hpp:397