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 // UNSUPPORTED: libcpp-has-no-incomplete-ranges 11 12 // <algorithm> 13 14 // template<bidirectional_iterator I, sentinel_for<I> S> 15 // requires permutable<I> 16 // constexpr I ranges::reverse(I first, S last); 17 // template<bidirectional_range R> 18 // requires permutable<iterator_t<R>> 19 // constexpr borrowed_iterator_t<R> ranges::reverse(R&& r); 20 21 #include <algorithm> 22 #include <array> 23 #include <concepts> 24 #include <ranges> 25 26 #include "almost_satisfies_types.h" 27 #include "test_iterators.h" 28 29 template <class Iter, class Sent = sentinel_wrapper<Iter>> 30 concept HasReverseIt = requires (Iter first, Sent last) { std::ranges::reverse(first, last); }; 31 32 static_assert(HasReverseIt<int*>); 33 static_assert(!HasReverseIt<BidirectionalIteratorNotDerivedFrom>); 34 static_assert(!HasReverseIt<BidirectionalIteratorNotDecrementable>); 35 static_assert(!HasReverseIt<PermutableNotForwardIterator>); 36 static_assert(!HasReverseIt<PermutableNotSwappable>); 37 38 39 template <class Range> 40 concept HasReverseR = requires (Range range) { std::ranges::reverse(range); }; 41 42 static_assert(HasReverseR<UncheckedRange<int*>>); 43 static_assert(!HasReverseR<BidirectionalRangeNotDerivedFrom>); 44 static_assert(!HasReverseR<BidirectionalRangeNotDecrementable>); 45 static_assert(!HasReverseR<PermutableRangeNotForwardIterator>); 46 static_assert(!HasReverseR<PermutableRangeNotSwappable>); 47 48 template <class Iter, class Sent, size_t N> 49 constexpr void test(std::array<int, N> value, std::array<int, N> expected) { 50 { 51 auto val = value; 52 std::same_as<Iter> decltype(auto) ret = std::ranges::reverse(Iter(val.data()), Sent(Iter(val.data() + val.size()))); 53 assert(val == expected); 54 assert(base(ret) == val.data() + val.size()); 55 } 56 { 57 auto val = value; 58 auto range = std::ranges::subrange(Iter(val.data()), Sent(Iter(val.data() + val.size()))); 59 std::same_as<Iter> decltype(auto) ret = std::ranges::reverse(range); 60 assert(val == expected); 61 assert(base(ret) == val.data() + val.size()); 62 } 63 } 64 65 template <class Iter, class Sent = Iter> 66 constexpr void test_iterators() { 67 // simple test 68 test<Iter, Sent, 4>({1, 2, 3, 4}, {4, 3, 2, 1}); 69 // check that an odd number of elements works 70 test<Iter, Sent, 7>({1, 2, 3, 4, 5, 6, 7}, {7, 6, 5, 4, 3, 2, 1}); 71 // check that an empty range works 72 test<Iter, Sent, 0>({}, {}); 73 // check that a single element works 74 test<Iter, Sent, 1>({5}, {5}); 75 } 76 77 struct SwapCounter { 78 int* counter; 79 constexpr SwapCounter(int* counter_) : counter(counter_) {} 80 friend constexpr void swap(SwapCounter& lhs, SwapCounter&) { ++*lhs.counter; } 81 }; 82 83 constexpr bool test() { 84 test_iterators<bidirectional_iterator<int*>>(); 85 test_iterators<bidirectional_iterator<int*>, sentinel_wrapper<bidirectional_iterator<int*>>>(); 86 test_iterators<random_access_iterator<int*>>(); 87 test_iterators<random_access_iterator<int*>, sentinel_wrapper<random_access_iterator<int*>>>(); 88 test_iterators<contiguous_iterator<int*>>(); 89 test_iterators<contiguous_iterator<int*>, sentinel_wrapper<contiguous_iterator<int*>>>(); 90 test_iterators<int*>(); 91 92 // check that std::ranges::dangling is returned 93 { 94 [[maybe_unused]] std::same_as<std::ranges::dangling> auto ret = std::ranges::reverse(std::array {1, 2, 3, 4}); 95 } 96 97 { 98 { 99 int counter = 0; 100 SwapCounter a[] = {&counter, &counter, &counter, &counter}; 101 std::ranges::reverse(a); 102 assert(counter == 2); 103 } 104 { 105 int counter = 0; 106 SwapCounter a[] = {&counter, &counter, &counter, &counter}; 107 std::ranges::reverse(a, a + 4); 108 assert(counter == 2); 109 } 110 } 111 112 return true; 113 } 114 115 int main(int, char**) { 116 test(); 117 static_assert(test()); 118 119 return 0; 120 } 121