c++中如何打印未知类型对象的类型

在 C++ 中要打印未知类型对象的类型名称,可以通过以下方法实现:

目录

[方法一:使用 typeid 和 name()(需包含 )](#方法一:使用 typeid 和 name()(需包含 ))

使用示例:

问题与改进:

[方法二:编译时类型名称(C++17 起)](#方法二:编译时类型名称(C++17 起))

使用示例:

[方法三:使用 Boost 库(跨平台)](#方法三:使用 Boost 库(跨平台))

对比总结:

注意事项:

完整示例(支持跨平台反修饰):


方法一:使用 typeidname()(需包含 <typeinfo>

cpp 复制代码
#include <iostream>
#include <typeinfo>

template <typename T>
void printType(const T& obj) {
    std::cout << "类型名称: " << typeid(obj).name() << std::endl;
}

使用示例:

cpp 复制代码
int main() {
    auto x = 3.14;
    printType(x);  // 输出类似 "d"(GCC)或 "double"(MSVC)
    return 0;
}

问题与改进:

  • 编译器差异

    • GCC/Clang 会返回名称修饰的字符串(如 i 表示 intd 表示 double

    • MSVC 会直接返回可读名称(如 int

  • Demangling(反修饰)

    cpp 复制代码
    #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 起)

cpp 复制代码
#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;
}

使用示例:

cpp 复制代码
printTypeAtCompileTime<std::vector<int>>();
// 输出类似 "std::vector<int, std::allocator<int>>"

方法三:使用 Boost 库(跨平台)

cpp 复制代码
#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 库 输出美观、跨平台 需要额外安装依赖库

注意事项:

  1. 多态类型typeid 对多态类型会返回动态类型

    cpp 复制代码
    class Base { virtual void foo() {} }; // 必须包含虚函数
    class Derived : public Base {};
    
    Base* obj = new Derived;
    std::cout << typeid(*obj).name(); // 输出 Derived 的类型
  2. 类型修饰

    cpp 复制代码
    const int& x = 42;
    printType(x);  // 可能输出 "i" 而非 "const int&"
  3. 平台兼容性

    cpp 复制代码
    #if defined(__GNUC__) && !defined(__clang__)
    // GCC 专用处理
    #elif defined(_MSC_VER)
    // MSVC 专用处理
    #endif

完整示例(支持跨平台反修饰):

cpp 复制代码
#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;
}
相关推荐
Sammyyyyy9 分钟前
2025年,Javascript后端应该用 Bun、Node.js 还是 Deno?
开发语言·javascript·node.js
CoovallyAIHub19 分钟前
方案 | 动车底部零部件检测实时流水线检测算法改进
深度学习·算法·计算机视觉
CoovallyAIHub21 分钟前
方案 | 光伏清洁机器人系统详细技术实施方案
深度学习·算法·计算机视觉
lxmyzzs25 分钟前
【图像算法 - 14】精准识别路面墙体裂缝:基于YOLO12与OpenCV的实例分割智能检测实战(附完整代码)
人工智能·opencv·算法·计算机视觉·裂缝检测·yolo12
洋曼巴-young27 分钟前
240. 搜索二维矩阵 II
数据结构·算法·矩阵
汉汉汉汉汉39 分钟前
C++11新特性详解:从列表初始化到线程库
c++
William一直在路上42 分钟前
Python数据类型转换详解:从基础到实践
开发语言·python
看到我,请让我去学习1 小时前
Qt— 布局综合项目(Splitter,Stacked,Dock)
开发语言·qt
GUET_一路向前2 小时前
【C语言防御性编程】if条件常量在前,变量在后
c语言·开发语言·if-else·防御性编程
曳渔2 小时前
UDP/TCP套接字编程简单实战指南
java·开发语言·网络·网络协议·tcp/ip·udp