From a96009adf7520cfd0b41037c6e08aa299299bf06 Mon Sep 17 00:00:00 2001 From: szdytom Date: Thu, 20 Jul 2023 00:11:54 +0800 Subject: [PATCH] [libvmake] allow concat multiple sequences --- libvmake/examples/concating.cpp | 9 ++++++ libvmake/vmake.hpp | 49 ++++++++++++++++++++++----------- 2 files changed, 42 insertions(+), 16 deletions(-) create mode 100644 libvmake/examples/concating.cpp diff --git a/libvmake/examples/concating.cpp b/libvmake/examples/concating.cpp new file mode 100644 index 0000000..901fac8 --- /dev/null +++ b/libvmake/examples/concating.cpp @@ -0,0 +1,9 @@ +#include "../vmake.hpp" +#include +using namespace std; + +int main() { + vmake::outputln(cout, " ", vmake::concat(vmake::range(1, 3) + , vmake::range(1, 4), vmake::range(1, 4, 2))); + return 0; +} diff --git a/libvmake/vmake.hpp b/libvmake/vmake.hpp index 1bdd12e..6494178 100644 --- a/libvmake/vmake.hpp +++ b/libvmake/vmake.hpp @@ -319,36 +319,51 @@ inline auto repeat_n(Tval &&x, size_t n) { namespace details { -template +template +inline bool concat_terminate_helper(T &g, std::index_sequence seq) { + bool res = true; + void(std::array{ + (!res || std::get(g).is_terminated() || (res = false))... + }); + return res; +} + +template +inline Res concat_call_helper(T &g, std::index_sequence seq) { + polyfill::optional x; + void(std::array{ + (x.has_value() || std::get(g).is_terminated() + || (x.emplace(std::move(std::get(g)()))))... + }); + if (!x.has_value()) throw sequence_terminated_error(); + return *x; +} + +template struct concator { using result = typename Gen1::result; - using core = Gen1; - using core2 = Gen2; + using core = std::tuple; - Gen1 g1; - Gen2 g2; + core g; - concator(Gen1 &&g1, Gen2 &&g2) : g1(std::move(g1)), g2(std::move(g2)) {} - concator(concator &&c) = default; - concator(const concator &c) = default; -// concator& operator=(concator &&c) = default; + concator(Gen1&& g1, Gen&&... g2) : g(std::forward(g1), std::forward(g2)...) {} + concator(concator&&) = default; + concator(const concator&) = default; bool is_terminated() const noexcept { - return g1.is_terminated() && g2.is_terminated(); + return concat_terminate_helper(g, std::make_index_sequence()); } auto operator()() { - if (g1.is_terminated()) return g2(); - return g1(); + return concat_call_helper(g, std::make_index_sequence()); } }; } // namespace details -template -inline constexpr auto concat(Gen1 &&x, Gen2 &&y) noexcept { - return details::concator::type - , typename std::decay::type>(std::forward(x), std::forward(y)); +template +inline constexpr auto concat(Gen&&... g) noexcept { + return details::concator::type...>(std::forward(g)...); } namespace details { @@ -685,6 +700,8 @@ using empty_sequence_int = decltype(nothing()); static_assert(is_sequence_t::value, ""); static_assert(is_sequence_t::value, ""); static_assert(is_sequence_t(empty_sequence_int{}))>::value, ""); +static_assert(is_sequence_t::value, ""); static_assert(!is_sequence_t::value, ""); static_assert(!is_sequence_t>::value, "");