How std::type_info::name Handles Name Mangling in C++
In C++, the std::type_info::name() member function
provides an identifier for a given data type at runtime through Run-Time
Type Information (RTTI). However, the C++ standard does not mandate a
human-readable format, leaving the output implementation-defined.
Consequently, most compilers return the compiler-specific "mangled" name
of the type—a symbol encoded with structural metadata such as
namespaces, template parameters, and qualifiers—rather than its literal
source-code representation. Understanding how
std::type_info::name() produces these decorated names and
how to demangle them is essential for effective runtime type inspection
and debugging.
The Standard
Specification of std::type_info::name
According to the ISO C++ standard,
std::type_info::name() returns a pointer to a
null-terminated string (const char*) that represents the
type. The standard establishes only minimal guarantees:
- The returned pointer remains valid throughout the program execution.
- The string identifies the type, but identical types are only guaranteed to produce equivalent representations within the same execution context.
- The formatting, readability, and content of the string are entirely defined by the implementation (the compiler).
Because the standard avoids dictating a human-readable format, compiler vendors prioritize internal efficiency and linkage semantics, frequently exposing the internal ABI (Application Binary Interface) representation directly.
The Role of Name Mangling
Name mangling is a technique employed by C++ compilers to preserve type information through the compilation and linking phases. Because C++ allows function overloading, namespaces, classes, and templates, the linker requires distinct, unique symbol names that plain C-style identifiers cannot supply.
When std::type_info::name() is invoked, compilers often
return this underlying ABI-level decorated string. The string
encodes:
- Namespaces and class scoping.
- Template arguments and specialization details.
- Type qualifiers such as
const,volatile, and references.
Compiler Implementations: GCC and Clang vs. MSVC
Different toolchains handle std::type_info::name()
distinctly based on their platform ABIs:
GCC and Clang (Itanium C++ ABI)
Compilers adhering to the Itanium C++ ABI (common on Linux, macOS,
and many embedded platforms) return raw mangled symbols from
name().
- Primitive types yield single-character abbreviations:
intproduces"i",doubleproduces"d", andcharproduces"c". - Complex types produce structured symbols:
std::stringappears as a symbol such as"NSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE".
Microsoft Visual C++ (MSVC)
MSVC behaves differently. Its implementation of
std::type_info::name() automatically demangles the internal
name and returns a human-readable string, such as
"class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >".
For access to the raw decorated string under MSVC, the non-standard
member function std::type_info::raw_name() must be called
instead.
Demangling Names at Runtime
Because Itanium ABI implementations expose raw mangled symbols, translating the string into a human-readable format requires compiler-specific runtime utilities.
In GCC and Clang, the C++ runtime provides the
abi::__cxa_demangle function declared in the
<cxxabi.h> header:
#include <iostream>
#include <typeinfo>
#include <cxxabi.h>
#include <memory>
#include <string>
std::string demangle(const char* mangled_name) {
int status = 0;
std::unique_ptr<char, void(*)(void*)> res{
abi::__cxa_demangle(mangled_name, nullptr, nullptr, &status),
std::free
};
return (status == 0) ? res.get() : mangled_name;
}For MSVC, if working directly with decorated names from
raw_name(), the Windows API provides the
UnDecorateSymbolName function through the
DbgHelp.h library.
Portability Considerations
Because std::type_info::name() relies entirely on
implementation-defined behavior, developers should adhere to the
following best practices:
- Avoid Serialization: Do not persist the output of
name()across disk, network, or process boundaries, as strings can change between compiler versions or build flags. - Avoid Control Flow Logic: Do not write conditional
code based on string comparisons of
name(). Usestd::type_indexor the==and!=operators onstd::type_infoinstances for robust, portable type comparisons. - Use for Diagnostic Logging Only: Treat the return value strictly as an aid for debugging, logging, and diagnostics where absolute cross-platform consistency is not required.