在 C++ 中要打印未知类型对象的类型名称,可以通过以下方法实现:
目录
使用示例:
问题与改进:
方法二:编译时类型名称(C++17 起)
使用示例:
方法三:使用 Boost 库(跨平台)
对比总结:
注意事项:
完整示例(支持跨平台反修饰):
方法一:使用 typeid
和 name()
(需包含 <typeinfo>
)
#include <iostream>
#include <typeinfo>template <typename T>
void printType(const T& obj) {std::cout << "类型名称: " << typeid(obj).name() << std::endl;
}
使用示例:
int main() {auto x = 3.14;printType(x); // 输出类似 "d"(GCC)或 "double"(MSVC)return 0;
}
问题与改进:
-
编译器差异:
-
GCC/Clang 会返回名称修饰的字符串(如
i
表示int
,d
表示double
) -
MSVC 会直接返回可读名称(如
int
)
-
-
Demangling(反修饰):
#include <cxxabi.h> // GCC/Clang 专用template <typename T> void printHumanReadableType(const T& obj) {int status;char* name = abi::__cxa_demangle(typeid(obj).name(), 0, 0, &status);std::cout << "可读类型: " << (status == 0 ? name : "未知类型") << std::endl;free(name); }
方法二:编译时类型名称(C++17 起)
#include <string_view>template <typename T>
constexpr std::string_view type_name() {#if defined(__clang__)return __PRETTY_FUNCTION__;#elif defined(__GNUC__)return __PRETTY_FUNCTION__;#elif defined(_MSC_VER)return __FUNCSIG__;#endif
}template <typename T>
void printTypeAtCompileTime() {constexpr auto prefix = sizeof("auto type_name() [T = ") - 1;constexpr auto suffix = sizeof("]") - 1;constexpr auto name = type_name<T>();std::cout << "编译时类型: " << name.substr(prefix, name.size() - prefix - suffix)<< std::endl;
}
使用示例:
printTypeAtCompileTime<std::vector<int>>();
// 输出类似 "std::vector<int, std::allocator<int>>"
方法三:使用 Boost 库(跨平台)
#include <boost/type_index.hpp>template <typename T>
void printTypeWithBoost(const T& obj) {using boost::typeindex::type_id_with_cvr;std::cout << "Boost 类型: "<< type_id_with_cvr<T>().pretty_name()<< std::endl;
}
对比总结:
方法 | 优点 | 缺点 |
---|---|---|
typeid | 简单直接 | 需要处理名称修饰 |
编译时方法 | 无需运行时开销 | 依赖编译器特定宏 |
Boost 库 | 输出美观、跨平台 | 需要额外安装依赖库 |
注意事项:
-
多态类型:
typeid
对多态类型会返回动态类型class Base { virtual void foo() {} }; // 必须包含虚函数 class Derived : public Base {};Base* obj = new Derived; std::cout << typeid(*obj).name(); // 输出 Derived 的类型
-
类型修饰:
const int& x = 42; printType(x); // 可能输出 "i" 而非 "const int&"
-
平台兼容性:
#if defined(__GNUC__) && !defined(__clang__) // GCC 专用处理 #elif defined(_MSC_VER) // MSVC 专用处理 #endif
完整示例(支持跨平台反修饰):
#include <iostream>
#include <typeinfo>
#include <cxxabi.h>template <typename T>
std::string demangle() {int status = -1;const char* name = typeid(T).name();char* demangled = abi::__cxa_demangle(name, NULL, NULL, &status);std::string result = (status == 0) ? demangled : name;free(demangled);return result;
}int main() {const std::vector<double> vec;std::cout << "Demangled type: " << demangle<decltype(vec)>() << std::endl;// 输出: std::vector<double, std::allocator<double> >return 0;
}