Line data Source code
1 1 : // Distributed under the MIT License.
2 : // See LICENSE.txt for details.
3 :
4 : /// \file
5 : /// Contains a pretty_type library to write types in a "pretty" format
6 :
7 : #pragma once
8 :
9 : #include <boost/core/demangle.hpp>
10 : #include <deque>
11 : #include <forward_list>
12 : #include <list>
13 : #include <map>
14 : #include <memory>
15 : #include <queue>
16 : #include <set>
17 : #include <sstream>
18 : #include <stack>
19 : #include <string>
20 : #include <type_traits>
21 : #include <typeinfo>
22 : #include <unordered_map>
23 : #include <unordered_set>
24 : #include <vector>
25 :
26 : #include "Utilities/Requires.hpp"
27 : #include "Utilities/TMPL.hpp"
28 : #include "Utilities/TypeTraits/ArraySize.hpp"
29 : #include "Utilities/TypeTraits/IsA.hpp"
30 : #include "Utilities/TypeTraits/IsStdArray.hpp"
31 :
32 : /// \cond
33 : #define PRETTY_TYPE_USE_BOOST
34 : /// \endcond
35 :
36 : /*!
37 : * \ingroup PrettyTypeGroup
38 : * \brief Contains all functions that are part of PrettyType, used for printing
39 : * types in a pretty manner.
40 : */
41 1 : namespace pretty_type {
42 : namespace detail {
43 : using str_const = const char* const;
44 :
45 : template <typename T>
46 : struct Type;
47 :
48 : template <>
49 : struct Type<char> {
50 : using type = char;
51 : static constexpr str_const type_name = {"char"};
52 : };
53 :
54 : template <>
55 : struct Type<signed char> {
56 : using type = signed char;
57 : static constexpr str_const type_name = {"signed char"};
58 : };
59 :
60 : template <>
61 : struct Type<unsigned char> {
62 : using type = unsigned char;
63 : static constexpr str_const type_name = {"unsigned char"};
64 : };
65 :
66 : template <>
67 : struct Type<wchar_t> {
68 : using type = wchar_t;
69 : static constexpr str_const type_name = {"wchar_t"};
70 : };
71 :
72 : template <>
73 : struct Type<char16_t> {
74 : using type = char16_t;
75 : static constexpr str_const type_name = {"char16_t"};
76 : };
77 :
78 : template <>
79 : struct Type<char32_t> {
80 : using type = char32_t;
81 : static constexpr str_const type_name = {"char32_t"};
82 : };
83 :
84 : template <>
85 : struct Type<int> {
86 : using type = int;
87 : static constexpr str_const type_name = {"int"};
88 : };
89 :
90 : template <>
91 : struct Type<unsigned int> {
92 : using type = unsigned int;
93 : static constexpr str_const type_name = {"unsigned int"};
94 : };
95 :
96 : template <>
97 : struct Type<long> {
98 : using type = long;
99 : static constexpr str_const type_name = {"long"};
100 : };
101 :
102 : template <>
103 : struct Type<unsigned long> {
104 : using type = unsigned long;
105 : static constexpr str_const type_name = {"unsigned long"};
106 : };
107 :
108 : template <>
109 : struct Type<long long> {
110 : using type = long long;
111 : static constexpr str_const type_name = {"long long"};
112 : };
113 :
114 : template <>
115 : struct Type<unsigned long long> {
116 : using type = unsigned long long;
117 : static constexpr str_const type_name = {"unsigned long long"};
118 : };
119 :
120 : template <>
121 : struct Type<short> {
122 : using type = short;
123 : static constexpr str_const type_name = {"short"};
124 : };
125 :
126 : template <>
127 : struct Type<unsigned short> {
128 : using type = unsigned short;
129 : static constexpr str_const type_name = {"unsigned short"};
130 : };
131 :
132 : template <>
133 : struct Type<float> {
134 : using type = float;
135 : static constexpr str_const type_name = {"float"};
136 : };
137 :
138 : template <>
139 : struct Type<double> {
140 : using type = double;
141 : static constexpr str_const type_name = {"double"};
142 : };
143 :
144 : template <>
145 : struct Type<long double> {
146 : using type = long double;
147 : static constexpr str_const type_name = {"long double"};
148 : };
149 :
150 : template <>
151 : struct Type<bool> {
152 : using type = bool;
153 : static constexpr str_const type_name = {"bool"};
154 : };
155 :
156 : template <>
157 : struct Type<void> {
158 : using type = void;
159 : static constexpr str_const type_name = {"void"};
160 : };
161 :
162 : template <>
163 : struct Type<std::string> {
164 : using type = std::string;
165 : static constexpr str_const type_name = {"std::string"};
166 : };
167 :
168 : template <typename... T>
169 : using TemplateMap_t = tmpl::map<tmpl::pair<T, Type<T>>...>;
170 :
171 : template <typename T>
172 : std::string add_qualifiers() {
173 : std::stringstream ss;
174 : if (std::is_pointer<T>::value) {
175 : if (std::is_const<std::remove_pointer_t<T>>::value) {
176 : ss << " const";
177 : }
178 : if (std::is_volatile<std::remove_pointer_t<T>>::value) {
179 : ss << " volatile";
180 : }
181 : ss << "*";
182 : }
183 : if (std::is_const<std::remove_reference_t<T>>::value) {
184 : ss << " const";
185 : }
186 : if (std::is_volatile<std::remove_reference_t<T>>::value) {
187 : ss << " volatile";
188 : }
189 : if (std::is_reference<T>::value) {
190 : ss << "&";
191 : }
192 : return ss.str();
193 : }
194 :
195 : /*!
196 : * \ingroup PrettyTypeGroup
197 : * Used to construct the name of a container
198 : *
199 : * \tparam T the type whose name to print
200 : * \tparam M the map of the basic types to print
201 : * \tparam KT the struct holding the template alias template_list which is a
202 : * list of known specializations of construct_name for those containers
203 : */
204 : template <typename T, typename M, typename KT, typename = std::nullptr_t>
205 : struct construct_name;
206 : template <typename T, typename M, typename KT>
207 : struct construct_name<
208 : T, M, KT,
209 : Requires<tmpl::has_key<M, std::decay_t<std::remove_pointer_t<T>>>::value ==
210 : 1>> {
211 : static std::string get() {
212 : constexpr str_const t =
213 : tmpl::at<M, std::decay_t<std::remove_pointer_t<T>>>::type_name;
214 : std::stringstream ss;
215 : ss << t << add_qualifiers<T>();
216 : return ss.str();
217 : }
218 : };
219 :
220 : template <typename T, typename M, typename KT>
221 : struct construct_name<
222 : T, M, KT,
223 : Requires<
224 : tmpl::has_key<M, std::decay_t<std::remove_reference_t<
225 : std::remove_pointer_t<T>>>>::value == 0 and
226 : std::is_same<
227 : tmpl::list<>,
228 : tmpl::find<typename KT::template template_list<std::decay_t<
229 : std::remove_reference_t<std::remove_pointer_t<T>>>>,
230 : std::is_base_of<std::true_type, tmpl::_1>>>::value>> {
231 : static std::string get() {
232 : std::stringstream ss;
233 : #if defined(PRETTY_TYPE_USE_BOOST)
234 : ss << boost::core::demangle(typeid(T).name());
235 : #else
236 : ss << typeid(T).name();
237 : #endif
238 : return ss.str();
239 : }
240 : };
241 :
242 : // STL Sequences
243 : template <typename T, typename M, typename KT>
244 : struct construct_name<
245 : T, M, KT,
246 : Requires<tt::is_a_v<std::vector, std::decay_t<std::remove_reference_t<
247 : std::remove_pointer_t<T>>>>>> {
248 : using type = std::decay_t<std::remove_pointer_t<T>>;
249 : static std::string get() {
250 : std::stringstream ss;
251 : ss << "std::vector<"
252 : << construct_name<
253 : std::decay_t<std::remove_pointer_t<typename type::value_type>>, M,
254 : KT>::get();
255 : ss << add_qualifiers<typename type::value_type>() << ">";
256 : ss << add_qualifiers<T>();
257 : return ss.str();
258 : }
259 : };
260 :
261 : template <typename T, typename M, typename KT>
262 : struct construct_name<
263 : T, M, KT,
264 : Requires<tt::is_std_array_v<
265 : std::decay_t<std::remove_reference_t<std::remove_pointer_t<T>>>>>> {
266 : using type = std::decay_t<std::remove_reference_t<std::remove_pointer_t<T>>>;
267 : static std::string get() {
268 : std::stringstream ss;
269 : ss << "std::array<"
270 : << construct_name<
271 : std::decay_t<std::remove_pointer_t<typename type::value_type>>, M,
272 : KT>::get();
273 : ss << add_qualifiers<typename type::value_type>();
274 : ss << ", " << tt::array_size<type>::value << ">";
275 : ss << add_qualifiers<T>();
276 : return ss.str();
277 : }
278 : };
279 :
280 : template <typename T, typename M, typename KT>
281 : struct construct_name<
282 : T, M, KT,
283 : Requires<tt::is_a_v<std::deque, std::decay_t<std::remove_reference_t<
284 : std::remove_pointer_t<T>>>>>> {
285 : using type = std::decay_t<std::remove_pointer_t<T>>;
286 : static std::string get() {
287 : std::stringstream ss;
288 : ss << "std::deque<"
289 : << construct_name<
290 : std::decay_t<std::remove_pointer_t<typename type::value_type>>, M,
291 : KT>::get();
292 : ss << add_qualifiers<typename type::value_type>() << ">";
293 : ss << add_qualifiers<T>();
294 : return ss.str();
295 : }
296 : };
297 :
298 : template <typename T, typename M, typename KT>
299 : struct construct_name<
300 : T, M, KT,
301 : Requires<tt::is_a_v<std::forward_list, std::decay_t<std::remove_reference_t<
302 : std::remove_pointer_t<T>>>>>> {
303 : using type = std::decay_t<std::remove_pointer_t<T>>;
304 : static std::string get() {
305 : std::stringstream ss;
306 : ss << "std::forward_list<"
307 : << construct_name<
308 : std::decay_t<std::remove_pointer_t<typename type::value_type>>, M,
309 : KT>::get();
310 : ss << add_qualifiers<typename type::value_type>() << ">";
311 : ss << add_qualifiers<T>();
312 : return ss.str();
313 : }
314 : };
315 :
316 : template <typename T, typename M, typename KT>
317 : struct construct_name<
318 : T, M, KT,
319 : Requires<tt::is_a_v<std::list, std::decay_t<std::remove_reference_t<
320 : std::remove_pointer_t<T>>>>>> {
321 : using type = std::decay_t<std::remove_pointer_t<T>>;
322 : static std::string get() {
323 : std::stringstream ss;
324 : ss << "std::list<"
325 : << construct_name<
326 : std::decay_t<std::remove_pointer_t<typename type::value_type>>, M,
327 : KT>::get();
328 : ss << add_qualifiers<typename type::value_type>() << ">";
329 : ss << add_qualifiers<T>();
330 : return ss.str();
331 : }
332 : };
333 :
334 : // STL Associative containers
335 : template <typename T, typename M, typename KT>
336 : struct construct_name<
337 : T, M, KT,
338 : Requires<tt::is_a_v<std::map, std::decay_t<std::remove_reference_t<
339 : std::remove_pointer_t<T>>>>>> {
340 : using type = std::decay_t<std::remove_reference_t<std::remove_pointer_t<T>>>;
341 : static std::string get() {
342 : std::stringstream ss;
343 : ss << "std::map<"
344 : << construct_name<
345 : std::decay_t<std::remove_pointer_t<typename type::key_type>>, M,
346 : KT>::get()
347 : << add_qualifiers<typename type::key_type>() << ", "
348 : << construct_name<
349 : std::decay_t<std::remove_pointer_t<typename type::mapped_type>>,
350 : M, KT>::get()
351 : << add_qualifiers<typename type::mapped_type>() << ">";
352 : ss << add_qualifiers<T>();
353 : return ss.str();
354 : }
355 : };
356 :
357 : template <typename T, typename M, typename KT>
358 : struct construct_name<
359 : T, M, KT,
360 : Requires<tt::is_a_v<std::multimap, std::decay_t<std::remove_reference_t<
361 : std::remove_pointer_t<T>>>>>> {
362 : using type = std::decay_t<std::remove_reference_t<std::remove_pointer_t<T>>>;
363 : static std::string get() {
364 : std::stringstream ss;
365 : ss << "std::multimap<"
366 : << construct_name<
367 : std::decay_t<std::remove_pointer_t<typename type::key_type>>, M,
368 : KT>::get()
369 : << add_qualifiers<typename type::key_type>() << ", "
370 : << construct_name<
371 : std::decay_t<std::remove_pointer_t<typename type::mapped_type>>,
372 : M, KT>::get()
373 : << add_qualifiers<typename type::mapped_type>() << ">";
374 : ss << add_qualifiers<T>();
375 : return ss.str();
376 : }
377 : };
378 :
379 : template <typename T, typename M, typename KT>
380 : struct construct_name<
381 : T, M, KT,
382 : Requires<tt::is_a_v<std::multiset, std::decay_t<std::remove_reference_t<
383 : std::remove_pointer_t<T>>>>>> {
384 : using type = std::decay_t<std::remove_reference_t<std::remove_pointer_t<T>>>;
385 : static std::string get() {
386 : std::stringstream ss;
387 : ss << "std::multiset<"
388 : << construct_name<
389 : std::decay_t<std::remove_pointer_t<typename type::key_type>>, M,
390 : KT>::get()
391 : << add_qualifiers<typename type::key_type>() << ">";
392 : ss << add_qualifiers<T>();
393 : return ss.str();
394 : }
395 : };
396 :
397 : template <typename T, typename M, typename KT>
398 : struct construct_name<
399 : T, M, KT,
400 : Requires<tt::is_a_v<std::set, std::decay_t<std::remove_reference_t<
401 : std::remove_pointer_t<T>>>>>> {
402 : using type = std::decay_t<std::remove_reference_t<std::remove_pointer_t<T>>>;
403 : static std::string get() {
404 : std::stringstream ss;
405 : ss << "std::set<"
406 : << construct_name<
407 : std::decay_t<std::remove_pointer_t<typename type::key_type>>, M,
408 : KT>::get()
409 : << add_qualifiers<typename type::key_type>() << ">";
410 : ss << add_qualifiers<T>();
411 : return ss.str();
412 : }
413 : };
414 :
415 : // STL Unordered associative containers
416 :
417 : template <typename T, typename M, typename KT>
418 : struct construct_name<
419 : T, M, KT,
420 : Requires<tt::is_a_v<
421 : std::unordered_map,
422 : std::decay_t<std::remove_reference_t<std::remove_pointer_t<T>>>>>> {
423 : using type = std::decay_t<std::remove_reference_t<std::remove_pointer_t<T>>>;
424 : static std::string get() {
425 : std::stringstream ss;
426 : ss << "std::unordered_map<"
427 : << construct_name<
428 : std::decay_t<std::remove_pointer_t<typename type::key_type>>, M,
429 : KT>::get()
430 : << add_qualifiers<typename type::key_type>() << ", "
431 : << construct_name<
432 : std::decay_t<std::remove_pointer_t<typename type::mapped_type>>,
433 : M, KT>::get()
434 : << add_qualifiers<typename type::mapped_type>() << ">";
435 : ss << add_qualifiers<T>();
436 : return ss.str();
437 : }
438 : };
439 :
440 : template <typename T, typename M, typename KT>
441 : struct construct_name<
442 : T, M, KT,
443 : Requires<tt::is_a_v<
444 : std::unordered_multimap,
445 : std::decay_t<std::remove_reference_t<std::remove_pointer_t<T>>>>>> {
446 : using type = std::decay_t<std::remove_reference_t<std::remove_pointer_t<T>>>;
447 : static std::string get() {
448 : std::stringstream ss;
449 : ss << "std::unordered_multimap<"
450 : << construct_name<
451 : std::decay_t<std::remove_pointer_t<typename type::key_type>>, M,
452 : KT>::get()
453 : << add_qualifiers<typename type::key_type>() << ", "
454 : << construct_name<
455 : std::decay_t<std::remove_pointer_t<typename type::mapped_type>>,
456 : M, KT>::get()
457 : << add_qualifiers<typename type::mapped_type>() << ">";
458 : ss << add_qualifiers<T>();
459 : return ss.str();
460 : }
461 : };
462 :
463 : template <typename T, typename M, typename KT>
464 : struct construct_name<
465 : T, M, KT,
466 : Requires<tt::is_a_v<
467 : std::unordered_multiset,
468 : std::decay_t<std::remove_reference_t<std::remove_pointer_t<T>>>>>> {
469 : using type = std::decay_t<std::remove_reference_t<std::remove_pointer_t<T>>>;
470 : static std::string get() {
471 : std::stringstream ss;
472 : ss << "std::unordered_multiset<"
473 : << construct_name<
474 : std::decay_t<std::remove_pointer_t<typename type::key_type>>, M,
475 : KT>::get()
476 : << add_qualifiers<typename type::key_type>() << ">";
477 : ss << add_qualifiers<T>();
478 : return ss.str();
479 : }
480 : };
481 :
482 : template <typename T, typename M, typename KT>
483 : struct construct_name<
484 : T, M, KT,
485 : Requires<tt::is_a_v<
486 : std::unordered_set,
487 : std::decay_t<std::remove_reference_t<std::remove_pointer_t<T>>>>>> {
488 : using type = std::decay_t<std::remove_reference_t<std::remove_pointer_t<T>>>;
489 : static std::string get() {
490 : std::stringstream ss;
491 : ss << "std::unordered_set<"
492 : << construct_name<
493 : std::decay_t<std::remove_pointer_t<typename type::key_type>>, M,
494 : KT>::get()
495 : << add_qualifiers<typename type::key_type>() << ">";
496 : ss << add_qualifiers<T>();
497 : return ss.str();
498 : }
499 : };
500 :
501 : // STL Container adaptors
502 : template <typename T, typename M, typename KT>
503 : struct construct_name<
504 : T, M, KT,
505 : Requires<tt::is_a_v<
506 : std::priority_queue,
507 : std::decay_t<std::remove_reference_t<std::remove_pointer_t<T>>>>>> {
508 : using type = std::decay_t<std::remove_reference_t<std::remove_pointer_t<T>>>;
509 : static std::string get() {
510 : std::stringstream ss;
511 : ss << "std::priority_queue<"
512 : << construct_name<
513 : std::decay_t<std::remove_pointer_t<typename type::value_type>>, M,
514 : KT>::get()
515 : << add_qualifiers<typename type::value_type>() << ", "
516 : << construct_name<std::decay_t<std::remove_pointer_t<
517 : typename type::container_type>>,
518 : M, KT>::get()
519 : << add_qualifiers<typename type::container_type>() << ">";
520 : ss << add_qualifiers<T>();
521 : return ss.str();
522 : }
523 : };
524 :
525 : template <typename T, typename M, typename KT>
526 : struct construct_name<
527 : T, M, KT,
528 : Requires<tt::is_a_v<std::queue, std::decay_t<std::remove_reference_t<
529 : std::remove_pointer_t<T>>>>>> {
530 : using type = std::decay_t<std::remove_reference_t<std::remove_pointer_t<T>>>;
531 : static std::string get() {
532 : std::stringstream ss;
533 : ss << "std::queue<"
534 : << construct_name<
535 : std::decay_t<std::remove_pointer_t<typename type::value_type>>, M,
536 : KT>::get()
537 : << add_qualifiers<typename type::value_type>() << ", "
538 : << construct_name<std::decay_t<std::remove_pointer_t<
539 : typename type::container_type>>,
540 : M, KT>::get()
541 : << add_qualifiers<typename type::container_type>() << ">";
542 : ss << add_qualifiers<T>();
543 : return ss.str();
544 : }
545 : };
546 :
547 : template <typename T, typename M, typename KT>
548 : struct construct_name<
549 : T, M, KT,
550 : Requires<tt::is_a_v<std::stack, std::decay_t<std::remove_reference_t<
551 : std::remove_pointer_t<T>>>>>> {
552 : using type = std::decay_t<std::remove_reference_t<std::remove_pointer_t<T>>>;
553 : static std::string get() {
554 : std::stringstream ss;
555 : ss << "std::stack<"
556 : << construct_name<
557 : std::decay_t<std::remove_pointer_t<typename type::value_type>>, M,
558 : KT>::get()
559 : << add_qualifiers<typename type::value_type>() << ", "
560 : << construct_name<std::decay_t<std::remove_pointer_t<
561 : typename type::container_type>>,
562 : M, KT>::get()
563 : << add_qualifiers<typename type::container_type>() << ">";
564 : ss << add_qualifiers<T>();
565 : return ss.str();
566 : }
567 : };
568 :
569 : // STL Smart pointers
570 : template <typename T, typename M, typename KT>
571 : struct construct_name<
572 : T, M, KT,
573 : Requires<tt::is_a_v<std::unique_ptr, std::decay_t<std::remove_reference_t<
574 : std::remove_pointer_t<T>>>>>> {
575 : using type = std::decay_t<std::remove_reference_t<std::remove_pointer_t<T>>>;
576 : static std::string get() {
577 : std::stringstream ss;
578 : ss << "std::unique_ptr<"
579 : << construct_name<std::decay_t<std::remove_pointer_t<decltype(
580 : *std::declval<type>())>>,
581 : M, KT>::get()
582 : << add_qualifiers<
583 : std::remove_reference_t<decltype(*std::declval<type>())>>()
584 : << ">";
585 : ss << add_qualifiers<T>();
586 : return ss.str();
587 : }
588 : };
589 :
590 : template <typename T, typename M, typename KT>
591 : struct construct_name<
592 : T, M, KT,
593 : Requires<tt::is_a_v<std::shared_ptr, std::decay_t<std::remove_reference_t<
594 : std::remove_pointer_t<T>>>>>> {
595 : using type = std::decay_t<std::remove_reference_t<std::remove_pointer_t<T>>>;
596 : static std::string get() {
597 : std::stringstream ss;
598 : ss << "std::shared_ptr<"
599 : << construct_name<std::decay_t<std::remove_pointer_t<decltype(
600 : *std::declval<type>())>>,
601 : M, KT>::get()
602 : << add_qualifiers<
603 : std::remove_reference_t<decltype(*std::declval<type>())>>()
604 : << ">";
605 : ss << add_qualifiers<T>();
606 : return ss.str();
607 : }
608 : };
609 :
610 : template <typename T, typename M, typename KT>
611 : struct construct_name<
612 : T, M, KT,
613 : Requires<tt::is_a_v<std::weak_ptr, std::decay_t<std::remove_reference_t<
614 : std::remove_pointer_t<T>>>>>> {
615 : using type = std::decay_t<std::remove_reference_t<std::remove_pointer_t<T>>>;
616 : using element_type = typename type::element_type;
617 : static std::string get() {
618 : std::stringstream ss;
619 : ss << "std::weak_ptr<"
620 : << construct_name<std::decay_t<std::remove_pointer_t<element_type>>, M,
621 : KT>::get()
622 : << add_qualifiers<element_type>() << ">";
623 : ss << add_qualifiers<T>();
624 : return ss.str();
625 : }
626 : };
627 : } // namespace detail
628 :
629 : /*!
630 : * \ingroup PrettyTypeGroup
631 : * \brief typelist of basic types that can be pretty printed
632 : *
633 : * These are specializations of tt::Type<T>
634 : */
635 1 : using basics_map =
636 : detail::TemplateMap_t<char, signed char, unsigned char, wchar_t, char16_t,
637 : char32_t, int, unsigned int, long, unsigned long,
638 : long long, unsigned long long, short, unsigned short,
639 : float, double, long double, bool, std::string>;
640 :
641 : /*!
642 : * \ingroup PrettyTypeGroup
643 : * \brief A list of type traits to check if something is an STL member
644 : *
645 : * Contains a template alias with the name template_list of type traits that
646 : * identify STL containers that can be pretty printed
647 : */
648 1 : struct stl_templates {
649 : /// List of known STL classes that can be pretty printed
650 : template <typename X>
651 1 : using template_list = tmpl::list<
652 : tt::is_a<std::vector, X>, tt::is_std_array<X>, tt::is_a<std::deque, X>,
653 : tt::is_a<std::forward_list, X>, tt::is_a<std::list, X>,
654 : tt::is_a<std::map, X>, tt::is_a<std::set, X>, tt::is_a<std::multiset, X>,
655 : tt::is_a<std::multimap, X>, tt::is_a<std::unordered_map, X>,
656 : tt::is_a<std::unordered_multimap, X>,
657 : tt::is_a<std::unordered_multiset, X>, tt::is_a<std::unordered_set, X>,
658 : tt::is_a<std::priority_queue, X>, tt::is_a<std::queue, X>,
659 : tt::is_a<std::stack, X>, tt::is_a<std::unique_ptr, X>,
660 : tt::is_a<std::shared_ptr, X>, tt::is_a<std::weak_ptr, X>>;
661 : };
662 :
663 : /*!
664 : * \ingroup PrettyTypeGroup
665 : * \brief Returns a string with the prettiest typename known for the type T.
666 : *
667 : * Example usage: auto name = get_name<T>();
668 : *
669 : * \tparam T the type to print
670 : * \tparam Map a tmpl::map of basic types (non-containers) and their Type<T>
671 : * specializations that determine how to print the type name in a pretty form
672 : * \tparam KnownTemplates struct hold template alias tmpl::list of is_... that
673 : * are known how to be printed pretty
674 : * \return std::string containing the typename
675 : */
676 : template <typename T, typename Map = basics_map,
677 : typename KnownTemplates = stl_templates>
678 1 : std::string get_name() {
679 : return detail::construct_name<T, Map, KnownTemplates>::get();
680 : }
681 :
682 : /*!
683 : * \ingroup PrettyTypeGroup
684 : * \brief Returns a string with the prettiest typename known for the runtime
685 : * type of x.
686 : *
687 : * The result will generally not be as pretty as the result of
688 : * get_name, but this function will report the derived type of a class
689 : * when only given a base class reference, which get_type cannot do.
690 : */
691 : template <typename T>
692 1 : std::string get_runtime_type_name(const T& x) {
693 : return boost::core::demangle(typeid(x).name());
694 : }
695 :
696 : namespace detail {
697 : std::string extract_short_name(const std::string& name);
698 : } // namespace detail
699 :
700 : /*!
701 : * \ingroup PrettyTypeGroup
702 : * \brief Return the "short name" of a class, that is, the name
703 : * without template parameters or scopes.
704 : */
705 : template <typename T>
706 1 : std::string short_name() {
707 : return detail::extract_short_name(typeid(T).name());
708 : }
709 :
710 : namespace detail {
711 : template <typename T, typename = std::void_t<>>
712 : struct name_helper {
713 : static std::string name() { return pretty_type::short_name<T>(); }
714 : };
715 :
716 : template <typename T>
717 : struct name_helper<T, std::void_t<decltype(T::name())>> {
718 : static std::string name() { return T::name(); }
719 : };
720 : } // namespace detail
721 :
722 : /// @{
723 : /*!
724 : * \ingroup PrettyTypeGroup
725 : * \brief Return the result of the `name()` member of a class. If a class
726 : * doesn't have a `name()` member, call `pretty_type::short_name<T>()` instead.
727 : *
728 : * \warning Do not use this inside the `name()` member of struct. This
729 : * can lead to recursion as `pretty_type::name<Tag>()` will call the `name()`
730 : * member of the struct.
731 : */
732 : template <typename T>
733 1 : std::string name() {
734 : return detail::name_helper<T>::name();
735 : }
736 :
737 : template <typename T>
738 1 : std::string name(const T& /*unused*/) {
739 : return name<T>();
740 : }
741 : /// @}
742 :
743 : /*!
744 : * \ingroup PrettyTypeGroup
745 : * \brief Return a comma separated list of the `pretty_type::name` of every type
746 : * in a `tmpl::list`.
747 : *
748 : * \note The `tmpl::list` must be flattened.
749 : */
750 : template <typename List>
751 1 : std::string list_of_names() {
752 : static_assert(tt::is_a_v<tmpl::list, List>);
753 : std::stringstream ss{};
754 : bool first_element = true;
755 : tmpl::for_each<List>([&first_element, &ss](auto v) {
756 : using type = tmpl::type_from<decltype(v)>;
757 : static_assert(not tt::is_a_v<tmpl::list, type>,
758 : "The tmpl::list provided to pretty_type::list_of_names must "
759 : "be flattened.");
760 : if (not first_element) {
761 : ss << ", ";
762 : } else {
763 : first_element = false;
764 : }
765 :
766 : ss << pretty_type::name<type>();
767 : });
768 :
769 : return ss.str();
770 : }
771 :
772 : /*!
773 : * \ingroup PrettyTypeGroup
774 : * \brief Return a vector of the `pretty_type::get_name` of every type
775 : * in a `tmpl::list`.
776 : */
777 : template <typename... Types>
778 1 : std::vector<std::string> vector_of_get_names(tmpl::list<Types...> /*meta*/) {
779 : return {pretty_type::get_name<Types>()...};
780 : }
781 : } // namespace pretty_type
|