#include #include #include #include #include #include #include /*! \brief Unpacks a range of tuples into a set of ranges \param begin,end The range to unpack \param outs... The ranges to output to \return InputIterator An iterator to one past the last element unpacked */ template InputIterator unpack_copy(InputIterator begin, InputIterator end, OutputIterators... outs) { for (; begin != end; ++begin) { std::tie(*outs...) = *begin; (++outs, ...); } return begin; } /*! \brief Unpack results from a generator into a set of ranges \param g A generator that returns a tuple \param N The number of times to call the generator \param outs The ranges to output to \return Generator g */ template Generator unpack_generate_n(Generator g, std::size_t N, OutputIterators... outs) { for (std::size_t i = 0; i != N; ++i) { std::tie(*outs...) = g(); (++outs, ...); } return g; } template struct parallel_vector { using type = T; }; template struct parallel_vector> { using type = std::tuple...>; }; template struct parallel_vector> { using type = std::array, N>; }; template using parallel_vector_t = typename parallel_vector::type; template using parallel_vector_for_t = parallel_vector_t::value_type>; namespace detail { template void push_multiple(TupleIn in, TupleOut& out, std::index_sequence) { return (void(), ..., std::get(out).push_back(std::get(in))); } } // namespace detail /*! \brief Unpacks a range of tuples into a new tuple of vectors \param begin,end The range to unpack \return parallel_vector_for_t A tuple of vectors containing the unpacked elements */ template parallel_vector_for_t unpack_build_copy(InputIterator begin, InputIterator end) { parallel_vector_for_t output; for (; begin != end; ++begin) { detail::push_multiple( *begin, output, std::make_index_sequence< std::tuple_size_v>>{}); } return output; } template using parallel_vector_gen_t = parallel_vector_t()())>>; /*! \brief Unpacks a tuple-yielding generator into a new tuple of vectors \param g A generator that returns a tuple \param N The number of times to call the generator \return parallel_vector_gen_t A tuple of vectors containing the unpacked results of the generator */ template parallel_vector_gen_t unpack_build_generate_n(Generator g, std::size_t N) { parallel_vector_gen_t output; for (std::size_t i = 0; i != N; ++i) { detail::push_multiple( g(), output, std::make_index_sequence< std::tuple_size_v>>{}); } return output; } int multi_main(int, char**) { std::vector a, b; unpack_generate_n( [i = 0]() mutable -> std::tuple { return {i, 8 - i++}; }, 8, std::back_inserter(a), std::back_inserter(b)); std::cout << "a, b: "; for (std::size_t i = 0; i != a.size(); ++i) { std::cout << a[i] << ' ' << b[i] << ' '; } std::cout << '\n'; const std::vector> V{{1, 8}, {2, 7}, {3, 6}, {4, 5}, {5, 4}, {6, 3}, {7, 2}, {8, 1}}; std::vector c, d; unpack_copy(V.cbegin(), V.cend(), std::back_inserter(c), std::back_inserter(d)); std::cout << "c, d: "; for (std::size_t i = 0; i != c.size(); ++i) { std::cout << c[i] << ' ' << d[i] << ' '; } std::cout << '\n'; auto [x, y] = unpack_build_generate_n( [i = 0]() mutable -> std::tuple { return {i, 8 - i++}; }, 8); std::cout << "x, y: "; for (std::size_t i = 0; i != x.size(); ++i) { std::cout << x[i] << ' ' << y[i] << ' '; } std::cout << '\n'; auto [z, w] = unpack_build_copy(V.cbegin(), V.cend()); std::cout << "z, w: "; for (std::size_t i = 0; i != z.size(); ++i) { std::cout << z[i] << ' ' << w[i] << ' '; } std::cout << '\n'; return 0; }