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

Can you interleave variadic parameters in call sites?

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

我实际上想执行以下操作,但我不知道如何执行(伪代码):

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]));
}

注意:我知道可以做到以下几点(伪代码):

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]));
}

我想到的一个部分解决方案是添加一个 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));
}

但我想我必须手动编写每个我想考虑的案例。

像这样:

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++)))...));
}

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

如果您想避免复制 parse<Ts>(*(things++)) 的 return 值,您可以使用 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...>());
}