11d1a191eSNikolas Klauser //===----------------------------------------------------------------------===//
21d1a191eSNikolas Klauser //
31d1a191eSNikolas Klauser // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
41d1a191eSNikolas Klauser // See https://llvm.org/LICENSE.txt for license information.
51d1a191eSNikolas Klauser // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
61d1a191eSNikolas Klauser //
71d1a191eSNikolas Klauser //===----------------------------------------------------------------------===//
81d1a191eSNikolas Klauser
91d1a191eSNikolas Klauser // UNSUPPORTED: c++03, c++11, c++14, c++17
101d1a191eSNikolas Klauser // UNSUPPORTED: libcpp-has-no-incomplete-ranges
111d1a191eSNikolas Klauser
121d1a191eSNikolas Klauser // <algorithm>
131d1a191eSNikolas Klauser
141d1a191eSNikolas Klauser // template<bidirectional_iterator I, sentinel_for<I> S>
151d1a191eSNikolas Klauser // requires permutable<I>
161d1a191eSNikolas Klauser // constexpr I ranges::reverse(I first, S last);
171d1a191eSNikolas Klauser // template<bidirectional_range R>
181d1a191eSNikolas Klauser // requires permutable<iterator_t<R>>
191d1a191eSNikolas Klauser // constexpr borrowed_iterator_t<R> ranges::reverse(R&& r);
201d1a191eSNikolas Klauser
211d1a191eSNikolas Klauser #include <algorithm>
221d1a191eSNikolas Klauser #include <array>
231d1a191eSNikolas Klauser #include <concepts>
241d1a191eSNikolas Klauser #include <ranges>
251d1a191eSNikolas Klauser
261d1a191eSNikolas Klauser #include "almost_satisfies_types.h"
27*a81cc1fcSHui Xie #include "MoveOnly.h"
281d1a191eSNikolas Klauser #include "test_iterators.h"
291d1a191eSNikolas Klauser
301d1a191eSNikolas Klauser template <class Iter, class Sent = sentinel_wrapper<Iter>>
311d1a191eSNikolas Klauser concept HasReverseIt = requires (Iter first, Sent last) { std::ranges::reverse(first, last); };
321d1a191eSNikolas Klauser
331d1a191eSNikolas Klauser static_assert(HasReverseIt<int*>);
341d1a191eSNikolas Klauser static_assert(!HasReverseIt<BidirectionalIteratorNotDerivedFrom>);
351d1a191eSNikolas Klauser static_assert(!HasReverseIt<BidirectionalIteratorNotDecrementable>);
361d1a191eSNikolas Klauser static_assert(!HasReverseIt<PermutableNotForwardIterator>);
371d1a191eSNikolas Klauser static_assert(!HasReverseIt<PermutableNotSwappable>);
381d1a191eSNikolas Klauser
391d1a191eSNikolas Klauser
401d1a191eSNikolas Klauser template <class Range>
411d1a191eSNikolas Klauser concept HasReverseR = requires (Range range) { std::ranges::reverse(range); };
421d1a191eSNikolas Klauser
431d1a191eSNikolas Klauser static_assert(HasReverseR<UncheckedRange<int*>>);
441d1a191eSNikolas Klauser static_assert(!HasReverseR<BidirectionalRangeNotDerivedFrom>);
451d1a191eSNikolas Klauser static_assert(!HasReverseR<BidirectionalRangeNotDecrementable>);
461d1a191eSNikolas Klauser static_assert(!HasReverseR<PermutableRangeNotForwardIterator>);
471d1a191eSNikolas Klauser static_assert(!HasReverseR<PermutableRangeNotSwappable>);
481d1a191eSNikolas Klauser
491d1a191eSNikolas Klauser template <class Iter, class Sent, size_t N>
test(std::array<int,N> value,std::array<int,N> expected)501d1a191eSNikolas Klauser constexpr void test(std::array<int, N> value, std::array<int, N> expected) {
511d1a191eSNikolas Klauser {
521d1a191eSNikolas Klauser auto val = value;
531d1a191eSNikolas Klauser std::same_as<Iter> decltype(auto) ret = std::ranges::reverse(Iter(val.data()), Sent(Iter(val.data() + val.size())));
541d1a191eSNikolas Klauser assert(val == expected);
551d1a191eSNikolas Klauser assert(base(ret) == val.data() + val.size());
561d1a191eSNikolas Klauser }
571d1a191eSNikolas Klauser {
581d1a191eSNikolas Klauser auto val = value;
591d1a191eSNikolas Klauser auto range = std::ranges::subrange(Iter(val.data()), Sent(Iter(val.data() + val.size())));
601d1a191eSNikolas Klauser std::same_as<Iter> decltype(auto) ret = std::ranges::reverse(range);
611d1a191eSNikolas Klauser assert(val == expected);
621d1a191eSNikolas Klauser assert(base(ret) == val.data() + val.size());
631d1a191eSNikolas Klauser }
641d1a191eSNikolas Klauser }
651d1a191eSNikolas Klauser
661d1a191eSNikolas Klauser template <class Iter, class Sent = Iter>
test_iterators()671d1a191eSNikolas Klauser constexpr void test_iterators() {
681d1a191eSNikolas Klauser // simple test
691d1a191eSNikolas Klauser test<Iter, Sent, 4>({1, 2, 3, 4}, {4, 3, 2, 1});
701d1a191eSNikolas Klauser // check that an odd number of elements works
711d1a191eSNikolas Klauser test<Iter, Sent, 7>({1, 2, 3, 4, 5, 6, 7}, {7, 6, 5, 4, 3, 2, 1});
721d1a191eSNikolas Klauser // check that an empty range works
731d1a191eSNikolas Klauser test<Iter, Sent, 0>({}, {});
741d1a191eSNikolas Klauser // check that a single element works
751d1a191eSNikolas Klauser test<Iter, Sent, 1>({5}, {5});
761d1a191eSNikolas Klauser }
771d1a191eSNikolas Klauser
781d1a191eSNikolas Klauser struct SwapCounter {
791d1a191eSNikolas Klauser int* counter;
SwapCounterSwapCounter801d1a191eSNikolas Klauser constexpr SwapCounter(int* counter_) : counter(counter_) {}
swap(SwapCounter & lhs,SwapCounter &)811d1a191eSNikolas Klauser friend constexpr void swap(SwapCounter& lhs, SwapCounter&) { ++*lhs.counter; }
821d1a191eSNikolas Klauser };
831d1a191eSNikolas Klauser
test()841d1a191eSNikolas Klauser constexpr bool test() {
851d1a191eSNikolas Klauser test_iterators<bidirectional_iterator<int*>>();
861d1a191eSNikolas Klauser test_iterators<bidirectional_iterator<int*>, sentinel_wrapper<bidirectional_iterator<int*>>>();
871d1a191eSNikolas Klauser test_iterators<random_access_iterator<int*>>();
881d1a191eSNikolas Klauser test_iterators<random_access_iterator<int*>, sentinel_wrapper<random_access_iterator<int*>>>();
891d1a191eSNikolas Klauser test_iterators<contiguous_iterator<int*>>();
901d1a191eSNikolas Klauser test_iterators<contiguous_iterator<int*>, sentinel_wrapper<contiguous_iterator<int*>>>();
911d1a191eSNikolas Klauser test_iterators<int*>();
921d1a191eSNikolas Klauser
93*a81cc1fcSHui Xie test_iterators<ProxyIterator<bidirectional_iterator<int*>>>();
94*a81cc1fcSHui Xie test_iterators<ProxyIterator<random_access_iterator<int*>>>();
95*a81cc1fcSHui Xie test_iterators<ProxyIterator<contiguous_iterator<int*>>>();
96*a81cc1fcSHui Xie
971d1a191eSNikolas Klauser // check that std::ranges::dangling is returned
981d1a191eSNikolas Klauser {
991d1a191eSNikolas Klauser [[maybe_unused]] std::same_as<std::ranges::dangling> auto ret = std::ranges::reverse(std::array {1, 2, 3, 4});
1001d1a191eSNikolas Klauser }
1011d1a191eSNikolas Klauser
1021d1a191eSNikolas Klauser {
1031d1a191eSNikolas Klauser {
1041d1a191eSNikolas Klauser int counter = 0;
1051d1a191eSNikolas Klauser SwapCounter a[] = {&counter, &counter, &counter, &counter};
1061d1a191eSNikolas Klauser std::ranges::reverse(a);
1071d1a191eSNikolas Klauser assert(counter == 2);
1081d1a191eSNikolas Klauser }
1091d1a191eSNikolas Klauser {
1101d1a191eSNikolas Klauser int counter = 0;
1111d1a191eSNikolas Klauser SwapCounter a[] = {&counter, &counter, &counter, &counter};
1121d1a191eSNikolas Klauser std::ranges::reverse(a, a + 4);
1131d1a191eSNikolas Klauser assert(counter == 2);
1141d1a191eSNikolas Klauser }
1151d1a191eSNikolas Klauser }
1161d1a191eSNikolas Klauser
117*a81cc1fcSHui Xie // Move only types work for ProxyIterator
118*a81cc1fcSHui Xie {
119*a81cc1fcSHui Xie {
120*a81cc1fcSHui Xie MoveOnly a[] = {1, 2, 3};
121*a81cc1fcSHui Xie ProxyRange proxyA{a};
122*a81cc1fcSHui Xie std::ranges::reverse(proxyA.begin(), proxyA.end());
123*a81cc1fcSHui Xie assert(a[0].get() == 3);
124*a81cc1fcSHui Xie assert(a[1].get() == 2);
125*a81cc1fcSHui Xie assert(a[2].get() == 1);
126*a81cc1fcSHui Xie }
127*a81cc1fcSHui Xie {
128*a81cc1fcSHui Xie MoveOnly a[] = {1, 2, 3};
129*a81cc1fcSHui Xie ProxyRange proxyA{a};
130*a81cc1fcSHui Xie std::ranges::reverse(proxyA);
131*a81cc1fcSHui Xie assert(a[0].get() == 3);
132*a81cc1fcSHui Xie assert(a[1].get() == 2);
133*a81cc1fcSHui Xie assert(a[2].get() == 1);
134*a81cc1fcSHui Xie }
135*a81cc1fcSHui Xie }
136*a81cc1fcSHui Xie
1371d1a191eSNikolas Klauser return true;
1381d1a191eSNikolas Klauser }
1391d1a191eSNikolas Klauser
main(int,char **)1401d1a191eSNikolas Klauser int main(int, char**) {
1411d1a191eSNikolas Klauser test();
1421d1a191eSNikolas Klauser static_assert(test());
1431d1a191eSNikolas Klauser
1441d1a191eSNikolas Klauser return 0;
1451d1a191eSNikolas Klauser }
146