zipのような
前の記事でunzipのようなものを書いたので逆の、sprout::tuple<sprout::array<Types>...>からsprout::array<sprout::tuple<Types...>>への変換も書きました。長さが違う場合、短い方に合わせます。最も要素数の少ない配列の要素数探索を行う際のオーダーがO(N)ですが、対数オーダーでソートしてから二分探索すればもう少し計算量上では高速化出来るかもしれません。が現実的に数百種類もの配列をzipするような状況は思いつかないですしこの実装で十分かなと思います。
Wandbox http://melpon.org/wandbox/permlink/fIZJYxV8C7UTBsfw
#include <sprout/tuple.hpp> #include <sprout/array.hpp> #include <sprout/algorithm.hpp> #include <sprout/index_tuple.hpp> template <sprout::index_t ArrayIndex, class... Types, std::size_t... Ns> constexpr auto zip_impl3(const sprout::array<Types, Ns>&... elems) { return sprout::make_tuple(elems[ArrayIndex]...); } template <sprout::index_t... ArrayIndices, sprout::index_t... TupleIndices, std::size_t... Ns, class... Types> constexpr auto zip_impl2( const sprout::index_tuple<ArrayIndices...>&, const sprout::index_tuple<TupleIndices...>&, const sprout::tuple<sprout::array<Types, Ns>...>& unzipped) { return sprout::make_array<sprout::tuple<Types...>>( zip_impl3<ArrayIndices>(sprout::get<TupleIndices>(unzipped)...)...); } template <std::size_t M, std::size_t N, std::size_t... Ns> struct zip_impl : zip_impl<sprout::min(M, N), Ns...> {}; template <std::size_t M, std::size_t N> struct zip_impl<M, N> { static constexpr auto value = sprout::min(M, N); }; template <class... Types, std::size_t... Ns> constexpr auto zip(const sprout::tuple<sprout::array<Types, Ns>...>& unzipped) { return zip_impl2(sprout::index_range<0, zip_impl<Ns...>::value>::make(), sprout::index_range<0, sizeof...(Types)>::make(), unzipped); } int main() { constexpr auto unzipped = sprout::make_tuple(sprout::make_array<int>(1, 2, 3, 4), sprout::make_array<char>('a', 'b', 'c')); constexpr auto zipped = zip(unzipped); static_assert(sprout::get<0>(zipped[0]) == 1, ""); static_assert(sprout::get<1>(zipped[0]) == 'a', ""); static_assert(sprout::get<0>(zipped[1]) == 2, ""); static_assert(sprout::get<1>(zipped[1]) == 'b', ""); static_assert(sprout::get<0>(zipped[2]) == 3, ""); static_assert(sprout::get<1>(zipped[2]) == 'c', ""); }