From e6943e416aa167b28d94ff3326bdd604a6bca728 Mon Sep 17 00:00:00 2001 From: Tristan Brindle Date: Tue, 20 Aug 2024 10:59:10 +0100 Subject: [PATCH] Require for_each_while() for sequence impls Temporarily, at least --- include/flux/core/concepts.hpp | 30 +++++++++++++++++++++++++++++ include/flux/op/adjacent_filter.hpp | 2 +- include/flux/op/cartesian_base.hpp | 14 ++++++++++++++ include/flux/op/drop.hpp | 2 +- include/flux/op/for_each_while.hpp | 21 +------------------- include/flux/op/scan.hpp | 2 ++ 6 files changed, 49 insertions(+), 22 deletions(-) diff --git a/include/flux/core/concepts.hpp b/include/flux/core/concepts.hpp index 0c91a31d..9b9a6a82 100644 --- a/include/flux/core/concepts.hpp +++ b/include/flux/core/concepts.hpp @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -143,6 +144,9 @@ concept sequence_concept = { Traits::move_at(seq, cur) } -> can_reference; { Traits::move_at_unchecked(seq, cur) } -> std::same_as>; } && + requires (Seq& seq, bool (*pred)(element_t)) { + { Traits::for_each_while(seq, pred) } -> std::same_as>; + } && #ifdef FLUX_HAVE_CPP23_TUPLE_COMMON_REF std::common_reference_with&&, value_t&> && std::common_reference_with&&, value_t const&> && @@ -403,6 +407,32 @@ struct default_sequence_traits { return Traits::distance(self, Traits::first(self), Traits::last(self)); } + template + requires detail::sequence_requirements + static constexpr auto for_each_while(Self& self, Pred&& pred) -> cursor_t + { + using Traits = detail::traits_t; + + auto cur = Traits::first(self); + if constexpr (bounded_sequence && regular_cursor>) { + auto const last = Traits::last(self); + while (cur != last) { + if (!std::invoke(pred, Traits::read_at(self, cur))) { + break; + } + Traits::inc(self, cur); + } + } else { + while (!Traits::is_last(self, cur)) { + if (!std::invoke(pred, Traits::read_at(self, cur))) { + break; + } + Traits::inc(self, cur); + } + } + return cur; + } + }; namespace detail { diff --git a/include/flux/op/adjacent_filter.hpp b/include/flux/op/adjacent_filter.hpp index 53dacef2..337b2d63 100644 --- a/include/flux/op/adjacent_filter.hpp +++ b/include/flux/op/adjacent_filter.hpp @@ -25,7 +25,7 @@ struct adjacent_filter_adaptor pred_(std::move(pred)) {} - struct flux_sequence_traits { + struct flux_sequence_traits : default_sequence_traits { private: struct cursor_type { cursor_t base_cur; diff --git a/include/flux/op/cartesian_base.hpp b/include/flux/op/cartesian_base.hpp index 73f3f655..01597d6c 100644 --- a/include/flux/op/cartesian_base.hpp +++ b/include/flux/op/cartesian_base.hpp @@ -379,6 +379,20 @@ struct cartesian_traits_base_impl : default_sequence_traits { return cur; } + template + static constexpr auto for_each_while(Self& self, Function&& func) -> cursor_t + requires (ReadKind == read_kind::map) + { + auto cur = first(self); + while (!is_last(self, cur)) { + if (!std::invoke(func, read_at(self, cur))) { + break; + } + inc(self, cur); + } + return cur; + } + }; template diff --git a/include/flux/op/drop.hpp b/include/flux/op/drop.hpp index 16de2cf2..9675a440 100644 --- a/include/flux/op/drop.hpp +++ b/include/flux/op/drop.hpp @@ -54,7 +54,7 @@ struct drop_adaptor : inline_sequence_base> { return flux::data(self.base()) + (cmp::min)(self.count_, flux::size(self.base_)); } - void for_each_while(...) = delete; + using default_sequence_traits::for_each_while; }; }; diff --git a/include/flux/op/for_each_while.hpp b/include/flux/op/for_each_while.hpp index 9e2c7fb3..278e71a2 100644 --- a/include/flux/op/for_each_while.hpp +++ b/include/flux/op/for_each_while.hpp @@ -18,26 +18,7 @@ struct for_each_while_fn { boolean_testable>> constexpr auto operator()(Seq&& seq, Pred pred) const -> cursor_t { - if constexpr (requires { traits_t::for_each_while(seq, std::move(pred)); }) { - return traits_t::for_each_while(seq, std::move(pred)); - } else { - if constexpr (multipass_sequence && bounded_sequence) { - auto cur = first(seq); - auto end = last(seq); - while (cur != end) { - if (!std::invoke(pred, read_at(seq, cur))) { break; } - inc(seq, cur); - } - return cur; - } else { - auto cur = first(seq); - while (!is_last(seq, cur)) { - if (!std::invoke(pred, read_at(seq, cur))) { break; } - inc(seq, cur); - } - return cur; - } - } + return traits_t::for_each_while(seq, std::move(pred)); } }; diff --git a/include/flux/op/scan.hpp b/include/flux/op/scan.hpp index 42f9173f..2de2668b 100644 --- a/include/flux/op/scan.hpp +++ b/include/flux/op/scan.hpp @@ -146,6 +146,8 @@ struct scan_adaptor : inline_sequence_base> { return std::invoke(pred, std::as_const(self.accum_)); })); } + + using default_sequence_traits::for_each_while; // when Mode == exclusive }; };