user9455071
user9455071

Reputation:

How can I slice variadic template parameters and use them?

I'm quite new to template metaprogramming. This is what I wanted to do.

template <typename... Args>
void to_be_async_func(Args&&... args)
{
   //want to use args[0...N-2] to invoke a function call
   //and args[N-1(last)] to use a handler function after the prior call.
}

int main()
{
    int a = 5;
    int b = 3;
    to_be_async_func(a, b, [](int res)
    {
       //do something with the result
       //any Callable can be passed
    });
}

Initially I tried like

template<typename... Args, typename Callable>
void to_be_async_func(Args&&... args, Callable op)
{

}

However in this case "Callable" should have default value to be used like that.
In my opinion, some kind of helper template struct might do this.
If this thing is possible, could you please show me the way?
Thank you in advance.

EDIT
I've also seen this post and tried as instructed.
It worked. But as stated in the text, I want to know if there's a more standard way to achieve this.

Upvotes: 0

Views: 468

Answers (1)

Jarod42
Jarod42

Reputation: 218238

Using std::index_sequence seems the way to go:

template <typename F, typename... Args>
void to_be_async_func_first(F&& f, Args&&... args)
{
    std::invoke(std::forward<F>(f), std::forward<Args>(args)...);
}

template <std::size_t ... Is, typename... Args>
void to_be_async_func_impl(std::index_sequence<Is...>, Args&&... args)
{
    auto&& args_tuple = std::forward_as_tuple(std::forward<Args>(args)...);
    to_be_async_func_first(std::get<sizeof...(Args) - 1>(args_tuple),
                           std::get<Is>(args_tuple)...);
}

template <typename... Args>
void to_be_async_func(Args&&... args)
{
    to_be_async_func_impl(std::make_index_sequence<sizeof...(Args) - 1>(),
                          std::forward<Args>(args)...);
}

Upvotes: 1

Related Questions