Skip to content

Commit

Permalink
Implement ranges::split_view (#1731)
Browse files Browse the repository at this point in the history
  • Loading branch information
CaseyCarter authored Mar 18, 2021
1 parent 378dcad commit 038e07b
Show file tree
Hide file tree
Showing 8 changed files with 923 additions and 142 deletions.
147 changes: 9 additions & 138 deletions stl/inc/algorithm
Original file line number Diff line number Diff line change
Expand Up @@ -114,23 +114,6 @@ namespace ranges {
}
};

// STRUCT TEMPLATE in_in_result
template <class _In1, class _In2>
struct in_in_result {
/* [[no_unique_address]] */ _In1 in1;
/* [[no_unique_address]] */ _In2 in2;

template <_Convertible_from<const _In1&> _IIn1, _Convertible_from<const _In2&> _IIn2>
constexpr operator in_in_result<_IIn1, _IIn2>() const& {
return {in1, in2};
}

template <_Convertible_from<_In1> _IIn1, _Convertible_from<_In2> _IIn2>
constexpr operator in_in_result<_IIn1, _IIn2>() && {
return {_STD move(in1), _STD move(in2)};
}
};

// STRUCT TEMPLATE in_in_out_result
template <class _In1, class _In2, class _Out>
struct in_in_out_result {
Expand Down Expand Up @@ -416,21 +399,6 @@ namespace ranges {
inline constexpr _For_each_n_fn for_each_n{_Not_quite_object::_Construct_tag{}};

// VARIABLE ranges::find
// clang-format off
// concept-constrained for strict enforcement as it is used by several algorithms
template <input_iterator _It, sentinel_for<_It> _Se, class _Ty, class _Pj>
requires indirect_binary_predicate<ranges::equal_to, projected<_It, _Pj>, const _Ty*>
_NODISCARD constexpr _It _Find_unchecked(_It _First, const _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 Down Expand Up @@ -792,101 +760,6 @@ _NODISCARD pair<_FwdIt1, _FwdIt2> mismatch(

#ifdef __cpp_lib_concepts
namespace ranges {
// ALIAS TEMPLATE mismatch_result
template <class _In1, class _In2>
using mismatch_result = in_in_result<_In1, _In2>;

// VARIABLE ranges::mismatch
class _Mismatch_fn : private _Not_quite_object {
private:
template <class _It1, class _It2, class _Pr, class _Pj1, class _Pj2>
_NODISCARD static constexpr mismatch_result<_It1, _It2> _Mismatch_n(
_It1 _First1, _It2 _First2, iter_difference_t<_It1> _Count, _Pr _Pred, _Pj1 _Proj1, _Pj2 _Proj2) {
auto _UFirst1 = _Get_unwrapped(_STD move(_First1));
auto _UFirst2 = _Get_unwrapped(_STD move(_First2));

for (; _Count != 0; ++_UFirst1, (void) ++_UFirst2, --_Count) {
if (!_STD invoke(_Pred, _STD invoke(_Proj1, *_UFirst1), _STD invoke(_Proj2, *_UFirst2))) {
break;
}
}

_Seek_wrapped(_First1, _STD move(_UFirst1));
_Seek_wrapped(_First2, _STD move(_UFirst2));
return {_STD move(_First1), _STD move(_First2)};
}

template <class _It1, class _Se1, class _It2, class _Se2, class _Pr, class _Pj1, class _Pj2>
_NODISCARD static constexpr mismatch_result<_It1, _It2> _Mismatch_4(
_It1 _First1, _Se1 _Last1, _It2 _First2, _Se2 _Last2, _Pr _Pred, _Pj1 _Proj1, _Pj2 _Proj2) {
auto _UFirst1 = _Get_unwrapped(_STD move(_First1));
const auto _ULast1 = _Get_unwrapped(_STD move(_Last1));
auto _UFirst2 = _Get_unwrapped(_STD move(_First2));
const auto _ULast2 = _Get_unwrapped(_STD move(_Last2));

for (; _UFirst1 != _ULast1 && _UFirst2 != _ULast2; ++_UFirst1, (void) ++_UFirst2) {
if (!_STD invoke(_Pred, _STD invoke(_Proj1, *_UFirst1), _STD invoke(_Proj2, *_UFirst2))) {
break;
}
}

_Seek_wrapped(_First1, _STD move(_UFirst1));
_Seek_wrapped(_First2, _STD move(_UFirst2));
return {_STD move(_First1), _STD move(_First2)};
}

public:
using _Not_quite_object::_Not_quite_object;

// clang-format off
template <input_iterator _It1, sentinel_for<_It1> _Se1, input_iterator _It2, sentinel_for<_It2> _Se2,
class _Pr = ranges::equal_to, class _Pj1 = identity, class _Pj2 = identity>
requires indirectly_comparable<_It1, _It2, _Pr, _Pj1, _Pj2>
_NODISCARD constexpr mismatch_result<_It1, _It2> operator()(_It1 _First1, _Se1 _Last1,
_It2 _First2, _Se2 _Last2, _Pr _Pred = {}, _Pj1 _Proj1 = {}, _Pj2 _Proj2 = {}) const {
_Adl_verify_range(_First1, _Last1);
_Adl_verify_range(_First2, _Last2);

if constexpr (sized_sentinel_for<_Se1, _It1> && sized_sentinel_for<_Se2, _It2>) {
iter_difference_t<_It1> _Count1 = _Last1 - _First1;
const iter_difference_t<_It2> _Count2 = _Last2 - _First2;
if (_Count1 > _Count2) {
_Count1 = static_cast<decltype(_Count1)>(_Count2);
}

return _Mismatch_n(_STD move(_First1), _STD move(_First2), _Count1,
_Pass_fn(_Pred), _Pass_fn(_Proj1), _Pass_fn(_Proj2));
} else {
return _Mismatch_4(_STD move(_First1), _STD move(_Last1), _STD move(_First2), _STD move(_Last2),
_Pass_fn(_Pred), _Pass_fn(_Proj1), _Pass_fn(_Proj2));
}
}

template <input_range _Rng1, input_range _Rng2, class _Pr = ranges::equal_to, class _Pj1 = identity,
class _Pj2 = identity>
requires indirectly_comparable<iterator_t<_Rng1>, iterator_t<_Rng2>, _Pr, _Pj1, _Pj2>
_NODISCARD constexpr mismatch_result<borrowed_iterator_t<_Rng1>, borrowed_iterator_t<_Rng2>> operator()(
_Rng1&& _Range1, _Rng2&& _Range2, _Pr _Pred = {}, _Pj1 _Proj1 = {}, _Pj2 _Proj2 = {}) const {
if constexpr (sized_range<_Rng1> && sized_range<_Rng2>) {
range_difference_t<_Rng1> _Count1 = _RANGES distance(_Range1);
const range_difference_t<_Rng2> _Count2 = _RANGES distance(_Range2);
if (_Count1 > _Count2) {
_Count1 = static_cast<range_difference_t<_Rng1>>(_Count2);
}

return _Mismatch_n(_RANGES begin(_Range1), _RANGES begin(_Range2), _Count1,
_Pass_fn(_Pred), _Pass_fn(_Proj1), _Pass_fn(_Proj2));
} else {
return _Mismatch_4(_RANGES begin(_Range1), _RANGES end(_Range1),
_RANGES begin(_Range2), _RANGES end(_Range2),
_Pass_fn(_Pred), _Pass_fn(_Proj1), _Pass_fn(_Proj2));
}
}
// clang-format on
};

inline constexpr _Mismatch_fn mismatch{_Not_quite_object::_Construct_tag{}};

// VARIABLE ranges::equal
class _Equal_fn : private _Not_quite_object {
private:
Expand Down Expand Up @@ -4898,20 +4771,18 @@ _SampleIt sample(_PopIt _First, _PopIt _Last, _SampleIt _Dest, _Diff _Count,
}

#ifdef __cpp_lib_concepts
// STRUCT TEMPLATE _Require_constant
template <auto>
struct _Require_constant; // not defined; _Require_constant<E> is a valid type if E is a constant expression

// CONCEPT uniform_random_bit_generator
// clang-format off
template <class _Ty>
concept uniform_random_bit_generator = invocable<_Ty&> && unsigned_integral<invoke_result_t<_Ty&>> && requires {
{ (_Ty::min)() } -> same_as<invoke_result_t<_Ty&>>;
{ (_Ty::max)() } -> same_as<invoke_result_t<_Ty&>>;
typename _Require_constant<(_Ty::min)()>;
typename _Require_constant<(_Ty::max)()>;
requires (_Ty::min)() < (_Ty::max)();
};
concept uniform_random_bit_generator = invocable<_Ty&>
&& unsigned_integral<invoke_result_t<_Ty&>>
&& requires {
{ (_Ty::min)() } -> same_as<invoke_result_t<_Ty&>>;
{ (_Ty::max)() } -> same_as<invoke_result_t<_Ty&>>;
typename _Require_constant<(_Ty::min)()>;
typename _Require_constant<(_Ty::max)()>;
requires (_Ty::min)() < (_Ty::max)();
};
// clang-format on

namespace ranges {
Expand Down
Loading

0 comments on commit 038e07b

Please sign in to comment.