Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement drop_while_view #1366

Merged
merged 14 commits into from
Nov 6, 2020
52 changes: 0 additions & 52 deletions stl/inc/algorithm
Original file line number Diff line number Diff line change
Expand Up @@ -499,58 +499,6 @@ template <class _ExPo, class _FwdIt, class _Pr, _Enable_if_execution_policy_t<_E
_NODISCARD _FwdIt find_if_not(_ExPo&& _Exec, _FwdIt _First, _FwdIt _Last, _Pr _Pred) noexcept; // terminates
#endif // _HAS_CXX17

#ifdef __cpp_lib_concepts
namespace ranges {
// VARIABLE ranges::find_if_not
class _Find_if_not_fn : private _Not_quite_object {
public:
using _Not_quite_object::_Not_quite_object;

template <input_iterator _It, sentinel_for<_It> _Se, class _Pj = identity,
indirect_unary_predicate<projected<_It, _Pj>> _Pr>
_NODISCARD constexpr _It operator()(_It _First, _Se _Last, _Pr _Pred, _Pj _Proj = {}) const {
_Adl_verify_range(_First, _Last);

auto _UResult = _Find_if_not_unchecked(
_Get_unwrapped(_STD move(_First)), _Get_unwrapped(_STD move(_Last)), _Pass_fn(_Pred), _Pass_fn(_Proj));

_Seek_wrapped(_First, _STD move(_UResult));
return _First;
}

template <input_range _Rng, class _Pj = identity,
indirect_unary_predicate<projected<iterator_t<_Rng>, _Pj>> _Pr>
_NODISCARD constexpr borrowed_iterator_t<_Rng> operator()(_Rng&& _Range, _Pr _Pred, _Pj _Proj = {}) const {
auto _First = _RANGES begin(_Range);

auto _UResult = _Find_if_not_unchecked(
_Get_unwrapped(_STD move(_First)), _Uend(_Range), _Pass_fn(_Pred), _Pass_fn(_Proj));

_Seek_wrapped(_First, _STD move(_UResult));
return _First;
}

private:
template <class _It, class _Se, class _Pj, class _Pr>
_NODISCARD static constexpr _It _Find_if_not_unchecked(_It _First, const _Se _Last, _Pr _Pred, _Pj _Proj) {
_STL_INTERNAL_STATIC_ASSERT(input_iterator<_It>);
_STL_INTERNAL_STATIC_ASSERT(sentinel_for<_Se, _It>);
_STL_INTERNAL_STATIC_ASSERT(indirect_unary_predicate<_Pr, projected<_It, _Pj>>);

for (; _First != _Last; ++_First) {
if (!_STD invoke(_Pred, _STD invoke(_Proj, *_First))) {
break;
}
}

return _First;
}
};

inline constexpr _Find_if_not_fn find_if_not{_Not_quite_object::_Construct_tag{}};
} // namespace ranges
#endif // __cpp_lib_concepts

