C++存储带参函数指针队列并延迟调用的编译错误问题
问题分析与解决方案
编译错误原因
你代码里的pool_1.push(f1(4, 5.6));是核心错误:这里你直接调用了函数f1,得到的返回值是void,但Pool<F1>::push需要的是void(*)(int, double)类型的函数指针,两者类型完全不匹配,导致编译报错。同时你的代码根本没实现“把函数指针和参数一同存入队列”的逻辑,只是错误地试图直接调用函数而非存储调用所需的信息。
修正方案(不使用std::function/lambda)
要在仅用原始指针和基本类型的前提下实现需求,你需要用自定义结构体封装函数指针与对应参数,让队列存储这种结构体实例。以下提供两种实现方式:
方式1:通用模板封装(兼容多参数函数)
#include <queue> #include <iostream> #include <tuple> // 封装函数指针与任意参数的模板结构体 template<typename Ret, typename... Args> struct FuncPack { Ret (*func)(Args...); std::tuple<Args...> args; // 调用封装的函数(C++17及以上可用std::apply) void call() { std::apply(func, args); } }; // 通用任务池 template<class T> struct Pool { // 修改为const引用,支持临时对象传入 void push(const T& t) { m_queue.push(t); } void pop() { if (m_queue.empty()) return; T t = m_queue.front(); m_queue.pop(); t.call(); } std::queue<T> m_queue; }; // 测试函数 void func1(int p, double q) { std::cout << p << " " << q << std::endl; } int main() { // 针对func1定义对应的封装类型 using Pack1 = FuncPack<void, int, double>; Pool<Pack1> pool_1; // 打包函数指针与参数并推入队列 pool_1.push(Pack1{&func1, std::make_tuple(4, 5.6)}); // 执行队列中的任务 pool_1.pop(); }
方式2:专用结构体封装(更“原始”,无模板依赖)
如果不想用std::tuple,可以为每个函数写专用的封装结构体:
#include <queue> #include <iostream> // 仅针对func1的专用封装结构体 struct Func1Pack { void (*func)(int, double); int p; double q; void call() { func(p, q); } }; template<class T> struct Pool { void push(const T& t) { m_queue.push(t); } void pop() { if (m_queue.empty()) return; T t = m_queue.front(); m_queue.pop(); t.call(); } std::queue<T> m_queue; }; void func1(int p, double q) { std::cout << p << " " << q << std::endl; } int main() { Pool<Func1Pack> pool_1; pool_1.push(Func1Pack{&func1, 4, 5.6}); pool_1.pop(); }
关键说明
- 两种方式都通过结构体将函数指针和参数绑定在一起,实现了“延迟执行”的核心需求。
- 将
Pool::push的参数改为const T&,解决了原代码中左值引用无法绑定临时对象的问题。 - 方式1通用性强,支持任意参数的函数;方式2更贴近“原始类型”,但每个不同参数的函数都需要单独写封装结构体。
内容的提问来源于stack exchange,提问作者intrigued_66
相关产品推荐
相关产品推荐

