Reputation: 63
I need a bit of help. I need to perfect forward a tuple in a specific way. Imagine this
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); };
}
the task that is packaged will be executed later on a different thread but when I call apply I need the "callable" to have it's params expanded from the tuple and forwarded exactly like they were passed in the package_task
function. I can't use forward_as_tuple
since I am copying/moving the arguments and the callable to be executed later. I need something like
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); };
}
Any ideas would be appreciated.
Upvotes: 0
Views: 284
Reputation: 303117
If you're trying to make a one-shot callable that forwards its arguments through, the best you can do with C++17 or earlier is:
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);
};
}
That is, you forward
the Args
into a tuple, apply
the tuple and then forward
them back out.
In C++20, thanks to P0780, this can be simplified to:
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)...);
};
}
Upvotes: 2