如何将可变参数的void函数加入线程池的任务队列
问题原因
- 报错的核心原因是你当前的代码逻辑没有兼容类非静态成员函数这类可调用对象:类非静态成员函数调用时必须绑定对应的类实例,不能直接像普通函数那样通过
function(args...)的形式调用,因此编译器抛出要求使用.*/->*调用成员函数指针的错误。 - 还有一个隐藏的编译错误:你单参数的
push_function重载接收的是FUNCTION &非const左值引用,而你传入的lambda是临时右值,右值无法绑定到非const左值引用上,也会导致编译失败。
修复方案
首先确保你已经包含了<functional>头文件,然后按以下步骤修改代码:
- 修正单参数
push_function的参数类型,适配临时右值传入:
// 用万能引用兼容左值、右值传入,同时用完美转发减少拷贝,性能更优 template <typename FUNCTION> void push_function(FUNCTION &&function){ { std::unique_lock<std::mutex> lock(queue_mutex); queue.push(std::function<void()>(std::forward<FUNCTION>(function))); } cv.notify_one(); }
如果不想用万能引用,也可以直接改成const左值引用:void push_function(const FUNCTION &function)。
- 用
std::invoke统一处理所有可调用对象的调用逻辑,自动兼容普通函数、lambda、成员函数等不同类型:
template <typename FUNCTION, typename... ARGS> void push_function(FUNCTION &&function, ARGS &&...args){ push_function([func = std::forward<FUNCTION>(function), ...args = std::forward<ARGS>(args)] () mutable { std::invoke(func, args...); }); }
如果你的编译环境仅支持C++11/14,也可以用std::bind实现同样效果:
template <typename FUNCTION, typename... ARGS> void push_function(const FUNCTION &function, const ARGS &...args){ push_function(std::bind(function, args...)); }
修改完成后,如果你要传入类成员函数,只需要把类实例指针/引用作为第一个参数传入即可,示例:
// 假设Test是类,func是其非静态成员函数,obj是Test类的实例 push_function(&Test::func, &obj, 123, "test");
内容的提问来源于stack exchange,提问作者user_name01910191
相关产品推荐
相关产品推荐

