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

如何在catch站点遍历boost::exception的所有error_info元素?

当然可以实现!完全不用重复造轮子

其实Boost异常库本身就提供了遍历所有error_info元素的机制,比解析boost::diagnostic_information的输出要可靠得多。下面是具体的实现思路和代码示例:

核心思路

Boost的error_info是通过类型标签绑定到boost::exception上的,我们可以用boost::exception::visit函数来遍历所有附加的error_info元素,再通过自定义的**访问器(visitor)**来提取每个元素的名称和值——这和boost::diagnostic_information内部的实现逻辑是一致的,只是我们把它拆出来单独收集键值对而已。

具体实现步骤

1. 定义一个错误信息收集器(Visitor)

这个访问器会被boost::exception::visit调用,处理每个error_info元素:

#include <boost/exception/all.hpp>
#include <string>
#include <vector>
#include <sstream>
#include <iostream>

struct ErrorInfoCollector {
    // 用来存储提取到的名称-值对
    mutable std::vector<std::pair<std::string, std::string>> entries;

    // 模板方法,匹配任意类型的error_info
    template <typename ErrorInfoType>
    void operator()(ErrorInfoType const& ei) const {
        // 获取error_info的官方名称(比如errinfo_errno的名称是"errno")
        std::string info_name = ei.name();
        // 将值转换为字符串(和diagnostic_information的输出逻辑一致)
        std::ostringstream value_stream;
        value_stream << ei.value();
        // 存入键值对
        entries.emplace_back(info_name, value_stream.str());
    }
};

2. 在Catch块中遍历并收集信息

捕获异常后,先尝试将其转换为boost::exception类型,然后用visit函数触发遍历:

try {
    // 示例:抛出一个带多个error_info的异常
    throw boost::enable_error_info(std::runtime_error("Failed to read file"))
        << boost::errinfo_file_name("config.json")
        << boost::errinfo_errno(ENOENT)
        << boost::errinfo_line_number(42);
} catch (std::exception const& e) {
    // 检查是否是Boost包装过的异常
    if (auto boost_exc = dynamic_cast<boost::exception const*>(&e)) {
        ErrorInfoCollector collector;
        // 遍历所有error_info元素,收集键值对
        boost::exception::visit(*boost_exc, collector);

        // 输出收集到的结果
        std::cout << "提取到的异常信息键值对:\n";
        for (auto const& [name, value] : collector.entries) {
            std::cout << "- *" << name << "*: " << value << "\n";
        }

        // 同时也可以保留diagnostic_information的完整输出
        std::cout << "\n完整诊断信息:\n" << boost::diagnostic_information(e) << "\n";
    } else {
        // 普通std::exception,没有附加error_info
        std::cout << "标准异常: " << e.what() << "\n";
    }
}

关键细节说明

  • 类型安全的遍历:boost::exception::visit会自动匹配每个error_info的类型,不需要我们手动判断,避免了类型转换错误。
  • 和diagnostic_information保持一致:通过ei.name()获取官方名称,用流输出值,确保和boost::diagnostic_information的输出内容完全一致,不需要重复实现格式化逻辑。
  • 兼容普通std::exception:如果捕获的异常没有被boost::enable_error_info包装,dynamic_cast会返回nullptr,这时候就按普通异常处理即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 07:47:08