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// std::views::reverse
12
13#include <ranges>
14
15#include <cassert>
16#include <concepts>
17#include <iterator>
18#include <utility>
19
20#include "test_range.h"
21#include "types.h"
22
23constexpr bool test() {
24 int buf[] = {1, 2, 3};
25
26 // views::reverse(x) is equivalent to x.base() if x is a reverse_view
27 {
28 {
29 BidirRange view(buf, buf + 3);
30 std::ranges::reverse_view<BidirRange> reversed(view);
31 std::same_as<BidirRange> auto result = std::views::reverse(reversed);
32 assert(result.begin_ == buf);
33 assert(result.end_ == buf + 3);
34 }
35 {
36 // Common use case is worth testing
37 BidirRange view(buf, buf + 3);
38 std::same_as<BidirRange> auto result = std::views::reverse(std::views::reverse(view));
39 assert(result.begin_ == buf);
40 assert(result.end_ == buf + 3);
41 }
42 }
43
44 // views::reverse(x) is equivalent to subrange{end, begin, size} if x is a
45 // sized subrange over reverse iterators
46 {
47 using It = bidirectional_iterator<int*>;
48 using Subrange = std::ranges::subrange<It, It, std::ranges::subrange_kind::sized>;
49
50 using ReverseIt = std::reverse_iterator<It>;
51 using ReverseSubrange = std::ranges::subrange<ReverseIt, ReverseIt, std::ranges::subrange_kind::sized>;
52
53 {
54 BidirRange view(buf, buf + 3);
55 ReverseSubrange subrange(ReverseIt(std::ranges::end(view)), ReverseIt(std::ranges::begin(view)), /* size */3);
56 std::same_as<Subrange> auto result = std::views::reverse(subrange);
57 assert(base(result.begin()) == buf);
58 assert(base(result.end()) == buf + 3);
59 }
60 {
61 // std::move into views::reverse
62 BidirRange view(buf, buf + 3);
63 ReverseSubrange subrange(ReverseIt(std::ranges::end(view)), ReverseIt(std::ranges::begin(view)), /* size */3);
64 std::same_as<Subrange> auto result = std::views::reverse(std::move(subrange));
65 assert(base(result.begin()) == buf);
66 assert(base(result.end()) == buf + 3);
67 }
68 {
69 // with a const subrange
70 BidirRange view(buf, buf + 3);
71 ReverseSubrange const subrange(ReverseIt(std::ranges::end(view)), ReverseIt(std::ranges::begin(view)), /* size */3);
72 std::same_as<Subrange> auto result = std::views::reverse(subrange);
73 assert(base(result.begin()) == buf);
74 assert(base(result.end()) == buf + 3);
75 }
76 }
77
78 // views::reverse(x) is equivalent to subrange{end, begin} if x is an
79 // unsized subrange over reverse iterators
80 {
81 using It = bidirectional_iterator<int*>;
82 using Subrange = std::ranges::subrange<It, It, std::ranges::subrange_kind::unsized>;
83
84 using ReverseIt = std::reverse_iterator<It>;
85 using ReverseSubrange = std::ranges::subrange<ReverseIt, ReverseIt, std::ranges::subrange_kind::unsized>;
86
87 {
88 BidirRange view(buf, buf + 3);
89 ReverseSubrange subrange(ReverseIt(std::ranges::end(view)), ReverseIt(std::ranges::begin(view)));
90 std::same_as<Subrange> auto result = std::views::reverse(subrange);
91 assert(base(result.begin()) == buf);
92 assert(base(result.end()) == buf + 3);
93 }
94 {
95 // std::move into views::reverse
96 BidirRange view(buf, buf + 3);
97 ReverseSubrange subrange(ReverseIt(std::ranges::end(view)), ReverseIt(std::ranges::begin(view)));
98 std::same_as<Subrange> auto result = std::views::reverse(std::move(subrange));
99 assert(base(result.begin()) == buf);
100 assert(base(result.end()) == buf + 3);
101 }
102 {
103 // with a const subrange
104 BidirRange view(buf, buf + 3);
105 ReverseSubrange const subrange(ReverseIt(std::ranges::end(view)), ReverseIt(std::ranges::begin(view)));
106 std::same_as<Subrange> auto result = std::views::reverse(subrange);
107 assert(base(result.begin()) == buf);
108 assert(base(result.end()) == buf + 3);
109 }
110 }
111
112 // Otherwise, views::reverse(x) is equivalent to ranges::reverse_view{x}
113 {
114 BidirRange view(buf, buf + 3);
115 std::same_as<std::ranges::reverse_view<BidirRange>> auto result = std::views::reverse(view);
116 assert(base(result.begin().base()) == buf + 3);
117 assert(base(result.end().base()) == buf);
118 }
119
120 // Test that std::views::reverse is a range adaptor
121 {
122 // Test `v | views::reverse`
123 {
124 BidirRange view(buf, buf + 3);
125 std::same_as<std::ranges::reverse_view<BidirRange>> auto result = view | std::views::reverse;
126 assert(base(result.begin().base()) == buf + 3);
127 assert(base(result.end().base()) == buf);
128 }
129
130 // Test `adaptor | views::reverse`
131 {
132 BidirRange view(buf, buf + 3);
133 auto f = [](int i) { return i; };
134 auto const partial = std::views::transform(f) | std::views::reverse;
135 using Result = std::ranges::reverse_view<std::ranges::transform_view<BidirRange, decltype(f)>>;
136 std::same_as<Result> auto result = partial(view);
137 assert(base(result.begin().base().base()) == buf + 3);
138 assert(base(result.end().base().base()) == buf);
139 }
140
141 // Test `views::reverse | adaptor`
142 {
143 BidirRange view(buf, buf + 3);
144 auto f = [](int i) { return i; };
145 auto const partial = std::views::reverse | std::views::transform(f);
146 using Result = std::ranges::transform_view<std::ranges::reverse_view<BidirRange>, decltype(f)>;
147 std::same_as<Result> auto result = partial(view);
148 assert(base(result.begin().base().base()) == buf + 3);
149 assert(base(result.end().base().base()) == buf);
150 }
151
152 // Check SFINAE friendliness
153 {
154 struct NotABidirRange { };
155 static_assert(!std::is_invocable_v<decltype(std::views::reverse)>);
156 static_assert(!std::is_invocable_v<decltype(std::views::reverse), NotABidirRange>);
157 static_assert( CanBePiped<BidirRange, decltype(std::views::reverse)>);
158 static_assert( CanBePiped<BidirRange&, decltype(std::views::reverse)>);
159 static_assert(!CanBePiped<NotABidirRange, decltype(std::views::reverse)>);
160 }
161 }
162
163 {
164 static_assert(std::same_as<decltype(std::views::reverse), decltype(std::ranges::views::reverse)>);
165 }
166
167 return true;
168}
169
170int main(int, char**) {
171 test();
172 static_assert(test());
173
174 return 0;
175}
176

source code of libcxx/test/std/ranges/range.adaptors/range.reverse/adaptor.pass.cpp