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

如何将参数包与函数指针移入结构体?自定义包装packaged_task遇报错

解决自定义ThreadTask中存储带参数函数指针的问题

你的核心问题是没有在BaseFunc中存储调用函数所需的参数,导致Call()里直接调用func()时参数不匹配,触发编译器报错。以下是修正后的实现方案:

修正后的核心代码

#include <memory>
#include <tuple>
#include <utility>
#include <functional>

class ThreadTask {
    struct BaseInterface {
        virtual void Call() = 0;
        virtual ~BaseInterface() = default;
    };

    std::unique_ptr<BaseInterface> mImplementation;

    template <typename F, typename... Args>
    struct BaseFunc : BaseInterface {
        F func;
        std::tuple<Args...> args; // 存储调用函数所需的参数

        // 完美转发函数对象和参数,移动构造func,保存参数到tuple
        BaseFunc(F&& f, Args&&... args)
            : func(std::move(f)), args(std::forward<Args>(args)...) {}

        void Call() override {
            // 展开tuple中的参数,转发给func调用
            std::apply([this](auto&&... args) {
                std::invoke(this->func, std::forward<decltype(args)>(args)...);
            }, this->args);
        }
    };

public:
    // 对外暴露的构造函数,用于创建ThreadTask实例
    template <typename F, typename... Args>
    ThreadTask(F&& f, Args&&... args)
        : mImplementation(std::make_unique<BaseFunc<F, Args...>>(
              std::forward<F>(f), std::forward<Args>(args)...)) {}

    // 执行任务的接口
    void Execute() {
        if (mImplementation) {
            mImplementation->Call();
        }
    }
};

关键修改点说明

  • 存储参数:用std::tuple<Args...>保存调用函数所需的所有参数,适配任意数量和类型的参数组合。
  • 完美转发:构造函数中通过std::forward转发函数对象和参数,确保移动语义(适配std::packaged_task的移动-only特性),同时避免不必要的拷贝。
  • 参数展开调用:使用std::apply(C++17及以上支持)将tuple中的参数展开,配合std::invoke调用函数对象,确保参数正确转发。

使用示例

#include <future>
#include <iostream>

int main() {
    // 包装一个带参数的packaged_task
    std::packaged_task<int(int, int)> task([](int a, int b) {
        return a + b;
    });
    std::future<int> fut = task.get_future();

    // 创建ThreadTask实例,移动传入task和参数
    ThreadTask threadTask(std::move(task), 10, 20);

    // 在线程中执行任务(这里直接调用模拟线程执行)
    threadTask.Execute();

    // 获取任务结果
    std::cout << "Result: " << fut.get() << std::endl;
    return 0;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 11:05:28