c++futurepackaged-task

Create a packaged_task of function object


How to create a packaged_task of a function object ?

For example,

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

Now create a function object first:

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

Now I have a function that takes this function object as a parameter, creates a packaged_task and returns a future.

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

and later use this handle function as follows:

auto x = handle(task1);

Can you please help me with the proper syntax for the future as well as the packaged_task declaration?

Thanks !


Solution

  • This uses a metafunction to deduce the signature. Note that I didn't test this with other types of callable, so whilst it should work for anything with an operator(), it might need some work for other kinds of callable.

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