PrettyType.hpp
Go to the documentation of this file.
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 <typeinfo>
21 #include <unordered_map>
22 #include <unordered_set>
23 #include <vector>
24 
25 #include "Utilities/Requires.hpp"
26 #include "Utilities/TMPL.hpp"
27 #include "Utilities/TypeTraits.hpp"
28 
29 /// \cond
30 #define PRETTY_TYPE_USE_BOOST
31 /// \endcond
32 
33 /*!
34  * \ingroup PrettyTypeGroup
35  * \brief Contains all functions that are part of PrettyType, used for printing
36  * types in a pretty manner.
37  */
38 namespace pretty_type {
39 namespace detail {
40 using str_const = const char* const;
41 
42 template <typename T>
43 struct Type;
44 
45 template <>
46 struct Type<char> {
47  using type = char;
48  static constexpr str_const type_name = {"char"};
49 };
50 
51 template <>
52 struct Type<signed char> {
53  using type = signed char;
54  static constexpr str_const type_name = {"signed char"};
55 };
56 
57 template <>
58 struct Type<unsigned char> {
59  using type = unsigned char;
60  static constexpr str_const type_name = {"unsigned char"};
61 };
62 
63 template <>
64 struct Type<wchar_t> {
65  using type = wchar_t;
66  static constexpr str_const type_name = {"wchar_t"};
67 };
68 
69 template <>
70 struct Type<char16_t> {
71  using type = char16_t;
72  static constexpr str_const type_name = {"char16_t"};
73 };
74 
75 template <>
76 struct Type<char32_t> {
77  using type = char32_t;
78  static constexpr str_const type_name = {"char32_t"};
79 };
80 
81 template <>
82 struct Type<int> {
83  using type = int;
84  static constexpr str_const type_name = {"int"};
85 };
86 
87 template <>
88 struct Type<unsigned int> {
89  using type = unsigned int;
90  static constexpr str_const type_name = {"unsigned int"};
91 };
92 
93 template <>
94 struct Type<long> {
95  using type = long;
96  static constexpr str_const type_name = {"long"};
97 };
98 
99 template <>
100 struct Type<unsigned long> {
101  using type = unsigned long;
102  static constexpr str_const type_name = {"unsigned long"};
103 };
104 
105 template <>
106 struct Type<long long> {
107  using type = long long;
108  static constexpr str_const type_name = {"long long"};
109 };
110 
111 template <>
112 struct Type<unsigned long long> {
113  using type = unsigned long long;
114  static constexpr str_const type_name = {"unsigned long long"};
115 };
116 
117 template <>
118 struct Type<short> {
119  using type = short;
120  static constexpr str_const type_name = {"short"};
121 };
122 
123 template <>
124 struct Type<unsigned short> {
125  using type = unsigned short;
126  static constexpr str_const type_name = {"unsigned short"};
127 };
128 
129 template <>
130 struct Type<float> {
131  using type = float;
132  static constexpr str_const type_name = {"float"};
133 };
134 
135 template <>
136 struct Type<double> {
137  using type = double;
138  static constexpr str_const type_name = {"double"};
139 };
140 
141 template <>
142 struct Type<long double> {
143  using type = long double;
144  static constexpr str_const type_name = {"long double"};
145 };
146 
147 template <>
148 struct Type<bool> {
149  using type = bool;
150  static constexpr str_const type_name = {"bool"};
151 };
152 
153 template <>
154 struct Type<void> {
155  using type = void;
156  static constexpr str_const type_name = {"void"};
157 };
158 
159 template <>
160 struct Type<std::string> {
161  using type = std::string;
162  static constexpr str_const type_name = {"std::string"};
163 };
164 
165 template <typename... T>
166 using TemplateMap_t = tmpl::map<tmpl::pair<T, Type<T>>...>;
167 
168 template <typename T>
169 std::string add_qualifiers() {
173  ss << " const";
174  }
176  ss << " volatile";
177  }
178  ss << "*";
179  }
181  ss << " const";
182  }
184  ss << " volatile";
185  }
187  ss << "&";
188  }
189  return ss.str();
190 }
191 
192 /*!
193  * \ingroup PrettyTypeGroup
194  * Used to construct the name of a container
195  *
196  * \tparam T the type whose name to print
197  * \tparam M the map of the basic types to print
198  * \tparam KT the struct holding the template alias template_list which is a
199  * list of known specializations of construct_name for those containers
200  */
201 template <typename T, typename M, typename KT, typename = std::nullptr_t>
202 struct construct_name;
203 template <typename T, typename M, typename KT>
204 struct construct_name<
205  T, M, KT,
206  Requires<tmpl::has_key<M, std::decay_t<std::remove_pointer_t<T>>>::value ==
207  1>> {
208  static std::string get() {
209  constexpr str_const t =
210  tmpl::at<M, std::decay_t<std::remove_pointer_t<T>>>::type_name;
212  ss << t << add_qualifiers<T>();
213  return ss.str();
214  }
215 };
216 
217 template <typename T, typename M, typename KT>
218 struct construct_name<
219  T, M, KT,
220  Requires<
221  tmpl::has_key<M, std::decay_t<std::remove_reference_t<
222  std::remove_pointer_t<T>>>>::value == 0 and
223  std::is_same<
224  tmpl::list<>,
225  tmpl::find<typename KT::template template_list<std::decay_t<
226  std::remove_reference_t<std::remove_pointer_t<T>>>>,
227  std::is_base_of<std::true_type, tmpl::_1>>>::value>> {
228  static std::string get() {
230 #if defined(PRETTY_TYPE_USE_BOOST)
231  ss << boost::core::demangle(typeid(T).name());
232 #else
233  ss << typeid(T).name();
234 #endif
235  return ss.str();
236  }
237 };
238 
239 // STL Sequences
240 template <typename T, typename M, typename KT>
241 struct construct_name<
242  T, M, KT,
243  Requires<tt::is_a_v<std::vector, std::decay_t<std::remove_reference_t<
244  std::remove_pointer_t<T>>>>>> {
246  static std::string get() {
248  ss << "std::vector<"
249  << construct_name<
251  KT>::get();
252  ss << add_qualifiers<typename type::value_type>() << ">";
253  ss << add_qualifiers<T>();
254  return ss.str();
255  }
256 };
257 
258 template <typename T, typename M, typename KT>
259 struct construct_name<
260  T, M, KT, Requires<tt::is_std_array_v<std::decay_t<
261  std::remove_reference_t<std::remove_pointer_t<T>>>>>> {
263  static std::string get() {
265  ss << "std::array<"
266  << construct_name<
268  KT>::get();
269  ss << add_qualifiers<typename type::value_type>();
270  ss << ", " << tt::array_size<type>::value << ">";
271  ss << add_qualifiers<T>();
272  return ss.str();
273  }
274 };
275 
276 template <typename T, typename M, typename KT>
277 struct construct_name<
278  T, M, KT,
279  Requires<tt::is_a_v<std::deque, std::decay_t<std::remove_reference_t<
280  std::remove_pointer_t<T>>>>>> {
282  static std::string get() {
284  ss << "std::deque<"
285  << construct_name<
287  KT>::get();
288  ss << add_qualifiers<typename type::value_type>() << ">";
289  ss << add_qualifiers<T>();
290  return ss.str();
291  }
292 };
293 
294 template <typename T, typename M, typename KT>
295 struct construct_name<
296  T, M, KT,
297  Requires<tt::is_a_v<std::forward_list, std::decay_t<std::remove_reference_t<
298  std::remove_pointer_t<T>>>>>> {
300  static std::string get() {
302  ss << "std::forward_list<"
303  << construct_name<
305  KT>::get();
306  ss << add_qualifiers<typename type::value_type>() << ">";
307  ss << add_qualifiers<T>();
308  return ss.str();
309  }
310 };
311 
312 template <typename T, typename M, typename KT>
313 struct construct_name<
314  T, M, KT,
315  Requires<tt::is_a_v<std::list, std::decay_t<std::remove_reference_t<
316  std::remove_pointer_t<T>>>>>> {
318  static std::string get() {
320  ss << "std::list<"
321  << construct_name<
323  KT>::get();
324  ss << add_qualifiers<typename type::value_type>() << ">";
325  ss << add_qualifiers<T>();
326  return ss.str();
327  }
328 };
329 
330 // STL Associative containers
331 template <typename T, typename M, typename KT>
332 struct construct_name<
333  T, M, KT,
334  Requires<tt::is_a_v<std::map, std::decay_t<std::remove_reference_t<
335  std::remove_pointer_t<T>>>>>> {
337  static std::string get() {
339  ss << "std::map<"
340  << construct_name<
342  KT>::get()
343  << add_qualifiers<typename type::key_type>() << ", "
344  << construct_name<
346  M, KT>::get()
347  << add_qualifiers<typename type::mapped_type>() << ">";
348  ss << add_qualifiers<T>();
349  return ss.str();
350  }
351 };
352 
353 template <typename T, typename M, typename KT>
354 struct construct_name<
355  T, M, KT,
356  Requires<tt::is_a_v<std::multimap, std::decay_t<std::remove_reference_t<
357  std::remove_pointer_t<T>>>>>> {
359  static std::string get() {
361  ss << "std::multimap<"
362  << construct_name<
364  KT>::get()
365  << add_qualifiers<typename type::key_type>() << ", "
366  << construct_name<
368  M, KT>::get()
369  << add_qualifiers<typename type::mapped_type>() << ">";
370  ss << add_qualifiers<T>();
371  return ss.str();
372  }
373 };
374 
375 template <typename T, typename M, typename KT>
376 struct construct_name<
377  T, M, KT,
378  Requires<tt::is_a_v<std::multiset, std::decay_t<std::remove_reference_t<
379  std::remove_pointer_t<T>>>>>> {
381  static std::string get() {
383  ss << "std::multiset<"
384  << construct_name<
386  KT>::get()
387  << add_qualifiers<typename type::key_type>() << ">";
388  ss << add_qualifiers<T>();
389  return ss.str();
390  }
391 };
392 
393 template <typename T, typename M, typename KT>
394 struct construct_name<
395  T, M, KT,
396  Requires<tt::is_a_v<std::set, std::decay_t<std::remove_reference_t<
397  std::remove_pointer_t<T>>>>>> {
399  static std::string get() {
401  ss << "std::set<"
402  << construct_name<
404  KT>::get()
405  << add_qualifiers<typename type::key_type>() << ">";
406  ss << add_qualifiers<T>();
407  return ss.str();
408  }
409 };
410 
411 // STL Unordered associative containers
412 
413 template <typename T, typename M, typename KT>
414 struct construct_name<
415  T, M, KT,
416  Requires<tt::is_a_v<
417  std::unordered_map,
418  std::decay_t<std::remove_reference_t<std::remove_pointer_t<T>>>>>> {
420  static std::string get() {
422  ss << "std::unordered_map<"
423  << construct_name<
425  KT>::get()
426  << add_qualifiers<typename type::key_type>() << ", "
427  << construct_name<
429  M, KT>::get()
430  << add_qualifiers<typename type::mapped_type>() << ">";
431  ss << add_qualifiers<T>();
432  return ss.str();
433  }
434 };
435 
436 template <typename T, typename M, typename KT>
437 struct construct_name<
438  T, M, KT,
439  Requires<tt::is_a_v<
440  std::unordered_multimap,
441  std::decay_t<std::remove_reference_t<std::remove_pointer_t<T>>>>>> {
443  static std::string get() {
445  ss << "std::unordered_multimap<"
446  << construct_name<
448  KT>::get()
449  << add_qualifiers<typename type::key_type>() << ", "
450  << construct_name<
452  M, KT>::get()
453  << add_qualifiers<typename type::mapped_type>() << ">";
454  ss << add_qualifiers<T>();
455  return ss.str();
456  }
457 };
458 
459 template <typename T, typename M, typename KT>
460 struct construct_name<
461  T, M, KT,
462  Requires<tt::is_a_v<
463  std::unordered_multiset,
464  std::decay_t<std::remove_reference_t<std::remove_pointer_t<T>>>>>> {
466  static std::string get() {
468  ss << "std::unordered_multiset<"
469  << construct_name<
471  KT>::get()
472  << add_qualifiers<typename type::key_type>() << ">";
473  ss << add_qualifiers<T>();
474  return ss.str();
475  }
476 };
477 
478 template <typename T, typename M, typename KT>
479 struct construct_name<
480  T, M, KT,
481  Requires<tt::is_a_v<
482  std::unordered_set,
483  std::decay_t<std::remove_reference_t<std::remove_pointer_t<T>>>>>> {
485  static std::string get() {
487  ss << "std::unordered_set<"
488  << construct_name<
490  KT>::get()
491  << add_qualifiers<typename type::key_type>() << ">";
492  ss << add_qualifiers<T>();
493  return ss.str();
494  }
495 };
496 
497 // STL Container adaptors
498 template <typename T, typename M, typename KT>
499 struct construct_name<
500  T, M, KT,
501  Requires<tt::is_a_v<
502  std::priority_queue,
503  std::decay_t<std::remove_reference_t<std::remove_pointer_t<T>>>>>> {
505  static std::string get() {
507  ss << "std::priority_queue<"
508  << construct_name<
510  KT>::get()
511  << add_qualifiers<typename type::value_type>() << ", "
512  << construct_name<std::decay_t<std::remove_pointer_t<
513  typename type::container_type>>,
514  M, KT>::get()
515  << add_qualifiers<typename type::container_type>() << ">";
516  ss << add_qualifiers<T>();
517  return ss.str();
518  }
519 };
520 
521 template <typename T, typename M, typename KT>
522 struct construct_name<
523  T, M, KT,
524  Requires<tt::is_a_v<std::queue, std::decay_t<std::remove_reference_t<
525  std::remove_pointer_t<T>>>>>> {
527  static std::string get() {
529  ss << "std::queue<"
530  << construct_name<
532  KT>::get()
533  << add_qualifiers<typename type::value_type>() << ", "
534  << construct_name<std::decay_t<std::remove_pointer_t<
535  typename type::container_type>>,
536  M, KT>::get()
537  << add_qualifiers<typename type::container_type>() << ">";
538  ss << add_qualifiers<T>();
539  return ss.str();
540  }
541 };
542 
543 template <typename T, typename M, typename KT>
544 struct construct_name<
545  T, M, KT,
546  Requires<tt::is_a_v<std::stack, std::decay_t<std::remove_reference_t<
547  std::remove_pointer_t<T>>>>>> {
549  static std::string get() {
551  ss << "std::stack<"
552  << construct_name<
554  KT>::get()
555  << add_qualifiers<typename type::value_type>() << ", "
556  << construct_name<std::decay_t<std::remove_pointer_t<
557  typename type::container_type>>,
558  M, KT>::get()
559  << add_qualifiers<typename type::container_type>() << ">";
560  ss << add_qualifiers<T>();
561  return ss.str();
562  }
563 };
564 
565 // STL Smart pointers
566 template <typename T, typename M, typename KT>
567 struct construct_name<
568  T, M, KT,
569  Requires<tt::is_a_v<std::unique_ptr, std::decay_t<std::remove_reference_t<
570  std::remove_pointer_t<T>>>>>> {
572  static std::string get() {
574  ss << "std::unique_ptr<"
575  << construct_name<std::decay_t<std::remove_pointer_t<decltype(
576  *std::declval<type>())>>,
577  M, KT>::get()
578  << add_qualifiers<
580  << ">";
581  ss << add_qualifiers<T>();
582  return ss.str();
583  }
584 };
585 
586 template <typename T, typename M, typename KT>
587 struct construct_name<
588  T, M, KT,
589  Requires<tt::is_a_v<std::shared_ptr, std::decay_t<std::remove_reference_t<
590  std::remove_pointer_t<T>>>>>> {
592  static std::string get() {
594  ss << "std::shared_ptr<"
595  << construct_name<std::decay_t<std::remove_pointer_t<decltype(
596  *std::declval<type>())>>,
597  M, KT>::get()
598  << add_qualifiers<
600  << ">";
601  ss << add_qualifiers<T>();
602  return ss.str();
603  }
604 };
605 
606 template <typename T, typename M, typename KT>
607 struct construct_name<
608  T, M, KT,
609  Requires<tt::is_a_v<std::weak_ptr, std::decay_t<std::remove_reference_t<
610  std::remove_pointer_t<T>>>>>> {
612  using element_type = typename type::element_type;
613  static std::string get() {
615  ss << "std::weak_ptr<"
616  << construct_name<std::decay_t<std::remove_pointer_t<element_type>>, M,
617  KT>::get()
618  << add_qualifiers<element_type>() << ">";
619  ss << add_qualifiers<T>();
620  return ss.str();
621  }
622 };
623 } // namespace detail
624 
625 /*!
626  * \ingroup PrettyTypeGroup
627  * \brief typelist of basic types that can be pretty printed
628  *
629  * These are specializations of tt::Type<T>
630  */
631 using basics_map =
632  detail::TemplateMap_t<char, signed char, unsigned char, wchar_t, char16_t,
633  char32_t, int, unsigned int, long, unsigned long,
634  long long, unsigned long long, short, unsigned short,
635  float, double, long double, bool, std::string>;
636 
637 /*!
638  * \ingroup PrettyTypeGroup
639  * \brief A list of type traits to check if something is an STL member
640  *
641  * Contains a template alias with the name template_list of type traits that
642  * identify STL containers that can be pretty printed
643  */
645  /// List of known STL classes that can be pretty printed
646  template <typename X>
647  using template_list = tmpl::list<
657 };
658 
659 /*!
660  * \ingroup PrettyTypeGroup
661  * \brief Returns a string with the prettiest typename known for the type T.
662  *
663  * Example usage: auto name = get_name<T>();
664  *
665  * \tparam T the type to print
666  * \tparam Map a tmpl::map of basic types (non-containers) and their Type<T>
667  * specializations that determine how to print the type name in a pretty form
668  * \tparam KnownTemplates struct hold template alias tmpl::list of is_... that
669  * are known how to be printed pretty
670  * \return std::string containing the typename
671  */
672 template <typename T, typename Map = basics_map,
673  typename KnownTemplates = stl_templates>
674 std::string get_name() {
676 }
677 
678 /*!
679  * \ingroup PrettyTypeGroup
680  * \brief Returns a string with the prettiest typename known for the runtime
681  * type of x.
682  *
683  * The result will generally not be as pretty as the result of
684  * get_name, but this function will report the derived type of a class
685  * when only given a base class reference, which get_type cannot do.
686  */
687 template <typename T>
688 std::string get_runtime_type_name(const T& x) {
689  return boost::core::demangle(typeid(x).name());
690 }
691 
692 /*!
693  * \ingroup PrettyTypeGroup
694  * \brief Extract the "short name" from a name, that is, the name
695  * without template parameters or scopes.
696  */
697 std::string extract_short_name(std::string name);
698 
699 /*!
700  * \ingroup PrettyTypeGroup
701  * \brief Return the "short name" of a class, that is, the name
702  * without template parameters or scopes.
703  */
704 template <typename T>
705 std::string short_name() {
706  return extract_short_name(get_name<T>());
707 }
708 } // namespace pretty_type
tmpl::list< tt::is_a< std::vector, X >, tt::is_std_array< X >, tt::is_a< std::deque, X >, tt::is_a< std::forward_list, X >, tt::is_a< std::list, X >, tt::is_a< std::map, X >, tt::is_a< std::set, X >, tt::is_a< std::multiset, X >, tt::is_a< std::multimap, X >, tt::is_a< std::unordered_map, X >, tt::is_a< std::unordered_multimap, X >, tt::is_a< std::unordered_multiset, X >, tt::is_a< std::unordered_set, X >, tt::is_a< std::priority_queue, X >, tt::is_a< std::queue, X >, tt::is_a< std::stack, X >, tt::is_a< std::unique_ptr, X >, tt::is_a< std::shared_ptr, X >, tt::is_a< std::weak_ptr, X > > template_list
List of known STL classes that can be pretty printed.
Definition: PrettyType.hpp:656
Contains all functions that are part of PrettyType, used for printing types in a pretty manner...
Definition: PrettyType.cpp:9
decltype(TypeTraits_detail::array_size_impl(std::declval< const Array & >())) array_size
Get the size of a std::array as a std::integral_constant.
Definition: TypeTraits.hpp:687
std::string short_name()
Return the "short name" of a class, that is, the name without template parameters or scopes...
Definition: PrettyType.hpp:705
Definition: Digraph.hpp:11
std::string extract_short_name(std::string name)
Extract the "short name" from a name, that is, the name without template parameters or scopes...
Definition: PrettyType.cpp:10
constexpr Tag::type & get(Variables< TagList > &v) noexcept
Return Tag::type pointing into the contiguous array.
Definition: Variables.hpp:649
std::string get_name()
Returns a string with the prettiest typename known for the type T.
Definition: PrettyType.hpp:674
constexpr bool is_std_array_v
Definition: TypeTraits.hpp:451
Defines the type alias Requires.
A collection of useful type traits.
Definition: TensorExpression.hpp:115
Definition: Determinant.hpp:11
constexpr bool is_a_v
Definition: TypeTraits.hpp:543
A list of type traits to check if something is an STL member.
Definition: PrettyType.hpp:644
std::string get_runtime_type_name(const T &x)
Returns a string with the prettiest typename known for the runtime type of x.
Definition: PrettyType.hpp:688
Check if type T is a template specialization of U
Definition: TypeTraits.hpp:536
Check if type T is a std::array.
Definition: TypeTraits.hpp:444
Wraps the template metaprogramming library used (brigand)
typename Requires_detail::requires_impl< B >::template_error_type_failed_to_meet_requirements_on_template_parameters Requires
Express requirements on the template parameters of a function or class, replaces std::enable_if_t ...
Definition: Requires.hpp:67
Defines type traits, some of which are future STL type_traits header.
detail::TemplateMap_t< char, signed char, unsigned char, wchar_t, char16_t, char32_t, int, unsigned int, long, unsigned long, long long, unsigned long long, short, unsigned short, float, double, long double, bool, std::string > basics_map
typelist of basic types that can be pretty printed
Definition: PrettyType.hpp:635