Is there a compiler out there that returns the name of a type in a readable fashion (or library providing that functionality or tool). Essentially what I want is the string corresponding to the type expression you'd write it in your source code.
-
2See also: http://stackoverflow.com/questions/281818/unmangling-the-result-of-stdtype-infoname – Flexo Jul 29 '12 at 17:22
-
If it's something like 'what is the type of foo in `auto foo = bar();`' then one option (if your rebuild times are cheap enough) is to force an error, e.g. `struct{}_ = foo;`, such that the error message is helpful enough to tell you the type of `foo`. – Luc Danton Jul 30 '12 at 04:17
-
@LucDanton I have been doing just that, but it's a nuisance. And, since most the times I want to do it doesn't involve "auto" it's not always easy to construct a case where the error message is helpful. – Fred Finkle Jul 30 '12 at 20:39
4 Answers
typeid(var).name()
is what you are looking for. The output differs from compiler to compiler though... For gcc
the output for int
is i
, for unsigned
is j
, for example. Here is a small test program:
#include <iostream>
#include <typeinfo>
struct A { virtual ~A() { } };
struct B : A { };
class C { };
class D : public C { };
int main() {
B b;
A* ap = &b;
A& ar = b;
std::cout << "ap: " << typeid(*ap).name() << std::endl;
std::cout << "ar: " << typeid(ar).name() << std::endl;
D d;
C* cp = &d;
C& cr = d;
std::cout << "cp: " << typeid(*cp).name() << std::endl;
std::cout << "cr: " << typeid(cr).name() << std::endl;
int e;
unsigned f;
char g;
float h;
double i;
std::cout << "int:\t" << typeid(e).name() << std::endl;
std::cout << "unsigned:\t" << typeid(f).name() << std::endl;
std::cout << "char:\t" << typeid(g).name() << std::endl;
std::cout << "float:\t" << typeid(h).name() << std::endl;
std::cout << "double:\t" << typeid(i).name() << std::endl;
}
See also this question: typeid(T).name() alternative in c++11?
-
2There may be compiler-specific tools to demangle the type name returned by 'typeid().name()`. For GCC, for instance, see http://gcc.gnu.org/onlinedocs/libstdc++/manual/ext_demangling.html. – JohannesD Jul 29 '12 at 13:31
-
1@ steffen I know I can I write my own for special cases (starting with the my code), but there's times when I'm reading someone else's code (someone I don't have contact with) and the type expression is complicated or they use "auto" and I have no idea what they are "saying". BTW, the __PRETTY_FUNCTION__ in your link is part of the solution. – Fred Finkle Jul 29 '12 at 13:36
-
@FredFinkle: Ok, I understand... something you can do in this case is compare the return values of `typeid()` to some values of classes or types you assume it could be. Or any class appearing in the code. – steffen Jul 29 '12 at 13:40
-
@JohannesD demangle looks perfect, but when I compile example code it compiles, but doesn't produce the same output. In fact, it doesn't print anything except the string "std::bad_exception". Maybe there's a work around. Thanks. – Fred Finkle Jul 29 '12 at 14:28
-
@JohannesD The example in gcc.gnu.org/onlinedocs/libstdc++/manual/ext_demangling.html has a bug. The line -- realname = abi::__cxa_demangle(e.what(), 0, 0, &status) -- should be something like -- realname = abi::__cxa_demangle(typeid(e).name(), 0, 0, &status). With that change it works perfectly. e.what() is the explanation of the exception not a mangled (or otherwise) name. – Fred Finkle Aug 04 '12 at 19:59
while making search for this question, I have just found what I need in the boost library: boost::core::demangle
IN my case it was for catching exceptions:
try {
//...
} catch (std::exception& e) {
boost::core::scoped_demangled_name demangled(typeid(e).name());
std::cerr << "ERROR: " << demangled.get() << ": " << e.what() << std::endl;
}

- 12,311
- 4
- 24
- 37
Below is a small class that I write to check type. You can add more type to it if needed. It can't check for array types, map, or anything that would be too advance. You can add more types if needed or even add your own custom type. It is just a small sample.
Also, the getType function is what you are looking for. Based on what type it matched, you can custom the output string. I omitted the include part, so for that one you just have to find the right include files as this library is a part of my bigger library.
/* header.hpp */
class _cType
{
public:
_cType();
~_cType();
template<class T, class U>
static bool isSame(T &vl, U &vr);
template<class T>
static bool isInt(T &v);
template<class T>
static bool isUInt(T &v);
template<class T>
static bool isFloat(T &v);
template<class T>
static bool isLong(T &v);
template<class T>
static bool isDouble(T &v);
template<class T>
static bool isBool(T &v);
template<class T>
static bool isString(T &v);
template<class T>
static bool isChar(T &v);
template<class T>
static std::string getType(T &v);
};
extern _cType Type;
/* source.cpp */
_cType::_cType(){};
template<class T, class U>
bool _cType::isSame(T &vl, U &vr){
return ( typeid(vl) == typeid(vr) );
}
template<class T>
bool _cType::isInt(T &v){
return typeid(v) == typeid(int);
}
template<class T>
bool _cType::isUInt(T &v){
return typeid(v) == typeid(unsigned int);
}
template<class T>
bool _cType::isFloat(T &v){
return typeid(v) == typeid(float);
}
template<class T>
bool _cType::isLong(T &v){
return typeid(v) == typeid(long);
}
template<class T>
bool _cType::isDouble(T &v){
return typeid(v) == typeid(double);
}
template<class T>
bool _cType::isBool(T &v){
return typeid(v) == typeid(bool);
}
template<class T>
bool _cType::isString(T &v){
return typeid(v) == typeid(std::string);
}
template<class T>
bool _cType::isChar(T &v){
return typeid(v) == typeid(char);
}
template<class T>
std::string _cType::getType(T &v){
if ( typeid(v) == typeid(int) ) return "int";
else if ( typeid(v) == typeid(unsigned int) ) return "unsigned int";
else if ( typeid(v) == typeid(float) ) return "float";
else if ( typeid(v) == typeid(long) ) return "long";
else if ( typeid(v) == typeid(double) ) return "double";
else if ( typeid(v) == typeid(char) ) return "char";
else if ( typeid(v) == typeid(std::string) ) return "std::string";
else if ( typeid(v) == typeid(bool) ) return "bool";
else return std::string("User defined or unknown type: ") + typeid(v).name();
}
_cType::~_cType(){};
_cType Type;

- 2,146
- 1
- 13
- 18
To answer the letter of your question (where the other answers address its intent), the simplest answer is that Visual C++ provides the "undecorated" (unmangled) name as output for std::type_info::name()
, while hiding the actual, mangled type behind compiler extension std::type_info::raw_name()
; CPPReference also mentions IBM and Oracle as providing demangled, human-readable names, but I have no experience with their compilers, and thus can't myself say whether this claim is accurate.

- 4,149
- 24
- 40