Skip to content

Commit

Permalink
Fix take_while_view
Browse files Browse the repository at this point in the history
  • Loading branch information
lackhole committed Jun 28, 2024
1 parent 6aea1bb commit 4cdb25e
Show file tree
Hide file tree
Showing 2 changed files with 61 additions and 3 deletions.
38 changes: 35 additions & 3 deletions include/preview/__ranges/views/take_while_view.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ namespace preview {
namespace ranges {

template<typename V, typename Pred>
class take_while_view {
class take_while_view : public view_interface<take_while_view<V, Pred>> {
public:
static_assert(ranges::view<V>::value, "Constraints not satisfied");
static_assert(ranges::input_range<V>::value, "Constraints not satisfied");
Expand Down Expand Up @@ -81,6 +81,38 @@ class take_while_view {
return !(x == y);
}

template<bool OtherConst, std::enable_if_t<conjunction<
bool_constant<(Const != OtherConst)>,
sentinel_for<sentinel_t<Base>, iterator_t<maybe_const<OtherConst, V>>>
>::value, int> = 0>
friend constexpr bool operator==(const iterator_t<maybe_const<OtherConst, V>>& x, const sentinel& y) {
return x == y.end_ || !preview::invoke(*y.pred_, *x);
}

template<bool OtherConst, std::enable_if_t<conjunction<
bool_constant<(Const != OtherConst)>,
sentinel_for<sentinel_t<Base>, iterator_t<maybe_const<OtherConst, V>>>
>::value, int> = 0>
friend constexpr bool operator==(const sentinel& y, const iterator_t<maybe_const<OtherConst, V>>& x) {
return x == y;
}

template<bool OtherConst, std::enable_if_t<conjunction<
bool_constant<(Const != OtherConst)>,
sentinel_for<sentinel_t<Base>, iterator_t<maybe_const<OtherConst, V>>>
>::value, int> = 0>
friend constexpr bool operator!=(const iterator_t<maybe_const<OtherConst, V>>& x, const sentinel& y) {
return !(x == y);
}

template<bool OtherConst, std::enable_if_t<conjunction<
bool_constant<(Const != OtherConst)>,
sentinel_for<sentinel_t<Base>, iterator_t<maybe_const<OtherConst, V>>>
>::value, int> = 0>
friend constexpr bool operator!=(const sentinel& y, const iterator_t<maybe_const<OtherConst, V>>& x) {
return !(x == y);
}

private:
sentinel_t<Base> end_;
const Pred* pred_;
Expand Down Expand Up @@ -125,15 +157,15 @@ class take_while_view {
negation<simple_view<V>>
>::value, int> = 0>
PREVIEW_CONSTEXPR_AFTER_CXX17 auto end() {
return sentinel<false>{ranges::end(base_), pred_.operator->()};
return sentinel<false>{ranges::end(base_), std::addressof(*pred_)};
}

template<typename Dummy = void, std::enable_if_t<preview::conjunction<std::is_void<Dummy>,
range<const V>,
indirect_unary_predicate<const Pred, iterator_t<const V>>
>::value, int> = 0>
PREVIEW_CONSTEXPR_AFTER_CXX17 auto end() const {
return sentinel<true>{ranges::end(base_), pred_.operator->()};
return sentinel<true>{ranges::end(base_), std::addressof(*pred_)};
}

private:
Expand Down
26 changes: 26 additions & 0 deletions test/ranges_views.cc
Original file line number Diff line number Diff line change
Expand Up @@ -523,3 +523,29 @@ TEST(VERSIONED(RangesViews), take_view) {
#endif
EXPECT_EQ(out, "3.141592");
}

TEST(VERSIONED(RangesViews), take_while_view) {
using namespace std::literals;
using namespace preview::literals;

for (int year : views::iota(2020)
| views::take_while([](int y){ return y < 2026; })) { (void)year; }

auto r1 = views::iota(10) | views::take_while([](int x) { return true; });
auto r2 = views::iota(10, 20) | views::take_while([](int x) { return true; });

auto it1 = r1.end();
auto it2 = r2.end();

EXPECT_TRUE(ranges::equal(
views::iota(2020) | views::take_while([](int y){ return y < 2026; }),
{2020, 2021, 2022, 2023, 2024, 2025}
));

const char note[]{"Today is yesterday's tomorrow!..."};
for (char x : ranges::take_while_view(note, [](char c){ return c != '.'; })) { (void)x; }
EXPECT_TRUE(ranges::equal(
ranges::take_while_view(note, [](char c){ return c != '.'; }),
"Today is yesterday's tomorrow!"_sv
));
}

0 comments on commit 4cdb25e

Please sign in to comment.