Skip to content

Commit

Permalink
Require for_each_while() for sequence impls
Browse files Browse the repository at this point in the history
Temporarily, at least
  • Loading branch information
tcbrindle committed Aug 20, 2024
1 parent e68ef68 commit e6943e4
Show file tree
Hide file tree
Showing 6 changed files with 49 additions and 22 deletions.
30 changes: 30 additions & 0 deletions include/flux/core/concepts.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include <compare>
#include <concepts>
#include <cstdint>
#include <functional>
#include <initializer_list>
#include <tuple>
#include <type_traits>
Expand Down Expand Up @@ -143,6 +144,9 @@ concept sequence_concept =
{ Traits::move_at(seq, cur) } -> can_reference;
{ Traits::move_at_unchecked(seq, cur) } -> std::same_as<rvalue_element_t<Seq>>;
} &&
requires (Seq& seq, bool (*pred)(element_t<Seq>)) {
{ Traits::for_each_while(seq, pred) } -> std::same_as<cursor_t<Seq>>;
} &&
#ifdef FLUX_HAVE_CPP23_TUPLE_COMMON_REF
std::common_reference_with<element_t<Seq>&&, value_t<Seq>&> &&
std::common_reference_with<rvalue_element_t<Seq>&&, value_t<Seq> const&> &&
Expand Down Expand Up @@ -403,6 +407,32 @@ struct default_sequence_traits {
return Traits::distance(self, Traits::first(self), Traits::last(self));
}

template <typename Self, typename Pred>
requires detail::sequence_requirements<Self>
static constexpr auto for_each_while(Self& self, Pred&& pred) -> cursor_t<Self>
{
using Traits = detail::traits_t<Self>;

auto cur = Traits::first(self);
if constexpr (bounded_sequence<Self> && regular_cursor<cursor_t<Self>>) {
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 {
Expand Down
2 changes: 1 addition & 1 deletion include/flux/op/adjacent_filter.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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> base_cur;
Expand Down
14 changes: 14 additions & 0 deletions include/flux/op/cartesian_base.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -379,6 +379,20 @@ struct cartesian_traits_base_impl : default_sequence_traits {
return cur;
}

template <typename Self, typename Function>
static constexpr auto for_each_while(Self& self, Function&& func) -> cursor_t<Self>
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 <std::size_t Arity, cartesian_kind CartesianKind, read_kind ReadKind, typename... Bases>
Expand Down
2 changes: 1 addition & 1 deletion include/flux/op/drop.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ struct drop_adaptor : inline_sequence_base<drop_adaptor<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;
};
};

Expand Down
21 changes: 1 addition & 20 deletions include/flux/op/for_each_while.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,26 +18,7 @@ struct for_each_while_fn {
boolean_testable<std::invoke_result_t<Pred&, element_t<Seq>>>
constexpr auto operator()(Seq&& seq, Pred pred) const -> cursor_t<Seq>
{
if constexpr (requires { traits_t<Seq>::for_each_while(seq, std::move(pred)); }) {
return traits_t<Seq>::for_each_while(seq, std::move(pred));
} else {
if constexpr (multipass_sequence<Seq> && bounded_sequence<Seq>) {
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<Seq>::for_each_while(seq, std::move(pred));
}
};

Expand Down
2 changes: 2 additions & 0 deletions include/flux/op/scan.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,8 @@ struct scan_adaptor : inline_sequence_base<scan_adaptor<Base, Func, R, Mode>> {
return std::invoke(pred, std::as_const(self.accum_));
}));
}

using default_sequence_traits::for_each_while; // when Mode == exclusive
};
};

Expand Down

0 comments on commit e6943e4

Please sign in to comment.