You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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();
}

关键说明

  1. 两种方式都通过结构体将函数指针和参数绑定在一起,实现了“延迟执行”的核心需求。
  2. 将Pool::push的参数改为const T&,解决了原代码中左值引用无法绑定临时对象的问题。
  3. 方式1通用性强,支持任意参数的函数;方式2更贴近“原始类型”,但每个不同参数的函数都需要单独写封装结构体。

内容的提问来源于stack exchange,提问作者intrigued_66

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.11 17:53:16