如何实现通过模板参数包指定异常类型的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
相关产品推荐
相关产品推荐