// FUNCTION TEMPLATE adjacent_find
template <class _FwdIt, class _Pr>
_NODISCARD _CONSTEXPR20 _FwdIt adjacent_find(const _FwdIt _First, _FwdIt _Last, _Pr _Pred) {
Expand Down
98 changes: 98 additions & 0 deletions stl/inc/ranges
Original file line number Diff line number Diff line change
Expand Up @@ -1915,6 +1915,104 @@ namespace ranges {
inline constexpr _Drop_fn drop;
} // namespace views

// CLASS TEMPLATE ranges::drop_while_view
// clang-format off
template <view _Vw, class _Pr>
requires input_range<_Vw> && is_object_v<_Pr> && indirect_unary_predicate<const _Pr, iterator_t<_Vw>>
class drop_while_view : public _Cached_position_t<forward_range<_Vw>, _Vw, drop_while_view<_Vw, _Pr>> {
// clang-format on
private:
/* [[no_unique_address]] */ _Vw _Range{};
/* [[no_unique_address]] */ _Semiregular_box<_Pr> _Pred{};

public:
drop_while_view() = default;

constexpr drop_while_view(_Vw _Range_, _Pr _Pred_) noexcept(
is_nothrow_move_constructible_v<_Vw>&& is_nothrow_move_constructible_v<_Pr>) // strengthened
: _Range(_STD move(_Range_)), _Pred{in_place, _STD move(_Pred_)} {}

_NODISCARD constexpr _Vw base() const& noexcept(
is_nothrow_copy_constructible_v<_Vw>) /* strengthened */ requires copy_constructible<_Vw> {
return _Range;
}
_NODISCARD constexpr _Vw base() && noexcept(is_nothrow_move_constructible_v<_Vw>) /* strengthened */ {
return _STD move(_Range);
}

_NODISCARD constexpr const _Pr& pred() const noexcept /* strengthened */ {
#if _CONTAINER_DEBUG_LEVEL > 0
_STL_VERIFY(_Pred, "value-initialized drop_while_view has no predicate");
#endif // _CONTAINER_DEBUG_LEVEL > 0
return *_Pred;
}

_NODISCARD constexpr auto begin() {
#if _CONTAINER_DEBUG_LEVEL > 0
_STL_VERIFY(_Pred, "LWG-3490 forbids calling begin on a drop_while_view with no predicate");
#endif // _CONTAINER_DEBUG_LEVEL > 0
if constexpr (forward_range<_Vw>) {
if (this->_Has_cache()) {
return this->_Get_cache(_Range);
}
}

auto _First = _RANGES find_if_not(_Range, _STD cref(*_Pred));
if constexpr (forward_range<_Vw>) {
this->_Set_cache(_Range, _First);
}

return _First;
}

_NODISCARD constexpr auto end() noexcept(noexcept(_RANGES end(_Range))) /* strengthened */ {
return _RANGES end(_Range);
}
};

template <class _Rng, class _Pr>
drop_while_view(_Rng&&, _Pr) -> drop_while_view<views::all_t<_Rng>, _Pr>;

namespace views {
// VARIABLE views::drop_while
class _Drop_while_fn {
private:
template <class _Pr>
struct _Partial : _Pipe::_Base<_Partial<_Pr>> {
/* [[no_unique_address]] */ _Semiregular_box<_Pr> _Pred;

template <viewable_range _Rng>
_NODISCARD constexpr auto operator()(_Rng&& _Range) const& noexcept(
noexcept(drop_while_view{_STD forward<_Rng>(_Range), *_Pred})) requires requires {
drop_while_view{static_cast<_Rng&&>(_Range), *_Pred};
}
{ return drop_while_view{_STD forward<_Rng>(_Range), *_Pred}; }

template <viewable_range _Rng>
_NODISCARD constexpr auto operator()(_Rng&& _Range) && noexcept(
noexcept(drop_while_view{_STD forward<_Rng>(_Range), _STD move(*_Pred)})) requires requires {
drop_while_view{static_cast<_Rng&&>(_Range), _STD move(*_Pred)};
}
{ return drop_while_view{_STD forward<_Rng>(_Range), _STD move(*_Pred)}; }
};

public:
template <viewable_range _Rng, class _Pr>
_NODISCARD constexpr auto operator()(_Rng&& _Range, _Pr _Pred) const
noexcept(noexcept(drop_while_view{_STD forward<_Rng>(_Range), _STD move(_Pred)})) requires requires {
drop_while_view{static_cast<_Rng&&>(_Range), _STD move(_Pred)};
}
{ return drop_while_view{_STD forward<_Rng>(_Range), _STD move(_Pred)}; }

template <_Copy_constructible_object _Pr>
_NODISCARD constexpr auto operator()(_Pr _Pred) const noexcept(is_nothrow_move_constructible_v<_Pr>) {
return _Partial<_Pr>{._Pred = {in_place, _STD move(_Pred)}};
}
};

inline constexpr _Drop_while_fn drop_while;
} // namespace views

// CLASS TEMPLATE ranges::reverse_view
// clang-format off
template <view _Vw>
Expand Down
48 changes: 48 additions & 0 deletions stl/inc/xutility
Original file line number Diff line number Diff line change
Expand Up @@ -5849,6 +5849,54 @@ namespace ranges {
};

inline constexpr _Find_if_fn find_if{_Not_quite_object::_Construct_tag{}};

// VARIABLE ranges::find_if_not
class _Find_if_not_fn : private _Not_quite_object {
public:
using _Not_quite_object::_Not_quite_object;

template <input_iterator _It, sentinel_for<_It> _Se, class _Pj = identity,
indirect_unary_predicate<projected<_It, _Pj>> _Pr>
_NODISCARD constexpr _It operator()(_It _First, _Se _Last, _Pr _Pred, _Pj _Proj = {}) const {
_Adl_verify_range(_First, _Last);

auto _UResult = _Find_if_not_unchecked(
_Get_unwrapped(_STD move(_First)), _Get_unwrapped(_STD move(_Last)), _Pass_fn(_Pred), _Pass_fn(_Proj));

_Seek_wrapped(_First, _STD move(_UResult));
return _First;
}

template <input_range _Rng, class _Pj = identity,
indirect_unary_predicate<projected<iterator_t<_Rng>, _Pj>> _Pr>
_NODISCARD constexpr borrowed_iterator_t<_Rng> operator()(_Rng&& _Range, _Pr _Pred, _Pj _Proj = {}) const {
auto _First = _RANGES begin(_Range);

auto _UResult = _Find_if_not_unchecked(
_Get_unwrapped(_STD move(_First)), _Uend(_Range), _Pass_fn(_Pred), _Pass_fn(_Proj));

_Seek_wrapped(_First, _STD move(_UResult));
return _First;
}

private:
template <class _It, class _Se, class _Pj, class _Pr>
_NODISCARD static constexpr _It _Find_if_not_unchecked(_It _First, const _Se _Last, _Pr _Pred, _Pj _Proj) {
_STL_INTERNAL_STATIC_ASSERT(input_iterator<_It>);
_STL_INTERNAL_STATIC_ASSERT(sentinel_for<_Se, _It>);
_STL_INTERNAL_STATIC_ASSERT(indirect_unary_predicate<_Pr, projected<_It, _Pj>>);

for (; _First != _Last; ++_First) {
if (!_STD invoke(_Pred, _STD invoke(_Proj, *_First))) {
break;
}
}

return _First;
}
};

inline constexpr _Find_if_not_fn find_if_not{_Not_quite_object::_Construct_tag{}};
} // namespace ranges
#endif // __cpp_lib_concepts

