From 785d40e5782e7a96adfd14db8b787f1f10e0de97 Mon Sep 17 00:00:00 2001 From: szdytom Date: Sun, 23 Jul 2023 16:28:39 +0800 Subject: [PATCH] [libvmake] add vmake::zip() --- libvmake/examples/zipping.cpp | 9 ++++++ libvmake/vmake.hpp | 60 ++++++++++++++++++++++++++++++++++- 2 files changed, 68 insertions(+), 1 deletion(-) create mode 100644 libvmake/examples/zipping.cpp diff --git a/libvmake/examples/zipping.cpp b/libvmake/examples/zipping.cpp new file mode 100644 index 0000000..b967b83 --- /dev/null +++ b/libvmake/examples/zipping.cpp @@ -0,0 +1,9 @@ +#include "../vmake.hpp" +using namespace std; + +int main() { + vmake::outputln(cout, " ", vmake::transform(vmake::zip(vmake::range(1, 10) + , vmake::range(2, 10, 2)), [](const auto &x) { + return std::get<0>(x) + std::get<1>(x); + })); +} diff --git a/libvmake/vmake.hpp b/libvmake/vmake.hpp index b7bf761..43a31d1 100644 --- a/libvmake/vmake.hpp +++ b/libvmake/vmake.hpp @@ -523,7 +523,7 @@ struct grouper { } }; -} +} // namespace details template inline auto group(Gen &&g) { @@ -536,6 +536,64 @@ inline decltype(auto) discard_n(Gen &&g, size_t n) { return std::forward(g); } +namespace details { + +template +auto zipper_call_helper(Gen &&g, std::index_sequence) { + return std::make_tuple(std::get(g)()...); +} + +inline constexpr bool zip_terminate_helper() noexcept { + return false; +} + +template +inline bool zip_terminate_helper(Seq& f, Seqs& ...rest) noexcept { + if (f.is_terminated()) return true; + return zip_terminate_helper(rest...); +} + +template +inline auto zip_terminate_applier(Tuple &t, std::index_sequence) noexcept { + return polyfill::apply(zip_terminate_helper< + typename std::tuple_element::type...>, t); +} + + +template +struct zipper { +private: + static constexpr auto _n = std::tuple_size::value; + using _make_index = std::make_index_sequence<_n>; + +public: + using result = decltype(zipper_call_helper(std::declval(), _make_index())); + using core = Gen; + + Gen g; + + zipper(zipper &&) = default; + zipper(const zipper &) = default; + + zipper(Gen &&g) : g(std::forward(g)) {} + + bool is_terminated() const noexcept { + return zip_terminate_applier(g, _make_index()); + } + + decltype(auto) operator()() { + return zipper_call_helper(g, _make_index()); + } +}; + +} // namespace detail + +template +inline decltype(auto) zip(Gen&&... g) { + using Tuple = std::tuple::type...>; + return details::zipper(std::make_tuple(std::forward(g)...)); +} + namespace rng { inline auto make_seed() {