You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在C++运行时获取并打印variant中包含的类型?

在C++中运行时打印std::variant的类型(结合pybind11场景)

一、纯C++环境下打印std::variant的类型

核心思路是用std::visit遍历variant的所有可能类型,结合typeid获取类型信息。需要注意的是,GCC/Clang会输出经过名字修饰的类型名,需额外解析为可读格式;MSVC则直接输出友好的类型名称。

实现代码

#include <variant>
#include <iostream>
#include <typeinfo>
#include <string>

struct VariantTypePrinter {
    template<typename T>
    void operator()(const T&) const {
#ifdef __GNUC__
        int status;
        // 解析GCC/Clang的名字修饰字符串
        char* demangled = __cxxabiv1::__cxa_demangle(typeid(T).name(), nullptr, nullptr, &status);
        if (status == 0) {
            std::cout << demangled << std::endl;
            free(demangled);
        } else {
            std::cout << typeid(T).name() << std::endl;
        }
#else
        // MSVC直接输出可读类型名
        std::cout << typeid(T).name() << std::endl;
#endif
    }
};

// 使用示例
int main() {
    std::variant<int, float, std::string, bool> var = 3.14f;
    std::visit(VariantTypePrinter{}, var); // 输出float(GCC解析后)
    return 0;
}

二、结合pybind11的场景处理

从Python字典传递值到C时,有两种常见需求:打印Python端的原生类型,或者打印转换为C std::variant后的类型。

1. 直接打印Python对象的类型

通过pybind11的py::object直接获取Python层面的类型名称:

#include <pybind11/pybind11.h>

namespace py = pybind11;

void print_python_type(const py::object& obj) {
    // 获取Python类型的__name__属性
    std::cout << obj.attr("__class__").attr("__name__").cast<std::string>() << std::endl;
}

2. 转换为std::variant后打印C++类型

先将Python值转换为C++的std::variant,再用之前的VariantTypePrinter打印:

#include <pybind11/pybind11.h>
#include <pybind11/stl.h>
#include <variant>
#include <iostream>

namespace py = pybind11;

struct VariantTypePrinter {
    template<typename T>
    void operator()(const T&) const {
#ifdef __GNUC__
        int status;
        char* demangled = __cxxabiv1::__cxa_demangle(typeid(T).name(), nullptr, nullptr, &status);
        if (status == 0) {
            std::cout << demangled << std::endl;
            free(demangled);
        } else {
            std::cout << typeid(T).name() << std::endl;
        }
#else
        std::cout << typeid(T).name() << std::endl;
#endif
    }
};

void process_python_dict(const py::dict& dict) {
    for (auto& [key, value] : dict) {
        std::cout << "Key (Python type): ";
        print_python_type(key);
        std::cout << "Value (Python type): ";
        print_python_type(value);

        // 转换Python值到C++ variant(可根据需求扩展支持的类型)
        std::variant<int, float, std::string, bool> cpp_var;
        if (py::isinstance<py::int_>(value)) {
            cpp_var = value.cast<int>();
        } else if (py::isinstance<py::float_>(value)) {
            cpp_var = value.cast<float>();
        } else if (py::isinstance<py::str>(value)) {
            cpp_var = value.cast<std::string>();
        } else if (py::isinstance<py::bool_>(value)) {
            cpp_var = value.cast<bool>();
        }

        std::cout << "Value (C++ variant type): ";
        std::visit(VariantTypePrinter{}, cpp_var);
        std::cout << "---" << std::endl;
    }
}

PYBIND11_MODULE(type_printer, m) {
    m.def("process_dict", &process_python_dict, "Process Python dict and print types");
}

注意事项

  • typeid(T).name()的输出格式依赖编译器,GCC/Clang需要用__cxa_demangle解析,MSVC无需额外处理。
  • 若需要支持更多Python类型(如列表、嵌套字典),可以扩展std::variant的类型列表,或直接处理pybind11的py::list、py::dict类型。
  • 直接获取Python的类型名称更贴合Python端的类型认知,转换为C++ variant后打印的是对应的C++类型。

内容的提问来源于stack exchange,提问作者Contango

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.13 03:51:06