创建函数对象的packaged_task

时间:2019-09-14 07:31:35

标签: c++ future packaged-task

如何创建功能对象的packaged_task

例如,

class TaskA {
    public:
        std::function<int(void)> func;
        TaskA(std::function<int(void)>&f) : func(f) {}
        int res;
        int operator()() {
            std::this_thread::sleep_for(std::chrono::milliseconds(2000));
            return func();
        }
};

现在首先创建一个函数对象:

std::function<int(void)> func1 = xy; // xy is some function
TaskA task1(func1);

现在我有一个函数,该函数将该函数对象作为参数,创建一个packaged_task并返回未来。

template<typename TaskType>
auto handle(TaskType func) -> std::future</*correct syntax ?*/>
{
    auto task  = std::packaged_task</*correct syntax ?*/>(std::move(func));
    /* correct syntax ? */
    auto futur = task.get_future();

    // do something with the task

    return std::move(futur);
}

,然后按如下所示使用此句柄函数:

auto x = handle(task1);

您能为我提供futurepackaged_task声明的正确语法吗?

谢谢!

2 个答案:

答案 0 :(得分:1)

这使用一个元函数来推断签名。请注意,我并未在其他类型的可调用对象上进行此测试,因此尽管它可以与operator()一起使用,但对于其他类型的可调用对象可能还需要一些工作。

#include <functional>
#include <future>

class TaskA {
public:
    int operator()() { return 0; }
};

template <typename T>
struct function_signature
    : public function_signature<decltype(&T::operator())>
{};

template <typename ClassType, typename ReturnType, typename... Args>
struct function_signature<ReturnType(ClassType::*)(Args...)> {
    using type = ReturnType(Args...);
};

template<typename TaskType>
auto handle(TaskType func)
{
    using signature = typename function_signature<TaskType>::type;
    auto task  = std::packaged_task<signature>(std::move(func));

    auto futur = task.get_future();

    // do something with the task

    return std::move(futur);
}

int main() {
    TaskA task1;
    handle(task1);
}

答案 1 :(得分:1)

我会尝试明确说明任务的返回类型,函数类型和调用签名,并将其作为类接口的一部分。为了简单起见,我做了所有显式操作,但这可以通过模板或使用decltype功能来完成:

#include <cmath>
#include <iostream>
#include <map>
#include <functional>
#include <future>
#include <cmath>
#include <thread>
//#include <gsl/gsl>
using namespace std;

int f()
{
    return 3;
}

class TaskA
{
public:
    using ReturnType = int;
    using Function = std::function<ReturnType(void)>;
    typedef ReturnType (CallSignature)();

    TaskA(Function& f) : func{f} {}


    ReturnType operator()()
    {
        std::this_thread::sleep_for(std::chrono::milliseconds(2000));
        return func();
    }

private:
    Function func;
};

template<typename TaskType>
auto handle(TaskType func) -> std::future<typename TaskType::ReturnType>
{
    auto task = std::packaged_task<typename TaskType::CallSignature>{func};
    auto future = task.get_future();
    // do  something with task
    task();
    return future;
}

int main()
{
    std::function<int()> ff{f};
    TaskA task{ff};
    auto result = handle(task);
    cout << result.get() << endl;
}

live example here