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

如何实现通过模板参数包指定异常类型的C++捕获逻辑?

实现支持可变异常类型捕获的通用重试机制

你尝试的catch (const Exceptions& e...)语法不符合C规范,无法直接展开模板参数包生成多个catch分支。下面提供两种基于现代C特性的优雅实现方案,完美匹配你的重试需求:

方案一:递归模板展开异常捕获分支

通过递归模板逐步展开每个异常类型,生成对应的catch块:

#include <utility>

// 递归终止的基础版本:仅执行目标函数
template<typename Func>
auto execute_with_handler(Func&& func) {
    return std::forward<Func>(func)();
}

// 递归版本:处理一个异常类型,再递归处理剩余参数
template<typename Exc, typename... RemainingExcs, typename Func>
auto execute_with_handler(Func&& func) {
    try {
        return execute_with_handler<RemainingExcs...>(std::forward<Func>(func));
    } catch (const Exc& e) {
        log_error(e);
        throw; // 重新抛出以触发重试逻辑
    }
}

// 通用重试函数,模板参数指定需要捕获的异常类型
template<typename... TargetExceptions, typename Func>
auto retry(Func&& func, int max_retries = 3) {
    for (int attempt = 0; attempt < max_retries; ++attempt) {
        try {
            return execute_with_handler<TargetExceptions...>(std::forward<Func>(func));
        } catch (...) {
            // 仅捕获指定异常时进入重试,其他异常直接向上传递
        }
    }
    // 最后一次尝试,不做重试逻辑,直接执行
    return std::forward<Func>(func)();
}

使用示例

// 捕获Exc1和Exc2异常时自动重试最多3次
retry<Exc1, Exc2>([] {
    // 包含可能抛出Exc1、Exc2或其他异常的业务逻辑
});

方案二:C++17折叠表达式实现紧凑版

利用C++17的折叠表达式特性,直接在try块后展开所有异常类型的catch分支,代码更紧凑:

#include <utility>

template<typename... TargetExceptions, typename Func>
auto retry(Func&& func, int max_retries = 3) {
    auto wrapped_execution = [&]() -> decltype(auto) {
        try {
            return std::forward<Func>(func)();
        }
        // 折叠表达式展开每个异常类型的捕获逻辑
        catch (const TargetExceptions& e) ... {
            log_error(e);
            throw;
        }
    };

    for (int attempt = 0; attempt < max_retries; ++attempt) {
        try {
            return wrapped_execution();
        } catch (...) {
            // 非指定异常直接传递,不触发重试
        }
    }
    return std::forward<Func>(func)();
}

核心特性说明

  • 精准异常控制:仅捕获模板参数列表中的异常类型进行重试,其他异常直接向上传递,符合你的需求。
  • 完美转发:使用std::forward保证函数对象的类型完整性,支持左值、右值等各种类型的可调用对象。
  • 简洁性:无需额外编写异常处理lambda,直接通过模板参数指定目标异常,代码可读性更高。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.07 17:10:16