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

Jonathan Wakely jwakely@redhat.com
Mon Feb 24 13:47:00 GMT 2020


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.

>@@ -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.


>+      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 Libstdc++ mailing list