您可以在调用站点中交错可变参数吗?

Tho*_*ing 6 c++ variadic-templates c++20

是否可以在函数调用站点内交错模板参数?

我实际上想要实现以下内容,但我不知道如何实现(伪代码):

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]));
}
Run Code Online (Sandbox Code Playgroud)

注意:我知道可以执行以下操作(伪代码):

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]));
}
Run Code Online (Sandbox Code Playgroud)

我想出的部分解决方案是添加一个 swizzling 组件:

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));
}
Run Code Online (Sandbox Code Playgroud)

但我认为我必须根据我想要考虑的数量手动编写每个案例。

Pat*_*rts 4

像这样:

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++)))...));
}
Run Code Online (Sandbox Code Playgroud)

如果bar是 lambda 而不是函数模板,则可以bar直接作为第一个参数传递给std::apply.

如果您想避免复制 的返回值parse<Ts>(*(things++)),可以使用std::forward_as_tuple代替std::make_tuple

如果让您感到不舒服,一种稍微详细的替代方法*(things++)是使用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...>());
}
Run Code Online (Sandbox Code Playgroud)