向前转发复制的std :: tuple

时间:2018-09-25 18:53:27

标签: c++ tuples c++14 perfect-forwarding stdapply

我需要一些帮助。我需要以特定的方式完善元组。想象一下

template <typename F, typename... Args>
auto package_task(F&& func, Args&&... args) -> std::function<void()>
{
    //for the purposes of this example imagine capture to be std::move and
    //to be inplace in the lambdas' capture.
    auto callable = capture(std::forward<F>(func));
    auto params = capture(std::make_tuple(std::forward<Args>(args)...));

    return [callable , params]() mutable { std::apply(callable, params); };
}

打包的任务将稍后在另一个线程上执行,但是当我调用apply时,我需要“ callable”以使其参数从元组扩展并转发,就像它们在package_task函数中传递的一样。我无法使用forward_as_tuple,因为我正在复制/移动参数和可调用对象,以便稍后执行。我需要类似的东西

template <typename F, typename... Args>
auto package_task(F&& func, Args&&... args) -> std::function<void()>
{
    //for the purposes of this example image capture to be std::move and
    //to be inplace in the lambdas' capture.
    auto callable = capture(std::forward<F>(func));
    auto params = capture(std::make_tuple(std::forward<Args>(args)...));

    return [callable , params]() mutable { std::apply_but_expand_as<Args&&…>(callable, params); };
}

任何想法都会受到赞赏。

1 个答案:

答案 0 :(得分:2)

如果您要使可调用的单次调用通过其转发参数,那么使用C ++ 17或更早版本可以做到的最好是:

template <typename F, typename... Args>
auto package_task(F&& func, Args&&... args) -> std::function<void()>
{
    return [func = std::forward<F>(func),
            args_tuple = std::make_tuple(std::forward<Args>(args)...)]
           () mutable
    {
        return std::apply([](auto&&... args){
            return std::invoke(
                std::forward<F>(func),
                std::forward<Args>(args)...
                );
        }, args_tuple);
    };
}

也就是说,您将forward Args变成一个元组,apply该元组,然后forward将它们退回。


在C ++ 20中,多亏了P0780,这可以简化为:

template <typename F, typename... Args>
auto package_task(F&& func, Args&&... args) -> std::function<void()>
{
    return [func = std::forward<F>(func),
            ...args = std::forward<Args>(args)] () mutable
    {
        return std::invoke(std::forward<F>(f), std::forward<Args>(args)...);
    };
}