提问者:小点点

展开和转发数组


我很难将std::数组的参数包展开并转发到另一个函数

假设我们有一个函数,它包含一个std::数组,我想要展开它,并将它作为参数传递给其他函数,我可以这样做:

template<typename T, typename...Ts>
void other_function(T, Ts...) { /* Do stuff with Ts */ }

template<typename T, size_t Size, size_t... I>
void forward_array(std::array<T, Size>& array_arg, std::index_sequence<I...>)
{
   other_function(array_arg[I]...);
// for Size == 3 let's say we get the same thing as we would write
// other_function(array_arg[0], array_arg[1], array_arg[2]
// I skipped the std::forward
}

现在让我们假设我们有一个函数做同样的事情,但是它需要多个不同大小的数组。

template<typename T, size_t... Sizes /*, size_t... I_Sequence0, size_t... I_Sequence1, ... I_SequenceN */>
void forward_many_arrays(std::array<T, Sizes>&... array_args /*, ???*/)
{
  other_func( /* ??? */);
}

我想展开每个array_arg并将其传递给other_func,但是在这里我要如何准确地做到这一点呢?。 我们需要一种方法来索引每个数组参数。

在我的实际程序中,我有一个类,它的成员std::array是std::reference_wrapper,它不是默认可构造的,我试图为这个类提供一个替代构造函数,它接受任意数量的数组,其中数组大小之和匹配成员数组大小,并将它委托给接受T个引用的显式构造函数,但是我有点卡在那里,因为我不知道如何处理展开。


共2个答案

匿名用户

你可能有一个“通用的”getter

template <std::size_t I, typename Container, typename ... Containers>
decltype(auto) get(Container&& container, Containers&&...containers)
{
    constexpr std::size_t size = std::tuple_size_v<std::decay_t<Container>>;
    if constexpr (I < size) {
        return container[I];
    } else {
        return get<I - size>(containers...);
    }
}

如:

template <typename...Ts>
void other_function(Ts... ts) { ((std::cout << ts << " "), ...); }

template<typename... Ts, size_t... Is>
void forward_many_arrays(std::index_sequence<Is...>, Ts&&...ts)
{
  other_function(get<Is>(ts...)...);
}

template<typename... Ts>
void forward_many_arrays(Ts&&...ts)
{
  forward_many_arrays(std::make_index_sequence<(std::tuple_size_v<std::decay_t<Ts>> + ...)>(), ts...);
}

演示

匿名用户

一种基于简单递归的实现;

template<std::size_t n, class Fn, class T, class... Ts>
void apply_all_impl(Fn fn, T& t, Ts&... ts) {
    if constexpr (n == 0)
        fn(t, ts...);
    else
        std::apply([&](auto&... args) {
            apply_all_impl<n - 1>(fn, ts..., args...);
        }, t);
}

template<class Fn, class... Ts>
void apply_all(Fn fn, Ts&... ts) {
    apply_all_impl<sizeof...(Ts)>(fn, ts...);
}

用法示例:

std::array<int, 3> arr1{1, 2, 3};
std::array<int, 4> arr2{4, 5, 6, 7};

auto print_all = [](auto... ts) { (std::cout << ... << ts); };
apply_all(print_all, arr1, arr2);    // Output: 1234567

演示