如何正确编写支持void返回类型的C++模板包装响应类
支持void返回类型的函数调用包装类实现
需求
- 函数成功执行时,将结果存储到包装类的
data字段中 - 函数执行异常时,将异常转换为
int类型的错误码
原实现问题
原代码无法支持返回类型为void的函数,因为当f()返回void时,res.data = f();这一行会触发编译错误——void类型的值不能被赋值给任何变量。
修改后的完整实现
#include <exception> #include <iostream> #include <type_traits> struct ResponseBase { int code = 0; }; template<typename T> struct Response : ResponseBase { T data; }; template<> struct Response<void> : ResponseBase { }; template<typename F> auto try_catch_wrapper(F&& f) { using ReturnType = decltype(f()); Response<ReturnType> res; try { if constexpr (!std::is_void_v<ReturnType>) { res.data = f(); } else { f(); // void返回类型直接调用,无需赋值 } } catch (const std::exception&) { res.code = -1; } return res; } int main() { // 测试非void返回类型 auto a = try_catch_wrapper([]() { return 1; }); if (a.code == 0) { std::cout << "Invoke Success, Result: " << a.data << std::endl; } else { std::cout << "Error occured! Code: " << a.code << std::endl; } // 测试void返回类型 auto b = try_catch_wrapper([]() { std::cout << "Void function executed!" << std::endl; }); if (b.code == 0) { std::cout << "Void function invoke Success!" << std::endl; } else { std::cout << "Error occured! Code: " << b.code << std::endl; } }
关键修改说明
- 使用
using ReturnType = decltype(f());提取函数的返回类型,方便后续编译时判断 - 通过
if constexpr (!std::is_void_v<ReturnType>)做编译时分支处理:- 当返回类型非
void时,正常执行赋值操作存储结果 - 当返回类型为
void时,直接调用函数,跳过赋值步骤
- 当返回类型非
- 若使用C++17之前的版本,可将
std::is_void_v<ReturnType>替换为std::is_void<ReturnType>::value
修改后,包装类即可同时支持带返回值和无返回值的函数调用。
内容的提问来源于stack exchange,提问作者Eric Qiang
相关产品推荐
相关产品推荐

