Update 2022 Nov
Godbolt is here: https://godbolt.org/z/h6YK91d54
The code is much improved. The old bad version remains below to shame the author. Usage remains simple
1 2 3 4 5 6 |
int main(void) { printf("\n%s", display_type<int>().data()); printf("\n%s", display_type(42).data()); return EXIT_SUCCESS; } |
That code is C++. On windows I use clang.
Completely different and working approach: https://stackoverflow.com/a/56766138 . Not mine.
Update 2021 Aug
Design decisions explanations. To use this API one has to provide the type.
1 2 3 4 5 |
#define SX(F_, X_) printf("\n%s : " F_, (#X_), (X_)) SX("%s", (dbj::demang< decltype( argv ) >()).data() ); SX("%s", (dbj::demang< basic_string<char> >()).data() ); SX("%s", (dbj::demang< string(*)[42] >()).data() ); |
That does not mean one can not use instances or variables:
1 2 3 4 |
// all of this will compile SX("%s", (dbj::demang(argv)).data() ); SX("%s", (dbj::demang(std::string("string"))).data() ); SX("%s", (dbj::demang( pointer_to_array_of_42_strings).data() ); |
Beware! Here is a deliberate warning for the user. Objects and variables mean instantiation. Default constructors mandate and all that jazz. By sticking to types we stay in the realm of type computing. In C++ that also enables metaprogramming. Although not right now. That is because not before C++23 (hopefully) many more “things” will be constexpr
enabled, and we would be able to declare it as this:
1 2 3 4 |
// maybe c++23 compile time constexpr char const * demang() noexcept ; // compile time usage constexpr auto typename = dbj::demang<bool>() ; |
Also, all the functions used there will have to be constexpr
enabled.
Before we Begin
By the folly of much hacking, one could make it compile-time right now, but that is a path peppered with shards of glass. If you might disagree please submit your code.
There is this much upvoted C++ hack I know about on Stack Overflow. There are even more complex “tricks” too. Be forewarned: every trick is highly dependent on things that might change at random, in every new release of any of the compilers used. Thus no trick is advised, by me. Now back to safe seas.
Update 2021 Apr
Modern times. Godbolt and the proper immediately obvious test online of our boring simple and resilient solution. Here is the full code in case you can not be bothered to follow that Godbolt link. Please read the rest of the prose below. (Isn’t it funny how quickly we forgot both Wandbox and Coliru?)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 |
/* (c) 2018-2021 by dbj@dbj.org -- licence is at eof usage: auto demangled_name = dbj::demang< int (&) [42] >() ; This is both windows and linux code. */ #ifndef _WIN32 #include <cxxabi.h> #endif namespace dbj { #ifdef _WIN32 template <typename T> const char* demang() noexcept { static auto demangled_name = []() { return {typeid(T).name()}; }(); return demangled_name.data(); } #else // __linux__ template <typename T> const char* demang() noexcept { // once per one type static auto demangled_name = []() { int error = 0; std::string retval; char* name = abi::__cxa_demangle(typeid(T).name(), 0, 0, &error); switch (error) { case 0: retval = name; break; case -1: retval = "memory allocation failed"; break; case -2: retval = "not a valid mangled name"; break; default: retval = "__cxa_demangle failed"; break; } std::free(name); return retval; }(); // std::free(name) ; return demangled_name.data(); } #endif // __linux__ // calling with instances template <typename T> const char* demang(T const&) noexcept { return demang<T>(); } } // namespace dbj |
Note the optimization vs the previous version. Since one type has one name for the lifetime of a program above we do that only once and not before requested.
2018 May 24
In case you like to experiment or learn modern C++, you will be needing some R&D little nuggets of your own.
For example. C++ is notorious for its powerful meta-programming capabilities. Thus it is very likely, in your C++ quest, you need to see the name of some type that is giving you a headache, while you are trying to understand SFINAE, no less.
And very likely you are using Stack Overflow to find answers. And over there you realize not all people use your beloved Visual Studio and MSVC. A lot of good C++ programmers/architects do use GCC and clang. After all, clang is in widespread usage in some core C++ teams inside Microsoft too.
So. The little problem in that clang/GCC code is that type names do stay mangled by default.
As an example do the “Run code” here. That is the page on the typeid()
operator, on cppreference.com.
Meaning your MSVC code where you need to see the type name will produce mangled names on those numerous clang/GCC samples.
1 2 3 4 5 |
// some wandbox, coliru, etc. code int main ( int argc, char * argv[] ) { auto mangled_in_clang_gcc = typeid( decltype( argv ) ).name() ; } |
You will need to write a little code (like the one above ) to check this or that, using one of the good online compilers like the Wandbox I am using.
Not to worry. I have written a little function for you, to use when you need to see human-readable names in either MSVC on Windows or clang and GCC on Linux as is the Wandbox or Coliru, runtime, and platform.
Here it is
The usage is explained in the code. And here:
1 2 3 4 |
int main ( int argc, char * argv[] ) { auto human_readable_type_name = dbj::demang< decltype( argv ) >() ; } |
I do prefer Wandbox also because one can add headers, so I just add the code as a header. For Coliru you have only one file (AFAIK?) so you will have to copy-paste.