Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can you interleave variadic parameters in call sites?

Is it possible to interleave template parameters inside of function call sites?

I effectively want to do implement the following, but I don't know how (psuedo code):

template <size_t... indices, typename... Ts>
void foo(const Things *things)
{
    static_assert(sizeof...(indices) == sizeof...(Ts));
    constexpr n = sizeof...(Ts);
    bar(
      indices[0], parse<Ts[0]>(things[0]),
      indices[1], parse<Ts[1]>(things[1]),
      ...
      indices[n-1], parse<Ts[n-1]>(things[n-1]));
}

Note: I know the following can be done (psuedo code):

template <size_t... indices, typename... Ts>
void foo(const Things *things)
{
    static_assert(sizeof...(indices) == sizeof...(Ts));
    constexpr n = sizeof...(Ts);
    bar(
      indices[0], indices[1], ..., indices[n-1],
      parse<Ts[0]>(things[0]),
      parse<Ts[1]>(things[1]),
      ...
      parse<Ts[n-1]>(things[n-1]));
}

A partial solution I came up with is to add a swizzling component:

template <typename Func>
decltype(auto) swizzle()
{
    return Func();
}

template <typename Func, typename T0>
decltype(auto) swizzle(size_t i0, T0 &&t0)
{
    return Func(i0, std::forward<T0>(t0));
}

template <typename Func, typename T0, typename T1>
decltype(auto) swizzle(size_t i0, size_t i1, T0 &&t0, T1 &&t1)
{
    return Func(i0, std::forward<T0>(t0), i1, std::forward<T1>(t1));
}

but I think I have to manually write each case per arity I want to consider.

like image 998
Thomas Eding Avatar asked Dec 24 '21 01:12

Thomas Eding


People also ask

Should I use a variadic parameter?

A Variadic Argument can be a great fit in many cases but can also not be the right solution. This is due to its limitations that are important to know to decide whether or not it’s useful to use a Variadic Parameter. If an argument is defined implicitly as an array, it would be kind of logical to understand it’s possible to pass in an empty array:

How to access the arguments of a variadic function?

The variadic function consists of at least one fixed variable and then an ellipsis (…) as the last parameter. int function_name (data_type variable_name, ...); Values of the passed arguments can be accessed through the header file named as: This enables access to variadic function arguments. This one accesses the next variadic function argument.

What is variadic function in C programming?

Variadic functions are functions that can take a variable number of arguments. In C programming, a variadic function adds flexibility to the program. It takes one fixed argument and then any number of arguments can be passed. The variadic function consists of at least one fixed variable and then an ellipsis (…) as the last parameter.

What are variadic function templates?

We can easily iterate through the arguments, find the size (length) of the template, can access the values by an index, and can slice the templates too. So basically, Variadic function templates are functions that can take multiple numbers of arguments.


Video Answer


1 Answers

Like this:

template <size_t... indices, typename... Ts>
void foo(const Things *things)
{
    std::apply([](auto...args) {
        bar(args...);
    }, std::tuple_cat(std::make_tuple(indices, parse<Ts>(*(things++)))...));
}

If bar is a lambda instead of a function template, you can just pass bar directly as the first argument to std::apply.

If you want to avoid copying the return values of parse<Ts>(*(things++)), you can use std::forward_as_tuple instead of std::make_tuple.

One slightly more verbose alternative if the *(things++) makes you uncomfortable is to use std::index_sequence:

template <size_t... indices, typename... Ts>
void foo(const Things *things)
{
    [=]<auto... Is>(std::index_sequence<Is...>) {
        std::apply([](auto...args) {
            bar(args...);
        }, std::tuple_cat(std::make_tuple(indices, parse<Ts>(things[Is]))...));
    }(std::index_sequence_for<Ts...>());
}
like image 188
Patrick Roberts Avatar answered Nov 15 '22 14:11

Patrick Roberts