VCCC  2024.05
VisualCamp Common C++ library
shift.hpp
Go to the documentation of this file.
1 //
2 // Created by YongGyu Lee on 1/25/24.
3 //
4 
5 #ifndef VCCC_ALGORITHM_SHIFT_HPP
6 #define VCCC_ALGORITHM_SHIFT_HPP
7 
8 #include <algorithm>
9 #include <type_traits>
10 #include <utility>
11 
18 
19 namespace vccc {
20 namespace detail {
21 
22 template<typename It>
23 constexpr void move_nocheck(It first, It last, It dest) {
24  while (first != last) {
25  *dest = std::move(*first);
26  ++first;
27  }
28 }
29 
30 } // namespace detail
31 
34 
35 template<typename ForwardIt>
36 constexpr ForwardIt shift_left(
37  ForwardIt first, ForwardIt last, typename cxx20_iterator_traits<ForwardIt>::difference_type n)
38 {
39  static_assert(LegacyForwardIterator<ForwardIt>::value, "Constraints not satisfied");
40  static_assert(disjunction<
42  ValueSwappable<ForwardIt, ForwardIt>>::value, "Constraints not satisfied");
43 
44  if (n == 0)
45  return last;
46 
47  ForwardIt shift_first = first;
48  const auto d = ranges::advance(shift_first, n, last);
49  if (d != 0)
50  return first;
51 
52  for (; shift_first != last; ++shift_first, (void) ++first) {
53  *first = std::move(*shift_first);
54  }
55  return first;
56 }
57 
58 namespace detail {
59 
60 template<typename BidiIt>
61 constexpr BidiIt shift_right_impl_bidi(
62  BidiIt first, BidiIt last,
63  typename cxx20_iterator_traits<BidiIt>::difference_type n,
64  std::true_type /* RandomAccessIt */)
65 {
66  if (n >= last - first)
67  return last;
68  auto shift_last = last - n;
69  while (first != shift_last) {
70  *--last = std::move(*--shift_last);
71  }
72  return first;
73 }
74 
75 template<typename BidiIt>
76 constexpr BidiIt shift_right_impl_bidi(
77  BidiIt first, BidiIt last,
78  typename cxx20_iterator_traits<BidiIt>::difference_type n,
79  std::false_type /* RandomAccessIt */)
80 {
81  auto shift_last = last;
82  for (; n > 0; --n) {
83  if (shift_last == first)
84  return last;
85  --shift_last;
86  }
87  while (first != shift_last) {
88  *--last = std::move(*--shift_last);
89  }
90  return first;
91 }
92 
93 template<typename BidiIt>
94 constexpr BidiIt shift_right_impl(
95  BidiIt first, BidiIt last,
96  typename cxx20_iterator_traits<BidiIt>::difference_type n,
97  std::true_type /* BidirectionalIt */)
98 {
99  return shift_right_impl_bidi(first, last, n, LegacyRandomAccessIterator<BidiIt>{});
100 }
101 
102 template<typename ForwardIt>
103 constexpr ForwardIt shift_right_impl(
104  ForwardIt first, ForwardIt last,
105  typename cxx20_iterator_traits<ForwardIt>::difference_type n,
106  std::false_type /* BidirectionalIt */)
107 {
108  auto result = first;
109  for (; n > 0; --n) {
110  if (result == last)
111  return last;
112  ++result;
113  }
114 
115  auto trail = first;
116  auto lead = result;
117 
118  for (; trail != result; ++trail, (void) ++lead) {
119  if (lead == last) {
120  vccc::detail::move_nocheck(first, trail, result);
121  return first;
122  }
123  }
124 
125  for (;;) {
126  for (auto mid = first; mid != result; ++mid, (void) ++trail, ++lead) {
127  if (lead == last) {
128  trail = vccc::detail::move_nocheck(mid, result, trail);
129  vccc::detail::move_nocheck(first, mid, trail);
130 
131  return first;
132  }
133  using namespace std;
134  swap(*mid, *trail);
135  }
136  }
137  // Unreachable
138 }
139 
140 } // namespace detail
141 
142 template<typename ForwardIt>
143 constexpr ForwardIt shift_right(
144  ForwardIt first, ForwardIt last, typename cxx20_iterator_traits<ForwardIt>::difference_type n)
145 {
146  static_assert(LegacyForwardIterator<ForwardIt>::value, "Constraints not satisfied");
147  static_assert(disjunction<
149  ValueSwappable<ForwardIt, ForwardIt>>::value, "Constraints not satisfied");
150 
151  return detail::shift_right_impl(first, last, n, LegacyBidirectionalIterator<ForwardIt>{});
152 }
153 
155 
156 } // namespace vccc
157 
158 #endif // VCCC_ALGORITHM_SHIFT_HPP
constexpr ForwardIt shift_left(ForwardIt first, ForwardIt last, typename cxx20_iterator_traits< ForwardIt >::difference_type n)
Definition: shift.hpp:36
constexpr ForwardIt shift_right(ForwardIt first, ForwardIt last, typename cxx20_iterator_traits< ForwardIt >::difference_type n)
Definition: shift.hpp:143
constexpr VCCC_INLINE_OR_STATIC detail::advance_niebloid advance
Definition: advance.hpp:158
constexpr std::enable_if_t< conjunction< is_swappable< T >, is_swappable< U > >::value > swap(compressed_pair< T, U > &lhs, compressed_pair< T, U > &rhs) noexcept(conjunction< is_nothrow_swappable< T >, is_nothrow_swappable< U >>::value)
Definition: compressed_pair.hpp:108
Definition: matrix.hpp:495
Definition: directory.h:12
constexpr VCCC_INLINE_OR_STATIC detail::element_niebloid< 0 > first
Definition: key_value.hpp:34
constexpr VCCC_INLINE_OR_STATIC detail::element_niebloid< 1 > value
Definition: key_value.hpp:35
Definition: legacy_bidirectional_iterator.hpp:70
Definition: legacy_forward_iterator.hpp:49
Definition: value_swappable.hpp:29
Definition: cxx20_iterator_traits.hpp:188
Definition: disjunction.hpp:22