xref: /llvm-project/libcxx/test/std/ranges/range.adaptors/range.reverse/adaptor.pass.cpp (revision ba2236d3000645d3127f972aa7ac1844c47e299c)
1616a3cc0SLouis Dionne //===----------------------------------------------------------------------===//
2616a3cc0SLouis Dionne //
3616a3cc0SLouis Dionne // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4616a3cc0SLouis Dionne // See https://llvm.org/LICENSE.txt for license information.
5616a3cc0SLouis Dionne // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6616a3cc0SLouis Dionne //
7616a3cc0SLouis Dionne //===----------------------------------------------------------------------===//
8616a3cc0SLouis Dionne 
9616a3cc0SLouis Dionne // UNSUPPORTED: c++03, c++11, c++14, c++17
10616a3cc0SLouis Dionne 
11616a3cc0SLouis Dionne // std::views::reverse
12616a3cc0SLouis Dionne 
13616a3cc0SLouis Dionne #include <ranges>
14616a3cc0SLouis Dionne 
15616a3cc0SLouis Dionne #include <cassert>
16616a3cc0SLouis Dionne #include <concepts>
17616a3cc0SLouis Dionne #include <iterator>
18616a3cc0SLouis Dionne #include <utility>
19616a3cc0SLouis Dionne 
20*ba2236d3SWill Hawkins #include "test_range.h"
21616a3cc0SLouis Dionne #include "types.h"
22616a3cc0SLouis Dionne 
test()23616a3cc0SLouis Dionne constexpr bool test() {
24616a3cc0SLouis Dionne   int buf[] = {1, 2, 3};
25616a3cc0SLouis Dionne 
26616a3cc0SLouis Dionne   // views::reverse(x) is equivalent to x.base() if x is a reverse_view
27616a3cc0SLouis Dionne   {
28616a3cc0SLouis Dionne     {
29616a3cc0SLouis Dionne       BidirRange view(buf, buf + 3);
30616a3cc0SLouis Dionne       std::ranges::reverse_view<BidirRange> reversed(view);
31616a3cc0SLouis Dionne       std::same_as<BidirRange> auto result = std::views::reverse(reversed);
32616a3cc0SLouis Dionne       assert(result.begin_ == buf);
33616a3cc0SLouis Dionne       assert(result.end_ == buf + 3);
34616a3cc0SLouis Dionne     }
35616a3cc0SLouis Dionne     {
36616a3cc0SLouis Dionne       // Common use case is worth testing
37616a3cc0SLouis Dionne       BidirRange view(buf, buf + 3);
38616a3cc0SLouis Dionne       std::same_as<BidirRange> auto result = std::views::reverse(std::views::reverse(view));
39616a3cc0SLouis Dionne       assert(result.begin_ == buf);
40616a3cc0SLouis Dionne       assert(result.end_ == buf + 3);
41616a3cc0SLouis Dionne     }
42616a3cc0SLouis Dionne   }
43616a3cc0SLouis Dionne 
44616a3cc0SLouis Dionne   // views::reverse(x) is equivalent to subrange{end, begin, size} if x is a
45616a3cc0SLouis Dionne   // sized subrange over reverse iterators
46616a3cc0SLouis Dionne   {
47616a3cc0SLouis Dionne     using It = bidirectional_iterator<int*>;
48616a3cc0SLouis Dionne     using Subrange = std::ranges::subrange<It, It, std::ranges::subrange_kind::sized>;
49616a3cc0SLouis Dionne 
50616a3cc0SLouis Dionne     using ReverseIt = std::reverse_iterator<It>;
51616a3cc0SLouis Dionne     using ReverseSubrange = std::ranges::subrange<ReverseIt, ReverseIt, std::ranges::subrange_kind::sized>;
52616a3cc0SLouis Dionne 
53616a3cc0SLouis Dionne     {
54616a3cc0SLouis Dionne       BidirRange view(buf, buf + 3);
55616a3cc0SLouis Dionne       ReverseSubrange subrange(ReverseIt(std::ranges::end(view)), ReverseIt(std::ranges::begin(view)), /* size */3);
56616a3cc0SLouis Dionne       std::same_as<Subrange> auto result = std::views::reverse(subrange);
575f26d863SMark de Wever       assert(base(result.begin()) == buf);
585f26d863SMark de Wever       assert(base(result.end()) == buf + 3);
59616a3cc0SLouis Dionne     }
60616a3cc0SLouis Dionne     {
61616a3cc0SLouis Dionne       // std::move into views::reverse
62616a3cc0SLouis Dionne       BidirRange view(buf, buf + 3);
63616a3cc0SLouis Dionne       ReverseSubrange subrange(ReverseIt(std::ranges::end(view)), ReverseIt(std::ranges::begin(view)), /* size */3);
64616a3cc0SLouis Dionne       std::same_as<Subrange> auto result = std::views::reverse(std::move(subrange));
655f26d863SMark de Wever       assert(base(result.begin()) == buf);
665f26d863SMark de Wever       assert(base(result.end()) == buf + 3);
67616a3cc0SLouis Dionne     }
68616a3cc0SLouis Dionne     {
69616a3cc0SLouis Dionne       // with a const subrange
70616a3cc0SLouis Dionne       BidirRange view(buf, buf + 3);
71616a3cc0SLouis Dionne       ReverseSubrange const subrange(ReverseIt(std::ranges::end(view)), ReverseIt(std::ranges::begin(view)), /* size */3);
72616a3cc0SLouis Dionne       std::same_as<Subrange> auto result = std::views::reverse(subrange);
735f26d863SMark de Wever       assert(base(result.begin()) == buf);
745f26d863SMark de Wever       assert(base(result.end()) == buf + 3);
75616a3cc0SLouis Dionne     }
76616a3cc0SLouis Dionne   }
77616a3cc0SLouis Dionne 
78616a3cc0SLouis Dionne   // views::reverse(x) is equivalent to subrange{end, begin} if x is an
79616a3cc0SLouis Dionne   // unsized subrange over reverse iterators
80616a3cc0SLouis Dionne   {
81616a3cc0SLouis Dionne     using It = bidirectional_iterator<int*>;
82616a3cc0SLouis Dionne     using Subrange = std::ranges::subrange<It, It, std::ranges::subrange_kind::unsized>;
83616a3cc0SLouis Dionne 
84616a3cc0SLouis Dionne     using ReverseIt = std::reverse_iterator<It>;
85616a3cc0SLouis Dionne     using ReverseSubrange = std::ranges::subrange<ReverseIt, ReverseIt, std::ranges::subrange_kind::unsized>;
86616a3cc0SLouis Dionne 
87616a3cc0SLouis Dionne     {
88616a3cc0SLouis Dionne       BidirRange view(buf, buf + 3);
89616a3cc0SLouis Dionne       ReverseSubrange subrange(ReverseIt(std::ranges::end(view)), ReverseIt(std::ranges::begin(view)));
90616a3cc0SLouis Dionne       std::same_as<Subrange> auto result = std::views::reverse(subrange);
915f26d863SMark de Wever       assert(base(result.begin()) == buf);
925f26d863SMark de Wever       assert(base(result.end()) == buf + 3);
93616a3cc0SLouis Dionne     }
94616a3cc0SLouis Dionne     {
95616a3cc0SLouis Dionne       // std::move into views::reverse
96616a3cc0SLouis Dionne       BidirRange view(buf, buf + 3);
97616a3cc0SLouis Dionne       ReverseSubrange subrange(ReverseIt(std::ranges::end(view)), ReverseIt(std::ranges::begin(view)));
98616a3cc0SLouis Dionne       std::same_as<Subrange> auto result = std::views::reverse(std::move(subrange));
995f26d863SMark de Wever       assert(base(result.begin()) == buf);
1005f26d863SMark de Wever       assert(base(result.end()) == buf + 3);
101616a3cc0SLouis Dionne     }
102616a3cc0SLouis Dionne     {
103616a3cc0SLouis Dionne       // with a const subrange
104616a3cc0SLouis Dionne       BidirRange view(buf, buf + 3);
105616a3cc0SLouis Dionne       ReverseSubrange const subrange(ReverseIt(std::ranges::end(view)), ReverseIt(std::ranges::begin(view)));
106616a3cc0SLouis Dionne       std::same_as<Subrange> auto result = std::views::reverse(subrange);
1075f26d863SMark de Wever       assert(base(result.begin()) == buf);
1085f26d863SMark de Wever       assert(base(result.end()) == buf + 3);
109616a3cc0SLouis Dionne     }
110616a3cc0SLouis Dionne   }
111616a3cc0SLouis Dionne 
112616a3cc0SLouis Dionne   // Otherwise, views::reverse(x) is equivalent to ranges::reverse_view{x}
113616a3cc0SLouis Dionne   {
114616a3cc0SLouis Dionne     BidirRange view(buf, buf + 3);
115616a3cc0SLouis Dionne     std::same_as<std::ranges::reverse_view<BidirRange>> auto result = std::views::reverse(view);
1165f26d863SMark de Wever     assert(base(result.begin().base()) == buf + 3);
1175f26d863SMark de Wever     assert(base(result.end().base()) == buf);
118616a3cc0SLouis Dionne   }
119616a3cc0SLouis Dionne 
120616a3cc0SLouis Dionne   // Test that std::views::reverse is a range adaptor
121616a3cc0SLouis Dionne   {
122616a3cc0SLouis Dionne     // Test `v | views::reverse`
123616a3cc0SLouis Dionne     {
124616a3cc0SLouis Dionne       BidirRange view(buf, buf + 3);
125616a3cc0SLouis Dionne       std::same_as<std::ranges::reverse_view<BidirRange>> auto result = view | std::views::reverse;
1265f26d863SMark de Wever       assert(base(result.begin().base()) == buf + 3);
1275f26d863SMark de Wever       assert(base(result.end().base()) == buf);
128616a3cc0SLouis Dionne     }
129616a3cc0SLouis Dionne 
130616a3cc0SLouis Dionne     // Test `adaptor | views::reverse`
131616a3cc0SLouis Dionne     {
132616a3cc0SLouis Dionne       BidirRange view(buf, buf + 3);
133616a3cc0SLouis Dionne       auto f = [](int i) { return i; };
134616a3cc0SLouis Dionne       auto const partial = std::views::transform(f) | std::views::reverse;
135616a3cc0SLouis Dionne       using Result = std::ranges::reverse_view<std::ranges::transform_view<BidirRange, decltype(f)>>;
136616a3cc0SLouis Dionne       std::same_as<Result> auto result = partial(view);
1375f26d863SMark de Wever       assert(base(result.begin().base().base()) == buf + 3);
1385f26d863SMark de Wever       assert(base(result.end().base().base()) == buf);
139616a3cc0SLouis Dionne     }
140616a3cc0SLouis Dionne 
141616a3cc0SLouis Dionne     // Test `views::reverse | adaptor`
142616a3cc0SLouis Dionne     {
143616a3cc0SLouis Dionne       BidirRange view(buf, buf + 3);
144616a3cc0SLouis Dionne       auto f = [](int i) { return i; };
145616a3cc0SLouis Dionne       auto const partial = std::views::reverse | std::views::transform(f);
146616a3cc0SLouis Dionne       using Result = std::ranges::transform_view<std::ranges::reverse_view<BidirRange>, decltype(f)>;
147616a3cc0SLouis Dionne       std::same_as<Result> auto result = partial(view);
1485f26d863SMark de Wever       assert(base(result.begin().base().base()) == buf + 3);
1495f26d863SMark de Wever       assert(base(result.end().base().base()) == buf);
150616a3cc0SLouis Dionne     }
151616a3cc0SLouis Dionne 
152616a3cc0SLouis Dionne     // Check SFINAE friendliness
153616a3cc0SLouis Dionne     {
154616a3cc0SLouis Dionne       struct NotABidirRange { };
155616a3cc0SLouis Dionne       static_assert(!std::is_invocable_v<decltype(std::views::reverse)>);
156616a3cc0SLouis Dionne       static_assert(!std::is_invocable_v<decltype(std::views::reverse), NotABidirRange>);
157616a3cc0SLouis Dionne       static_assert( CanBePiped<BidirRange,     decltype(std::views::reverse)>);
158616a3cc0SLouis Dionne       static_assert( CanBePiped<BidirRange&,    decltype(std::views::reverse)>);
159616a3cc0SLouis Dionne       static_assert(!CanBePiped<NotABidirRange, decltype(std::views::reverse)>);
160616a3cc0SLouis Dionne     }
161616a3cc0SLouis Dionne   }
162616a3cc0SLouis Dionne 
163616a3cc0SLouis Dionne   {
164616a3cc0SLouis Dionne     static_assert(std::same_as<decltype(std::views::reverse), decltype(std::ranges::views::reverse)>);
165616a3cc0SLouis Dionne   }
166616a3cc0SLouis Dionne 
167616a3cc0SLouis Dionne   return true;
168616a3cc0SLouis Dionne }
169616a3cc0SLouis Dionne 
main(int,char **)170616a3cc0SLouis Dionne int main(int, char**) {
171616a3cc0SLouis Dionne   test();
172616a3cc0SLouis Dionne   static_assert(test());
173616a3cc0SLouis Dionne 
174616a3cc0SLouis Dionne   return 0;
175616a3cc0SLouis Dionne }
176