Drake
nice_type_name.h
Go to the documentation of this file.
1 #pragma once
2 
3 #include <memory>
4 #include <string>
5 #include <typeinfo>
6 #include <utility>
7 #include <vector>
8 
10 
11 namespace drake {
12 
13 /** @brief Obtains canonicalized, platform-independent, human-readable names for
14 arbitrarily-complicated C++ types.
15 
16 Usage: @code
17 // For types:
18 using std::pair; using std::string;
19 using MyVectorType = pair<int,string>;
20 std::cout << "Type MyVectorType was: "
21  << drake::NiceTypeName::Get<MyVectorType>() << std::endl;
22 // Output: std::pair<int,std::string>
23 
24 // For expressions:
25 std::unique_ptr<AbstractThing> thing; // Assume actual type is ConcreteThing.
26 std::cout << "Actual type of 'thing' was: "
27  << drake::NiceTypeName::Get(*thing) << std::endl;
28 // Output: ConcreteThing
29 @endcode
30 
31 We demangle and attempt to canonicalize the compiler-generated type names as
32 reported by `typeid(T).name()` so that the same string is returned by all
33 supported compilers and platforms. The output of NiceTypeName::Get<T>() is
34 useful in error and log messages and testing. It also provides a
35 persistent, platform-independent identifier for types; `std::type_info` cannot
36 provide that.
37 
38 @warning Don't expect usable names for types that are defined in an anonymous
39 namespace or for function-local types. Names will still be produced but they
40 won't be unique, pretty, or compiler-independent.
41 
42 This class exists only to group type name-related static methods; don't try
43 to construct an object of this type. **/
44 class NiceTypeName {
45  public:
46  /** Attempts to return a nicely demangled and canonicalized type name that is
47  the same on all platforms, using Canonicalize(). This is an expensive
48  operation but is only done once per instantiation of NiceTypeName::Get<T>()
49  for a given type `T`. The returned reference will not be deleted even at
50  program termination, so feel free to use it in error messages even in
51  destructors that may be invoked during program tear-down. **/
52  template <typename T>
53  static const std::string& Get() {
54  static const never_destroyed<std::string> canonical(
55  Canonicalize(Demangle(typeid(T).name())));
56  return canonical.access();
57  }
58 
59  /** Returns the type name of the most-derived type of an object of type T,
60  typically but not necessarily polymorphic. This must be calculated on the fly
61  so is expensive whenever called, though very reasonable for use in error
62  messages. For non-polymorphic types this produces the same result as would
63  `Get<decltype(thing)>()` but for polymorphic types the results will
64  differ. **/
65  template <typename T>
66  static std::string Get(const T& thing) {
67  return Canonicalize(Demangle(typeid(thing).name()));
68  }
69 
70  /** Using the algorithm appropriate to the current compiler, demangles a type
71  name as returned by `typeid(T).name()`, with the result hopefully suitable for
72  meaningful display to a human. The result is compiler-dependent.
73  @see Canonicalize() **/
74  static std::string Demangle(const char* typeid_name);
75 
76  /** Given a compiler-dependent demangled type name string as returned by
77  Demangle(), attempts to form a canonicalized representation that will be
78  the same for any compiler. Unnecessary spaces and superfluous keywords like
79  "class" and "struct" are removed. The NiceTypeName::Get<T>() method
80  uses this function to produce a human-friendly type name that is the same on
81  any platform. **/
82  static std::string Canonicalize(const std::string& demangled_name);
83 
84  private:
85  // No instances of this class should be created.
86  NiceTypeName() = delete;
87 };
88 
89 } // namespace drake
Obtains canonicalized, platform-independent, human-readable names for arbitrarily-complicated C++ typ...
Definition: nice_type_name.h:44
Definition: automotive_demo.cc:88
static std::string Canonicalize(const std::string &demangled_name)
Given a compiler-dependent demangled type name string as returned by Demangle(), attempts to form a c...
Definition: nice_type_name.cc:50
static std::string Demangle(const char *typeid_name)
Using the algorithm appropriate to the current compiler, demangles a type name as returned by typeid(...
Definition: nice_type_name.cc:33
static std::string Get(const T &thing)
Returns the type name of the most-derived type of an object of type T, typically but not necessarily ...
Definition: nice_type_name.h:66
static const std::string & Get()
Attempts to return a nicely demangled and canonicalized type name that is the same on all platforms...
Definition: nice_type_name.h:53
Wraps an underlying type T such that its storage is a direct member field of this object (i...
Definition: never_destroyed.h:25
T & access()
Returns the underlying T reference.
Definition: never_destroyed.h:40