On Sat, 15 Feb 2020, Jonathan Wakely wrote:
> On 14/02/20 10:35 -0500, Patrick Palka wrote:
> > These subroutines have only a single call site, so it might be best and
> > simplest
> > to eliminate them before we convert the algos into function objects.
> >
> > libstdc++-v3/ChangeLog:
> >
> > * include/bits/ranges_algo.h (ranges::__find_end): Fold into ...
> > (ranges::find_end): ... here.
> > (ranges::__lexicographical_compare): Fold into ...
> > (ranges::lexicographical_compare): ... here.
> > * include/bits/ranges_algobase.h (ranges::__equal): Fold into ...
> > (ranges::equal): ... here.
>
> OK for master, but please note the two comments below.
>
>
> > libstdc++-v3/include/bits/ranges_algo.h | 104 ++++++++------------
> > libstdc++-v3/include/bits/ranges_algobase.h | 33 +++----
> > 2 files changed, 55 insertions(+), 82 deletions(-)
> >
> > diff --git a/libstdc++-v3/include/bits/ranges_algo.h
> > b/libstdc++-v3/include/bits/ranges_algo.h
> > index 84a02cabb80..6b6f4defdf5 100644
> > --- a/libstdc++-v3/include/bits/ranges_algo.h
> > +++ b/libstdc++-v3/include/bits/ranges_algo.h
> > @@ -513,40 +513,7 @@ namespace ranges
> > std::move(__pred), std::move(__proj));
> > }
> >
> > - template<forward_iterator _Iter1, sentinel_for<_Iter1> _Sent1,
> > - forward_iterator _Iter2, sentinel_for<_Iter2> _Sent2,
> > - typename _Pred = ranges::equal_to,
> > - typename _Proj1 = identity, typename _Proj2 = identity>
> > - requires indirectly_comparable<_Iter1, _Iter2, _Pred, _Proj1, _Proj2>
> > - constexpr subrange<_Iter1>
> > - __find_end(_Iter1 __first1, _Sent1 __last1,
> > - _Iter2 __first2, _Sent2 __last2,
> > - _Pred __pred, _Proj1 __proj1, _Proj2 __proj2)
> > - {
> > - auto __i = ranges::next(__first1, __last1);
> > - if (__first2 == __last2)
> > - return {__i, __i};
> >
> > - auto __result_begin = __i;
> > - auto __result_end = __i;
> > - for (;;)
> > - {
> > - auto __new_range = ranges::search(__first1, __last1,
> > - __first2, __last2,
> > - __pred, __proj1, __proj2);
> > - auto __new_result_begin = ranges::begin(__new_range);
> > - auto __new_result_end = ranges::end(__new_range);
> > - if (__new_result_begin == __last1)
> > - return {__result_begin, __result_end};
> > - else
> > - {
> > - __result_begin = __new_result_begin;
> > - __result_end = __new_result_end;
> > - __first1 = __result_begin;
> > - ++__first1;
> > - }
> > - }
> > - }
> >
> > template<forward_iterator _Iter1, sentinel_for<_Iter1> _Sent1,
> > forward_iterator _Iter2, sentinel_for<_Iter2> _Sent2,
> > @@ -578,9 +545,31 @@ namespace ranges
> > return {__result_first, __result_last};
> > }
> > else
> > - return ranges::__find_end(__first1, __last1, __first2, __last2,
> > - std::move(__pred),
> > - std::move(__proj1), std::move(__proj2));
> > + {
> > + auto __i = ranges::next(__first1, __last1);
> > + if (__first2 == __last2)
> > + return {__i, __i};
> > +
> > + auto __result_begin = __i;
> > + auto __result_end = __i;
> > + for (;;)
> > + {
> > + auto __new_range = ranges::search(__first1, __last1,
> > + __first2, __last2,
> > + __pred, __proj1, __proj2);
> > + auto __new_result_begin = ranges::begin(__new_range);
> > + auto __new_result_end = ranges::end(__new_range);
> > + if (__new_result_begin == __last1)
> > + return {__result_begin, __result_end};
> > + else
> > + {
> > + __result_begin = __new_result_begin;
> > + __result_end = __new_result_end;
> > + __first1 = __result_begin;
> > + ++__first1;
> > + }
> > + }
> > + }
> > }
> >
> > template<forward_range _Range1, forward_range _Range2,
> > @@ -2908,14 +2897,26 @@ namespace ranges
> >
> > template<input_iterator _Iter1, sentinel_for<_Iter1> _Sent1,
> > input_iterator _Iter2, sentinel_for<_Iter2> _Sent2,
> > - typename _Proj1, typename _Proj2,
> > + typename _Proj1 = identity, typename _Proj2 = identity,
> > indirect_strict_weak_order<projected<_Iter1, _Proj1>,
> > - projected<_Iter2, _Proj2>> _Comp>
> > + projected<_Iter2, _Proj2>>
> > + _Comp = ranges::less>
> > constexpr bool
> > - __lexicographical_compare(_Iter1 __first1, _Sent1 __last1,
> > - _Iter2 __first2, _Sent2 __last2,
> > - _Comp __comp, _Proj1 __proj1, _Proj2 __proj2)
> > + lexicographical_compare(_Iter1 __first1, _Sent1 __last1,
> > + _Iter2 __first2, _Sent2 __last2,
> > + _Comp __comp = {},
> > + _Proj1 __proj1 = {}, _Proj2 __proj2 = {})
> > {
> > + if constexpr (__detail::__is_normal_iterator<_Iter1>
> > + || __detail::__is_normal_iterator<_Iter2>)
> > + return ranges::lexicographical_compare
> > + (std::__niter_base(std::move(__first1)),
> > + std::__niter_base(std::move(__last1)),
> > + std::__niter_base(std::move(__first2)),
> > + std::__niter_base(std::move(__last2)),
> > + std::move(__comp),
> > + std::move(__proj1), std::move(__proj2));
> > +
>
> I think we want "else {" here, so the lines following are not
> instantiated when we unpack normal iterators.
>
> That can be done in a separate patch later though.
>
> > constexpr bool __sized_iters
> > = (sized_sentinel_for<_Sent1, _Iter1>
> > && sized_sentinel_for<_Sent2, _Iter2>);
> > @@ -2976,27 +2977,6 @@ namespace ranges
> > return __first1 == __last1 && __first2 != __last2;
> > }
> >
> > - template<input_iterator _Iter1, sentinel_for<_Iter1> _Sent1,
> > - input_iterator _Iter2, sentinel_for<_Iter2> _Sent2,
> > - typename _Proj1 = identity, typename _Proj2 = identity,
> > - indirect_strict_weak_order<projected<_Iter1, _Proj1>,
> > - projected<_Iter2, _Proj2>>
> > - _Comp = ranges::less>
> > - constexpr bool
> > - lexicographical_compare(_Iter1 __first1, _Sent1 __last1,
> > - _Iter2 __first2, _Sent2 __last2,
> > - _Comp __comp = {},
> > - _Proj1 __proj1 = {}, _Proj2 __proj2 = {})
> > - {
> > - return (ranges::__lexicographical_compare
> > - (std::__niter_base(std::move(__first1)),
> > - std::__niter_base(std::move(__last1)),
> > - std::__niter_base(std::move(__first2)),
> > - std::__niter_base(std::move(__last2)),
> > - std::move(__comp),
> > - std::move(__proj1), std::move(__proj2)));
> > - }
> > -
> > template<input_range _Range1, input_range _Range2, typename _Proj1 =
> > identity,
> > typename _Proj2 = identity,
> > indirect_strict_weak_order<projected<iterator_t<_Range1>, _Proj1>,
> > diff --git a/libstdc++-v3/include/bits/ranges_algobase.h
> > b/libstdc++-v3/include/bits/ranges_algobase.h
> > index f63c032cf0b..813a5096ae0 100644
> > --- a/libstdc++-v3/include/bits/ranges_algobase.h
> > +++ b/libstdc++-v3/include/bits/ranges_algobase.h
> > @@ -73,14 +73,24 @@ namespace ranges
> >
> > template<input_iterator _Iter1, sentinel_for<_Iter1> _Sent1,
> > input_iterator _Iter2, sentinel_for<_Iter2> _Sent2,
> > - typename _Pred, typename _Proj1, typename _Proj2>
> > + typename _Pred = ranges::equal_to,
> > + typename _Proj1 = identity, typename _Proj2 = identity>
> > requires indirectly_comparable<_Iter1, _Iter2, _Pred, _Proj1, _Proj2>
> > constexpr bool
> > - __equal(_Iter1 __first1, _Sent1 __last1, _Iter2 __first2, _Sent2
> > __last2,
> > - _Pred __pred, _Proj1 __proj1, _Proj2 __proj2)
> > + equal(_Iter1 __first1, _Sent1 __last1, _Iter2 __first2, _Sent2 __last2,
> > + _Pred __pred = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {})
> > {
> > // TODO: implement more specializations to at least have parity with
> > // std::equal.
> > + if constexpr (__detail::__is_normal_iterator<_Iter1>
> > + || __detail::__is_normal_iterator<_Iter2>)
> > + return ranges::equal(std::__niter_base(std::move(__first1)),
> > + std::__niter_base(std::move(__last1)),
> > + std::__niter_base(std::move(__first2)),
> > + std::__niter_base(std::move(__last2)),
> > + std::move(__pred),
> > + std::move(__proj1), std::move(__proj2));
> > +
>
> Same thing here.
Thanks for the review. I committed the series, and will post a followup
patch that makes this adjustment.