Skip to content

Commit

Permalink
Reuse find{_if} implementation for remove{_if}
Browse files Browse the repository at this point in the history
  • Loading branch information
miscco committed Jul 6, 2020
1 parent e15e991 commit 14e98b0
Show file tree
Hide file tree
Showing 2 changed files with 63 additions and 29 deletions.
88 changes: 61 additions & 27 deletions stl/inc/algorithm
Original file line number Diff line number Diff line change
Expand Up @@ -386,6 +386,20 @@ namespace ranges {
inline constexpr _For_each_n_fn for_each_n{_Not_quite_object::_Construct_tag{}};

// VARIABLE ranges::find
// clang-format off
template <input_iterator _It, sentinel_for<_It> _Se, class _Ty, class _Pj = identity>
requires indirect_binary_predicate<ranges::equal_to, projected<_It, _Pj>, const _Ty*>
_NODISCARD constexpr _It _Find_unchecked(_It _First, _Se _Last, const _Ty& _Val, _Pj _Proj = {}) {
for (; _First != _Last; ++_First) {
if (_STD invoke(_Proj, *_First) == _Val) {
break;
}
}

return _First;
}
// clang-format on

class _Find_fn : private _Not_quite_object {
public:
using _Not_quite_object::_Not_quite_object;
Expand All @@ -394,25 +408,25 @@ namespace ranges {
template <input_iterator _It, sentinel_for<_It> _Se, class _Ty, class _Pj = identity>
requires indirect_binary_predicate<ranges::equal_to, projected<_It, _Pj>, const _Ty*>
_NODISCARD constexpr _It operator()(_It _First, _Se _Last, const _Ty& _Val, _Pj _Proj = {}) const {
_Adl_verify_range(_First, _Last);
// Performance note: investigate using _Find_unchecked when same_as<_Pj, identity>
auto _UFirst = _Get_unwrapped(_STD move(_First));
const auto _ULast = _Get_unwrapped(_STD move(_Last));
for (; _UFirst != _ULast; ++_UFirst) {
if (_STD invoke(_Proj, *_UFirst) == _Val) {
break;
}
}
_Adl_verify_range(_First, _Last);
auto _UResult = _RANGES _Find_unchecked(
_Get_unwrapped(_STD move(_First)), _Get_unwrapped(_STD move(_Last)), _Val, _Pass_fn(_Proj));

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

template <input_range _Rng, class _Ty, class _Pj = identity>
requires indirect_binary_predicate<ranges::equal_to, projected<iterator_t<_Rng>, _Pj>, const _Ty*>
_NODISCARD constexpr borrowed_iterator_t<_Rng> operator()(
// Performance note: investigate using _Find_unchecked when same_as<_Pj, identity>
_Rng&& _Range, const _Ty& _Val, _Pj _Proj = {}) const {
return (*this)(_RANGES begin(_Range), _RANGES end(_Range), _Val, _Pass_fn(_Proj));
auto _First = _RANGES begin(_Range);
auto _UResult = _RANGES _Find_unchecked(_First, _Uend(_Range), _Val, _Pass_fn(_Proj));

_Seek_wrapped(_First, _STD move(_UResult));
return _First;
}
// clang-format on
};
Expand All @@ -430,6 +444,18 @@ _NODISCARD _FwdIt find_if(_ExPo&& _Exec, _FwdIt _First, const _FwdIt _Last, _Pr
#ifdef __cpp_lib_concepts
namespace ranges {
// VARIABLE ranges::find_if
template <input_iterator _It, sentinel_for<_It> _Se, class _Pj = identity,
indirect_unary_predicate<projected<_It, _Pj>> _Pr>
_NODISCARD constexpr _It _Find_if_unchecked(_It _First, _Se _Last, _Pr _Pred, _Pj _Proj = {}) {
for (; _First != _Last; ++_First) {
if (_STD invoke(_Pred, _STD invoke(_Proj, *_First))) {
break;
}
}

return _First;
}

class _Find_if_fn : private _Not_quite_object {
public:
using _Not_quite_object::_Not_quite_object;
Expand All @@ -438,22 +464,21 @@ namespace ranges {
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 _UFirst = _Get_unwrapped(_STD move(_First));
const auto _ULast = _Get_unwrapped(_STD move(_Last));
for (; _UFirst != _ULast; ++_UFirst) {
if (_STD invoke(_Pred, _STD invoke(_Proj, *_UFirst))) {
break;
}
}
auto _UResult = _Find_if_unchecked(
_Get_unwrapped(_STD move(_First)), _Get_unwrapped(_STD move(_Last)), _Pass_fn(_Pred), _Pass_fn(_Proj));

_Seek_wrapped(_First, _STD move(_UFirst));
_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 {
return (*this)(_RANGES begin(_Range), _RANGES end(_Range), _Pass_fn(_Pred), _Pass_fn(_Proj));
auto _First = _RANGES begin(_Range);
auto _UResult = _RANGES _Find_if_unchecked(_First, _Uend(_Range), _Pass_fn(_Pred), _Pass_fn(_Proj));

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

Expand Down Expand Up @@ -3302,16 +3327,21 @@ namespace ranges {
requires indirect_binary_predicate<ranges::equal_to, projected<_It, _Pj>, const _Ty*>
constexpr subrange<_It> operator()(_It _First, _Se _Last, const _Ty& _Val, _Pj _Proj = {}) const {
_Adl_verify_range(_First, _Last);
auto _UResult = _Remove_unchecked(
_Get_unwrapped(_STD move(_First)), _Get_unwrapped(_STD move(_Last)), _Val, _Pass_fn(_Proj));
auto _ULast = _Get_unwrapped(_STD move(_Last));
auto _UFirst = _Find_unchecked(_Get_unwrapped(_STD move(_First)), _ULast, _Val, _Pass_fn(_Proj));
auto _UResult = _Remove_unchecked(_UFirst, _ULast, _Val, _Pass_fn(_Proj));

return _Rewrap_subrange<subrange<_It>>(_First, _STD move(_UResult));
}

template <forward_range _Rng, class _Ty, class _Pj = identity>
requires permutable<iterator_t<_Rng>>
&& indirect_binary_predicate<ranges::equal_to, projected<iterator_t<_Rng>, _Pj>, const _Ty*>
constexpr borrowed_subrange_t<_Rng> operator()(_Rng&& _Range, const _Ty& _Val, _Pj _Proj = {}) const {
auto _UResult = _Remove_unchecked(_Ubegin(_Range), _Uend(_Range), _Val, _Pass_fn(_Proj));
auto _ULast = _Uend(_Range);
auto _UFirst = _Find_unchecked(_Ubegin(_Range), _ULast, _Val, _Pass_fn(_Proj));
auto _UResult = _Remove_unchecked(_UFirst, _ULast, _Val, _Pass_fn(_Proj));

return _Rewrap_subrange<borrowed_subrange_t<_Rng>>(_Range, _STD move(_UResult));
}
// clang-format on
Expand Down Expand Up @@ -3347,8 +3377,10 @@ namespace ranges {
indirect_unary_predicate<projected<_It, _Pj>> _Pr>
constexpr subrange<_It> operator()(_It _First, _Se _Last, _Pr _Pred, _Pj _Proj = {}) const {
_Adl_verify_range(_First, _Last);
auto _UResult = _Remove_if_unchecked(
_Get_unwrapped(_STD move(_First)), _Get_unwrapped(_STD move(_Last)), _Pass_fn(_Pred), _Pass_fn(_Proj));
auto _ULast = _Get_unwrapped(_STD move(_Last));
auto _UFirst =
_Find_if_unchecked(_Get_unwrapped(_STD move(_First)), _ULast, _Pass_fn(_Pred), _Pass_fn(_Proj));
auto _UResult = _Remove_if_unchecked(_UFirst, _ULast, _Pass_fn(_Pred), _Pass_fn(_Proj));

return _Rewrap_subrange<subrange<_It>>(_First, _STD move(_UResult));
}
Expand All @@ -3358,7 +3390,9 @@ namespace ranges {
indirect_unary_predicate<projected<iterator_t<_Rng>, _Pj>> _Pr>
requires permutable<iterator_t<_Rng>>
constexpr borrowed_subrange_t<_Rng> operator()(_Rng&& _Range, _Pr _Pred, _Pj _Proj = {}) const {
auto _UResult = _Remove_if_unchecked(_Ubegin(_Range), _Uend(_Range), _Pass_fn(_Pred), _Pass_fn(_Proj));
auto _ULast = _Uend(_Range);
auto _UFirst = _Find_if_unchecked(_Ubegin(_Range), _ULast, _Pass_fn(_Pred), _Pass_fn(_Proj));
auto _UResult = _Remove_if_unchecked(_UFirst, _ULast, _Pass_fn(_Pred), _Pass_fn(_Proj));

return _Rewrap_subrange<borrowed_subrange_t<_Rng>>(_Range, _STD move(_UResult));
}
Expand Down Expand Up @@ -3432,7 +3466,7 @@ namespace ranges {

for (; _First != _Last; ++_First) {
if (_STD invoke(_Proj, *_First) != _Val) {
*_Result = _RANGES iter_move(_First);
*_Result = *_First;
++_Result;
}
}
Expand Down Expand Up @@ -3490,7 +3524,7 @@ namespace ranges {

for (; _First != _Last; ++_First) {
if (!_STD invoke(_Pred, _STD invoke(_Proj, *_First))) {
*_Result = _RANGES iter_move(_First);
*_Result = *_First;
++_Result;
}
}
Expand Down
4 changes: 2 additions & 2 deletions tests/std/tests/P0896R4_ranges_alg_remove_copy/test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,6 @@ struct instantiator {
};

int main() {
STATIC_ASSERT((test_fwd_write<instantiator, P, P>(), true));
test_fwd_write<instantiator, P, P>();
STATIC_ASSERT((test_fwd_write<instantiator, P const, P>(), true));
test_fwd_write<instantiator, P const, P>();
}

0 comments on commit 14e98b0

Please sign in to comment.