1 //===----------------------------------------------------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 // UNSUPPORTED: c++03, c++11, c++14, c++17 10 11 // <algorithm> 12 13 // template<permutable I, sentinel_for<I> S> 14 // constexpr subrange<I> rotate(I first, I middle, S last); // since C++20 15 // 16 // template<forward_range R> 17 // requires permutable<iterator_t<R>> 18 // constexpr borrowed_subrange_t<R> rotate(R&& r, iterator_t<R> middle); // Since C++20 19 20 #include <algorithm> 21 #include <array> 22 #include <cassert> 23 #include <ranges> 24 25 #include "almost_satisfies_types.h" 26 #include "test_iterators.h" 27 28 // Test constraints of the (iterator, sentinel) overload. 29 // ====================================================== 30 31 template <class Iter = int*, class Sent = int*> 32 concept HasRotateIter = 33 requires(Iter&& iter, Sent&& sent) { 34 std::ranges::rotate(std::forward<Iter>(iter), std::forward<Iter>(iter), std::forward<Sent>(sent)); 35 }; 36 37 static_assert(HasRotateIter<int*, int*>); 38 39 // !permutable<I> 40 static_assert(!HasRotateIter<PermutableNotForwardIterator>); 41 static_assert(!HasRotateIter<PermutableNotSwappable>); 42 43 // !sentinel_for<S, I> 44 static_assert(!HasRotateIter<int*, SentinelForNotSemiregular>); 45 static_assert(!HasRotateIter<int*, SentinelForNotWeaklyEqualityComparableWith>); 46 47 // Test constraints of the (range) overload. 48 // ========================================= 49 50 template <class Range> 51 concept HasRotateRange = 52 requires(Range&& range, std::ranges::iterator_t<Range> iter) { 53 std::ranges::rotate(std::forward<Range>(range), iter); 54 }; 55 56 template <class T> 57 using R = UncheckedRange<T>; 58 59 static_assert(HasRotateRange<R<int*>>); 60 61 // !forward_range<R> 62 static_assert(!HasRotateRange<ForwardRangeNotDerivedFrom>); 63 static_assert(!HasRotateRange<ForwardRangeNotIncrementable>); 64 static_assert(!HasRotateRange<ForwardRangeNotSentinelSemiregular>); 65 static_assert(!HasRotateRange<ForwardRangeNotSentinelEqualityComparableWith>); 66 67 // !permutable<iterator_t<R>> 68 static_assert(!HasRotateRange<PermutableRangeNotForwardIterator>); 69 static_assert(!HasRotateRange<PermutableRangeNotSwappable>); 70 71 template <class Iter, class Sent, size_t N> 72 constexpr void test_one(const std::array<int, N> input, size_t mid_index, std::array<int, N> expected) { 73 assert(mid_index <= N); 74 75 { // (iterator, sentinel) overload. 76 auto in = input; 77 auto begin = Iter(in.data()); 78 auto mid = Iter(in.data() + mid_index); 79 auto end = Sent(Iter(in.data() + in.size())); 80 81 std::same_as<std::ranges::subrange<Iter>> decltype(auto) result = std::ranges::rotate(begin, mid, end); 82 assert(base(result.begin()) == in.data() + in.size() - mid_index); 83 assert(base(result.end()) == in.data() + in.size()); 84 assert(in == expected); 85 } 86 87 { // (range) overload. 88 auto in = input; 89 auto begin = Iter(in.data()); 90 auto mid = Iter(in.data() + mid_index); 91 auto end = Sent(Iter(in.data() + in.size())); 92 auto range = std::ranges::subrange(std::move(begin), std::move(end)); 93 94 std::same_as<std::ranges::subrange<Iter>> decltype(auto) result = std::ranges::rotate(range, mid); 95 assert(base(result.begin()) == in.data() + in.size() - mid_index); 96 assert(base(result.end()) == in.data() + in.size()); 97 assert(in == expected); 98 } 99 } 100 101 template <class Iter, class Sent> 102 constexpr void test_iter_sent() { 103 // Empty sequence. 104 test_one<Iter, Sent, 0>({}, 0, {}); 105 106 // 1-element sequence. 107 test_one<Iter, Sent, 1>({1}, 0, {1}); 108 109 // 2-element sequence. 110 test_one<Iter, Sent, 2>({1, 2}, 1, {2, 1}); 111 112 // 3-element sequence. 113 test_one<Iter, Sent, 3>({1, 2, 3}, 1, {2, 3, 1}); 114 test_one<Iter, Sent, 3>({1, 2, 3}, 2, {3, 1, 2}); 115 116 // Longer sequence. 117 test_one<Iter, Sent, 7>({1, 2, 3, 4, 5, 6, 7}, 2, {3, 4, 5, 6, 7, 1, 2}); 118 119 // Rotate around the middle. 120 test_one<Iter, Sent, 7>({1, 2, 3, 4, 5, 6, 7}, 3, {4, 5, 6, 7, 1, 2, 3}); 121 122 // Rotate around the 1st element (no-op). 123 test_one<Iter, Sent, 7>({1, 2, 3, 4, 5, 6, 7}, 0, {1, 2, 3, 4, 5, 6, 7}); 124 125 // Rotate around the 2nd element. 126 test_one<Iter, Sent, 7>({1, 2, 3, 4, 5, 6, 7}, 1, {2, 3, 4, 5, 6, 7, 1}); 127 128 // Rotate around the last element. 129 test_one<Iter, Sent, 7>({1, 2, 3, 4, 5, 6, 7}, 6, {7, 1, 2, 3, 4, 5, 6}); 130 131 // Pass `end()` as `mid` (no-op). 132 test_one<Iter, Sent, 7>({1, 2, 3, 4, 5, 6, 7}, 7, {1, 2, 3, 4, 5, 6, 7}); 133 } 134 135 template <class Iter> 136 constexpr void test_iter() { 137 test_iter_sent<Iter, Iter>(); 138 test_iter_sent<Iter, sentinel_wrapper<Iter>>(); 139 } 140 141 constexpr void test_iterators() { 142 test_iter<forward_iterator<int*>>(); 143 test_iter<bidirectional_iterator<int*>>(); 144 test_iter<random_access_iterator<int*>>(); 145 test_iter<contiguous_iterator<int*>>(); 146 test_iter<int*>(); 147 } 148 149 constexpr bool test() { 150 test_iterators(); 151 152 { // Complexity: at most `last - first` swaps. 153 const std::array input = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; 154 auto expected = static_cast<int>(input.size()); 155 156 { 157 auto in = input; 158 int swaps = 0; 159 auto begin = adl::Iterator::TrackSwaps(in.data(), swaps); 160 auto end = adl::Iterator::TrackSwaps(in.data() + in.size(), swaps); 161 162 for (size_t mid = 0; mid != input.size(); ++mid) { 163 std::ranges::rotate(begin, begin + mid, end); 164 assert(swaps <= expected); 165 } 166 } 167 168 { 169 auto in = input; 170 int swaps = 0; 171 auto begin = adl::Iterator::TrackSwaps(in.data(), swaps); 172 auto end = adl::Iterator::TrackSwaps(in.data() + in.size(), swaps); 173 auto range = std::ranges::subrange(begin, end); 174 175 for (size_t mid = 0; mid != input.size(); ++mid) { 176 std::ranges::rotate(range, begin + mid); 177 assert(swaps <= expected); 178 } 179 } 180 } 181 182 return true; 183 } 184 185 int main(int, char**) { 186 test(); 187 static_assert(test()); 188 189 return 0; 190 } 191