Iros
 
Loading...
Searching...
No Matches
shift_right.h
Go to the documentation of this file.
1#pragma once
2
9#include "di/util/move.h"
10
11namespace di::container {
12namespace detail {
14 template<concepts::Permutable It, concepts::SentinelFor<It> Sent>
15 constexpr auto operator()(It first, Sent last, meta::IteratorSSizeType<It> n) const -> View<It> {
16 DI_ASSERT(n >= 0);
17
18 if (n == 0) {
19 return { first, container::next(first, last) };
20 }
21
23 auto last_it = container::next(first, last);
24 auto new_start = last_it;
25 container::advance(new_start, -n, first);
26
27 if (new_start == first) {
28 return { last_it, last_it };
29 }
30
31 // NOLINTNEXTLINE(readability-suspicious-call-argument)
32 auto real_start = container::move_backward(first, new_start, last_it).out;
33 return { real_start, last_it };
34 } else {
35 auto new_start = first;
36 container::advance(new_start, n, last);
37 if (new_start == last) {
38 return { new_start, new_start };
39 }
40
41 // Use fast and slow pointers, with the fast pointer
42 // n elements ahead of the slow pointer. This approach
43 // is outlined in the C++ paper for shift_left and shift_right.
44 // See https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0769r0.pdf.
45 auto fast = new_start;
46 auto slow = first;
47
48 // Fast path: the shift window is such that the size of the container is
49 // less than twice the shift amount. This lets us do the shift directly,
50 // without moving things around as we go.
51 for (; slow != new_start; ++fast, ++slow) {
52 if (fast == last) {
53 auto result = container::move(first, slow, new_start);
54 return { new_start, result.out };
55 }
56 }
57
58 // Cyclic path, use the first n elements of the input as storage
59 // for the elements which must be shifted into place. This approach essentially
60 // works on blocks of size n. At each block, we swap the elements at the start
61 // of the input with the elements of the current block. This makes the current
62 // block point to the correct values, which retaining the pending elements which
63 // otherwise would be overridden. Once we hit the end of the container, perform
64 // a final move operation to finish the shift.
65 for (;;) {
66 for (auto pending = first; pending != new_start; ++fast, ++slow, ++pending) {
67 if (fast == last) {
68 // Move the pending elements into place.
69 slow = container::move(pending, new_start, slow).out;
70
71 // Move the final elements into place.
72 auto last_it = container::move(first, pending, slow).out;
73 return { new_start, last_it };
74 }
75 // Swap the contents of slow and pending. The pending
76 // element of the previous iteration is now in the correct
77 // place, while pending now holds an element which will be
78 // shifted in later.
79 container::iterator_swap(pending, slow);
80 }
81 }
82 }
83 }
84
85 template<concepts::ForwardContainer Con>
87 constexpr auto operator()(Con&& container, meta::ContainerSSizeType<Con> n) const -> meta::BorrowedView<Con> {
89 }
90 };
91}
92
93constexpr inline auto shift_right = detail::ShiftRightFunction {};
94}
95
96namespace di {
98}
#define DI_ASSERT(...)
Definition assert_bool.h:7
Definition view.h:35
Definition bidirectional_iterator.h:8
Definition permutable.h:9
Definition sequence.h:13
Definition sequence.h:12
constexpr auto shift_right
Definition shift_right.h:93
constexpr auto next
Definition next.h:35
constexpr auto move
Definition move.h:38
constexpr auto iterator_swap
Definition iterator_swap.h:49
constexpr auto move_backward
Definition move_backward.h:34
constexpr auto end
Definition end.h:47
constexpr auto advance
Definition advance.h:62
constexpr auto begin
Definition begin.h:44
IteratorSSizeType< ContainerIterator< T > > ContainerSSizeType
Definition container_ssize_type.h:8
decltype(container::iterator_ssize_type(types::in_place_type< meta::RemoveCVRef< T > >)) IteratorSSizeType
Definition iterator_ssize_type.h:8
Conditional< concepts::BorrowedContainer< Con >, container::View< ContainerIterator< Con > >, container::Dangling > BorrowedView
Definition borrowed_view.h:12
Definition zstring_parser.h:9
constexpr auto operator()(It first, Sent last, meta::IteratorSSizeType< It > n) const -> View< It >
Definition shift_right.h:15