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;
}
相关推荐
咖啡の猫14 小时前
Python字典推导式
开发语言·python
leiming614 小时前
C++ vector容器
开发语言·c++·算法
SystickInt14 小时前
C语言 strcpy和memcpy 异同/区别
c语言·开发语言
CS Beginner15 小时前
【C语言】windows下编译mingw版本的glew库
c语言·开发语言·windows
FJW02081415 小时前
Python_work4
开发语言·python
Xの哲學15 小时前
Linux流量控制: 内核队列的深度剖析
linux·服务器·算法·架构·边缘计算
大学生资源网15 小时前
java毕业设计之儿童福利院管理系统的设计与实现(源码+)
java·开发语言·spring boot·mysql·毕业设计·源码·课程设计
JasmineWr15 小时前
JVM栈空间的使用和优化
java·开发语言
Poetinthedusk15 小时前
C#实现图片统一位深
开发语言·c#
yaoh.wang16 小时前
力扣(LeetCode) 88: 合并两个有序数组 - 解法思路
python·程序人生·算法·leetcode·面试·职场和发展·双指针