[PATCH] libstdc++: P0769R2 Add shift to <algorithm>

Patrick Palka ppalka@redhat.com
Mon Feb 24 14:12:00 GMT 2020


On Mon, 24 Feb 2020, Jonathan Wakely wrote:

> On 21/02/20 16:12 -0500, Patrick Palka wrote:
> > On Fri, 21 Feb 2020, Patrick Palka wrote:
> > 
> > > This patch adds std::shift_left and std::shift_right.  Alhough these are
> > > STL-style algos, they are nonetheless placed in <bits/ranges_algo.h>
> > > because
> > > they make use of some functions in the ranges namespace that are more
> > > easily
> > > reachable from <bits/ranges_algo.h> than from <bits/stl_algo.h>, namely
> > > ranges::next and ranges::swap_ranges.
> > > 
> > > This implementation of std::shift_right for non-bidirectional iterators
> > > deviates
> > > from the reference implementation a bit.  The main difference is that this
> > > implementation is significantly simpler, and yet saves around n/2
> > > additional
> > > iterator increments and n/2 iter_moves at the cost of around n/2
> > > additional
> > > iter_swaps (where n is the shift amount).
> > 
> > On second thought, this simplification of shift_right is a not a good
> > idea because the objects that were shifted and that are no longer a part
> > of the new range do not end up in a moved-from state at the end of the
> > algorithm.  Here is a version of the patch that instead adds something
> > akin to the reference implementation and improves the tests to verify
> > this moved-from property of both algorithms.
> > 
> > -- >8 --
> > 
> > Subject: [PATCH] libstdc++: P0769R2 Add shift to <algorithm>
> > 
> > This patch adds std::shift_left and std::shift_right as per P0769R2.
> > Alhough
> > these are STL-style algos, this patch places them in <bits/ranges_algo.h>
> > because they make use of some functions in the ranges namespace that are
> > more
> > easily reachable from <bits/ranges_algo.h> than from <bits/stl_algo.h>,
> > namely
> > ranges::next.  In order to place these algos in <bits/stl_algo.h>, we would
> > need
> > to include <bits/range_access.h> from <bits/stl_algo.h> which would
> > undesirably
> > increase the size of <bits/stl_algo.h>.
> > 
> > libstdc++-v3/ChangeLog:
> > 
> > 	P0769R2 Add shift to <algorithm>
> > 	* include/bits/ranges_algo.h (shift_left, shift_right): New.
> > 	* testsuite/25_algorithms/shift_left/1.cc: New test.
> > 	* testsuite/25_algorithms/shift_right/1.cc: New test.
> > ---
> > libstdc++-v3/include/bits/ranges_algo.h       |  92 ++++++++++++++++
> > .../testsuite/25_algorithms/shift_left/1.cc   | 104 ++++++++++++++++++
> > .../testsuite/25_algorithms/shift_right/1.cc  | 103 +++++++++++++++++
> > 3 files changed, 299 insertions(+)
> > create mode 100644 libstdc++-v3/testsuite/25_algorithms/shift_left/1.cc
> > create mode 100644 libstdc++-v3/testsuite/25_algorithms/shift_right/1.cc
> > 
> > diff --git a/libstdc++-v3/include/bits/ranges_algo.h
> > b/libstdc++-v3/include/bits/ranges_algo.h
> > index 7de1072abf0..7d7dbf04103 100644
> > --- a/libstdc++-v3/include/bits/ranges_algo.h
> > +++ b/libstdc++-v3/include/bits/ranges_algo.h
> 
> These new algos should go in <bits/stl_algo.h> because they're not in
> namespace ranges.

Since their implementation uses ranges::next(__it, __n, __last), putting
them in <bits/stl_algo.h> means we would need to include
<bits/range_access.h> from <bits/stl_algo.h>, or reimplement the
ranges::next() routine in <bits/stl_algo.h> (and its random access
iterator optimization) it seems.

> 
> > @@ -3683,6 +3683,98 @@ namespace ranges
> >   inline constexpr __prev_permutation_fn prev_permutation{};
> > 
> > } // namespace ranges
> > +
> > +  template<class ForwardIterator>
> > +    constexpr ForwardIterator
> > +    shift_left(ForwardIterator __first, ForwardIterator __last,
> > +	       typename iterator_traits<ForwardIterator>::difference_type __n)
> > +    {
> > +      __glibcxx_assert(__n >= 0);
> 
> If I'm reading the current draft correctly, n < 0 is allowed (and does
> nothing) so we shouldn't assert here.

From what I can tell, this is changed by P1243R4 (Rangify new
algorithms) which adds the precondition n >= 0 to these routines.

> 
> 
> > +      if (__n == 0)
> > +	return __last;
> > +
> > +      auto __mid = ranges::next(__first, __n, __last);
> > +      if (__mid == __last)
> > +	return __first;
> > +      return std::move(std::move(__mid), std::move(__last),
> > std::move(__first));
> > +    }
> > +
> > +  template<class ForwardIterator>
> > +    constexpr ForwardIterator
> > +    shift_right(ForwardIterator __first, ForwardIterator __last,
> > +		typename iterator_traits<ForwardIterator>::difference_type
> > __n)
> > +    {
> > +      __glibcxx_assert(__n >= 0);
> 
> Same here.



More information about the Gcc-patches mailing list