Expand Down
2 changes: 2 additions & 0 deletions tests/std/test.lst
Original file line number Diff line number Diff line change
Expand Up @@ -340,6 +340,8 @@ tests\P0896R4_ranges_to_address
tests\P0896R4_stream_iterators
tests\P0896R4_views_all
tests\P0896R4_views_drop
tests\P0896R4_views_drop_while
tests\P0896R4_views_drop_while_death
tests\P0896R4_views_empty
tests\P0896R4_views_filter
tests\P0896R4_views_filter_death
Expand Down
1 change: 1 addition & 0 deletions tests/std/tests/P0896R4_ranges_range_machinery/test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ STATIC_ASSERT(test_cpo(ranges::cdata));

STATIC_ASSERT(test_cpo(ranges::views::all));
STATIC_ASSERT(test_cpo(ranges::views::drop));
STATIC_ASSERT(test_cpo(ranges::views::drop_while));
STATIC_ASSERT(test_cpo(ranges::views::filter));
STATIC_ASSERT(test_cpo(ranges::views::reverse));
STATIC_ASSERT(test_cpo(ranges::views::single));
Expand Down
4 changes: 4 additions & 0 deletions tests/std/tests/P0896R4_views_drop_while/env.lst
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# Copyright (c) Microsoft Corporation.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

RUNALL_INCLUDE ..\concepts_matrix.lst
Loading