C++线程池实现中std::promise处理void返回值类型报错求解
C++线程池void返回值适配方案
问题原因
std::promise<void>的set_value成员函数为无参设计,你当前代码统一将f(args...)作为参数传入set_value,当函数返回值为void时,f(args...)没有返回值,无法作为参数传递,因此触发编译错误。无参数函数异常通常是参数没有做完美转发导致的值类别匹配错误。
解决方案
方案1:C++17及以上版本(推荐)
使用if constexpr做编译期分支区分,同时用std::invoke兼容普通函数、成员函数、lambda等所有可调用对象,配合完美转发处理参数:
#include <future> #include <functional> // std::invoke template <typename F, typename...Args> auto addWork(F&& f, Args&&... args) -> std::future<decltype(f(args...))> { using ReturnType = decltype(f(args...)); std::promise<ReturnType> result; if constexpr (std::is_void_v<ReturnType>) { std::invoke(std::forward<F>(f), std::forward<Args>(args)...); result.set_value(); // void类型调用无参set_value } else { result.set_value(std::invoke(std::forward<F>(f), std::forward<Args>(args)...)); } return result.get_future(); // 后续将任务加入线程池队列的逻辑写在这里 }
方案2:C++11/14版本兼容
通过模板函数重载区分void和非void返回场景:
#include <future> #include <utility> // 非void返回值处理逻辑 template<typename ReturnType, typename F, typename... Args> void fill_promise(std::promise<ReturnType>& prom, F&& func, Args&&... args) { prom.set_value(std::forward<F>(func)(std::forward<Args>(args)...)); } // void返回值特化逻辑 template<typename F, typename... Args> void fill_promise(std::promise<void>& prom, F&& func, Args&&... args) { std::forward<F>(func)(std::forward<Args>(args)...); prom.set_value(); } // addWork实现 template <typename F, typename...Args> auto addWork(F&& f, Args&&... args) -> std::future<decltype(f(args...))> { using ReturnType = decltype(f(args...)); std::promise<ReturnType> result; fill_promise(result, std::forward<F>(f), std::forward<Args>(args)...); return result.get_future(); // 后续将任务加入线程池队列的逻辑写在这里 }
两种方案都可以同时解决void返回值适配、无参数函数调用异常的问题。
内容的提问来源于stack exchange,提问作者Foledem
相关产品推荐
相关产品推荐

