mimic++ v9.2.1
Loading...
Searching...
No Matches
PrintType.hpp
Go to the documentation of this file.
1// Copyright Dominic (DNKpp) Koepke 2024 - 2025.
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"
16
17#ifndef MIMICPP_DETAIL_IS_MODULE
18 #include <algorithm>
19 #include <concepts>
20 #include <functional>
21 #include <iterator>
22 #include <type_traits>
23 #include <typeinfo>
24 #include <utility>
25#endif
26
28{
39 template <typename T>
40 [[nodiscard]]
42
62 template <print_iterator OutIter>
63 MIMICPP_DETAIL_CONSTEXPR_STRING OutIter prettify_type(OutIter out, StringT name);
64
83 template <print_iterator OutIter>
85}
86
87#ifdef MIMICPP_CONFIG_EXPERIMENTAL_PRETTY_TYPES
88
89 #if MIMICPP_DETAIL_IS_GCC || MIMICPP_DETAIL_IS_CLANG
90
91 #ifndef MIMICPP_DETAIL_IS_MODULE
92 #include <cstdlib>
93 #include <cxxabi.h>
94 #include <memory>
95 #endif
96
98{
99 namespace detail
100 {
101 struct free_deleter
102 {
103 void operator()(char* const c) const noexcept
104 {
105 std::free(c);
106 }
107 };
108 }
109
110 template <typename T>
112 {
113 auto* const rawName = typeid(T).name();
114
115 // see: https://gcc.gnu.org/onlinedocs/libstdc++/manual/ext_demangling.html
116 int status{};
117 std::unique_ptr<char, detail::free_deleter> const demangledName{
118 abi::__cxa_demangle(rawName, nullptr, nullptr, &status)};
119 if (0 == status)
120 {
121 return {demangledName.get()};
122 }
123
124 return {rawName};
125 }
126}
127
128 #else
129
131{
132 template <typename T>
134 {
135 return typeid(T).name();
136 }
137}
138
139 #endif
140
143
145{
146 template <print_iterator OutIter>
147 MIMICPP_DETAIL_CONSTEXPR_STRING OutIter prettify_type(OutIter out, StringT name)
148 {
150
151 PrintVisitor visitor{std::move(out)};
152 parsing::NameParser parser{std::ref(visitor), name};
153 parser.parse_type();
154
155 return visitor.out();
156 }
157
158 namespace detail
159 {
160 [[nodiscard]]
161 MIMICPP_DETAIL_CONSTEXPR_STRING StringT remove_template_details(StringT name)
162 {
163 if (name.ends_with(']'))
164 {
165 auto rest = name | std::views::reverse | std::views::drop(1);
166 if (auto const closingIter = util::find_closing_token(rest, ']', '[');
167 closingIter != rest.end())
168 {
169 auto const end = std::ranges::find_if_not(
170 closingIter + 1,
171 rest.end(),
173 name.erase(end.base(), name.end());
174 }
175 }
176
177 return name;
178 }
179 }
180
181 template <print_iterator OutIter>
183 {
184 name = detail::remove_template_details(std::move(name));
185
187
188 PrintVisitor visitor{std::move(out)};
189 parsing::NameParser parser{std::ref(visitor), name};
190 parser.parse_function();
191
192 return visitor.out();
193 }
194}
195
196#else
197
199{
200 template <typename T>
202 {
203 return typeid(T).name();
204 }
205
206 template <print_iterator OutIter>
208 {
209 return std::ranges::copy(name, std::move(out)).out;
210 }
211
212 template <print_iterator OutIter>
214 {
215 return std::ranges::copy(name, std::move(out)).out;
216 }
217}
218
219#endif
220
221namespace mimicpp::printing::type::detail
222{
223 template <typename Printer, typename T, typename OutIter>
224 concept type_printer_for = print_iterator<OutIter>
225 && requires(OutIter out) {
226 typename Printer;
227 { Printer::print(out) } -> std::convertible_to<OutIter>;
228 };
229
230 template <typename T, print_iterator OutIter, type_printer_for<T, OutIter> Printer = mimicpp::custom::TypePrinter<T>>
231 constexpr OutIter print_type_to([[maybe_unused]] util::priority_tag<4u> const, OutIter out)
232 {
233 return Printer::print(std::move(out));
234 }
235
236 template <typename T, print_iterator OutIter, type_printer_for<T, OutIter> Printer = common_type_printer<T>>
237 constexpr OutIter print_type_to([[maybe_unused]] util::priority_tag<3u> const, OutIter out)
238 {
239 return Printer::print(std::move(out));
240 }
241
242 template <typename T, print_iterator OutIter, type_printer_for<T, OutIter> Printer = signature_type_printer<T>>
243 constexpr OutIter print_type_to([[maybe_unused]] util::priority_tag<2u> const, OutIter out)
244 {
245 return Printer::print(std::move(out));
246 }
247
248 template <typename T, print_iterator OutIter, type_printer_for<T, OutIter> Printer = template_type_printer<T>>
249 constexpr OutIter print_type_to([[maybe_unused]] util::priority_tag<1u> const, OutIter out)
250 {
251 return Printer::print(std::move(out));
252 }
253
254 template <typename T, print_iterator OutIter>
255 OutIter print_type_to([[maybe_unused]] util::priority_tag<0u> const, OutIter out)
256 {
257 return type::prettify_type(
258 std::move(out),
260 }
261
262 inline constexpr util::priority_tag<4u> maxPrintTypePriority{};
263
264 template <typename T>
265 struct print_type_helper
266 {
267 template <print_iterator OutIter>
268 [[nodiscard]]
269 constexpr OutIter operator()(OutIter out) const
270 {
271 return print_type_to<T>(maxPrintTypePriority, std::move(out));
272 }
273 };
274
275 template <typename T>
276 requires(!std::is_array_v<T>)
277 struct print_type_helper<volatile T>
278 {
279 template <print_iterator OutIter>
280 [[nodiscard]]
281 constexpr OutIter operator()(OutIter out) const
282 {
283 return format::format_to(
284 print_type_helper<T>{}(std::move(out)),
285 " volatile");
286 }
287 };
288
289 template <typename T>
290 requires(!std::is_array_v<T>)
291 struct print_type_helper<const T>
292 {
293 template <print_iterator OutIter>
294 [[nodiscard]]
295 constexpr OutIter operator()(OutIter out) const
296 {
297 return format::format_to(
298 print_type_helper<T>{}(std::move(out)),
299 " const");
300 }
301 };
302
303 template <typename T>
304 requires(!std::is_array_v<T>)
305 struct print_type_helper<const volatile T>
306 {
307 template <print_iterator OutIter>
308 [[nodiscard]]
309 constexpr OutIter operator()(OutIter out) const
310 {
311 return format::format_to(
312 print_type_helper<T>{}(std::move(out)),
313 " const volatile");
314 }
315 };
316
317 template <typename T>
318 struct print_type_helper<T&>
319 {
320 template <print_iterator OutIter>
321 [[nodiscard]]
322 constexpr OutIter operator()(OutIter out) const
323 {
324 return format::format_to(
325 print_type_helper<T>{}(std::move(out)),
326 "&");
327 }
328 };
329
330 template <typename T>
331 struct print_type_helper<T&&>
332 {
333 template <print_iterator OutIter>
334 [[nodiscard]]
335 constexpr OutIter operator()(OutIter out) const
336 {
337 return format::format_to(
338 print_type_helper<T>{}(std::move(out)),
339 "&&");
340 }
341 };
342
343 template <typename T>
344 struct print_type_helper<T*>
345 {
346 template <print_iterator OutIter>
347 [[nodiscard]]
348 constexpr OutIter operator()(OutIter out) const
349 {
350 return format::format_to(
351 print_type_helper<T>{}(std::move(out)),
352 "*");
353 }
354 };
355
356 template <typename T>
357 struct print_type_helper<T[]>
358 {
359 template <print_iterator OutIter>
360 [[nodiscard]]
361 constexpr OutIter operator()(OutIter out) const
362 {
363 return format::format_to(
364 print_type_helper<T>{}(std::move(out)),
365 "[]");
366 }
367 };
368
369 template <typename T, std::size_t n>
370 struct print_type_helper<T[n]>
371 {
372 template <print_iterator OutIter>
373 [[nodiscard]]
374 constexpr OutIter operator()(OutIter out) const
375 {
376 return format::format_to(
377 print_type_helper<T>{}(std::move(out)),
378 "[{}]",
379 n);
380 }
381 };
382
383 // multidimensional arrays are evaluated from left to right,
384 // but we need it from right to left.
385 template <typename T, std::size_t n, std::size_t m>
386 struct print_type_helper<T[n][m]>
387 {
388 template <print_iterator OutIter>
389 [[nodiscard]]
390 constexpr OutIter operator()(OutIter out) const
391 {
392 return format::format_to(
393 print_type_helper<T[n]>{}(std::move(out)),
394 "[{}]",
395 m);
396 }
397 };
398}
399
401{
402 template <typename T>
404 {
405 public:
406 template <print_iterator OutIter>
407 constexpr OutIter operator()(OutIter out) const
408 {
409 return type::detail::print_type_helper<T>{}(std::move(out));
410 }
411
412 [[nodiscard]]
414 {
415 StringStreamT stream{};
416 std::invoke(*this, std::ostreambuf_iterator{stream});
417 return std::move(stream).str();
418 }
419 };
420}
421
423{
473
477 template <typename T>
478 [[maybe_unused]] inline constexpr printing::PrintTypeFn<T> print_type{};
479
483}
484
485#endif
#define MIMICPP_DETAIL_CONSTEXPR_STRING
Definition Config.hpp:60
#define MIMICPP_DETAIL_MODULE_EXPORT
Definition Config.hpp:19
Definition PrintType.hpp:404
constexpr OutIter operator()(OutIter out) const
Definition PrintType.hpp:407
StringT operator()() const
Definition PrintType.hpp:413
Definition NamePrintVisitor.hpp:53
constexpr void parse_function()
Definition NameParser.hpp:50
constexpr void parse_type()
Definition NameParser.hpp:40
Definition Format.hpp:38
Definition NameParserTokens.hpp:27
StringT type_name()
Returns the (potentially demangled) name.
Definition PrintType.hpp:201
MIMICPP_DETAIL_CONSTEXPR_STRING OutIter prettify_type(OutIter out, StringT name)
Prettifies a demangled name.
Definition PrintType.hpp:207
MIMICPP_DETAIL_CONSTEXPR_STRING OutIter prettify_function(OutIter out, StringT name)
Prettifies a function name produces by e.g. std::source_location::function_name().
Definition PrintType.hpp:213
constexpr printing::PrintTypeFn< T > print_type
Functional object, converting the given type to its textual representation.
Definition PrintType.hpp:478
std::array constexpr rest
Definition NameLexer.hpp:61
auto constexpr is_space
Definition NameLexer.hpp:28
Definition Fwd.hpp:54
Definition Fwd.hpp:31
constexpr std::ranges::borrowed_iterator_t< Range > find_closing_token(Range &&str, std::ranges::range_value_t< Range > const &openingToken, std::ranges::range_value_t< Range > const &closingToken)
Finds the next closing token in the given string.
Definition Algorithm.hpp:100
Definition Call.hpp:24
std::basic_ostringstream< CharT, CharTraitsT > StringStreamT
Definition Format.hpp:35
std::basic_string< CharT, CharTraitsT > StringT
Definition Fwd.hpp:391