1065dc485SJakub Mazurkiewicz //===----------------------------------------------------------------------===//
2065dc485SJakub Mazurkiewicz //
3065dc485SJakub Mazurkiewicz // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4065dc485SJakub Mazurkiewicz // See https://llvm.org/LICENSE.txt for license information.
5065dc485SJakub Mazurkiewicz // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6065dc485SJakub Mazurkiewicz //
7065dc485SJakub Mazurkiewicz //===----------------------------------------------------------------------===//
8065dc485SJakub Mazurkiewicz
9065dc485SJakub Mazurkiewicz // UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
10065dc485SJakub Mazurkiewicz
11065dc485SJakub Mazurkiewicz // <ranges>
12065dc485SJakub Mazurkiewicz
13065dc485SJakub Mazurkiewicz // std::views::chunk_by
14065dc485SJakub Mazurkiewicz
15065dc485SJakub Mazurkiewicz #include <ranges>
16065dc485SJakub Mazurkiewicz
17065dc485SJakub Mazurkiewicz #include <algorithm>
18065dc485SJakub Mazurkiewicz #include <cassert>
19065dc485SJakub Mazurkiewicz #include <concepts>
20065dc485SJakub Mazurkiewicz #include <initializer_list>
21065dc485SJakub Mazurkiewicz #include <type_traits>
22065dc485SJakub Mazurkiewicz #include <utility>
23065dc485SJakub Mazurkiewicz
24065dc485SJakub Mazurkiewicz #include "test_iterators.h"
25*ba2236d3SWill Hawkins #include "test_range.h"
26065dc485SJakub Mazurkiewicz
27065dc485SJakub Mazurkiewicz struct Pred {
operator ()Pred28065dc485SJakub Mazurkiewicz constexpr bool operator()(int x, int y) const { return x != -y; }
29065dc485SJakub Mazurkiewicz };
30065dc485SJakub Mazurkiewicz
31065dc485SJakub Mazurkiewicz struct NonCopyablePredicate : Pred {
32065dc485SJakub Mazurkiewicz NonCopyablePredicate(NonCopyablePredicate const&) = delete;
33065dc485SJakub Mazurkiewicz };
34065dc485SJakub Mazurkiewicz
35065dc485SJakub Mazurkiewicz struct Range : std::ranges::view_base {
36065dc485SJakub Mazurkiewicz using Iterator = forward_iterator<int*>;
37065dc485SJakub Mazurkiewicz using Sentinel = sentinel_wrapper<Iterator>;
RangeRange38065dc485SJakub Mazurkiewicz constexpr explicit Range(int* b, int* e) : begin_(b), end_(e) {}
beginRange39065dc485SJakub Mazurkiewicz constexpr Iterator begin() const { return Iterator(begin_); }
endRange40065dc485SJakub Mazurkiewicz constexpr Sentinel end() const { return Sentinel(Iterator(end_)); }
41065dc485SJakub Mazurkiewicz
42065dc485SJakub Mazurkiewicz private:
43065dc485SJakub Mazurkiewicz int* begin_;
44065dc485SJakub Mazurkiewicz int* end_;
45065dc485SJakub Mazurkiewicz };
46065dc485SJakub Mazurkiewicz
47065dc485SJakub Mazurkiewicz template <typename View>
compareViews(View v,std::initializer_list<std::initializer_list<int>> list)48065dc485SJakub Mazurkiewicz constexpr void compareViews(View v, std::initializer_list<std::initializer_list<int>> list) {
49065dc485SJakub Mazurkiewicz auto b1 = v.begin();
50065dc485SJakub Mazurkiewicz auto e1 = v.end();
51065dc485SJakub Mazurkiewicz auto b2 = list.begin();
52065dc485SJakub Mazurkiewicz auto e2 = list.end();
53065dc485SJakub Mazurkiewicz for (; b1 != e1 && b2 != e2; ++b1, ++b2) {
54065dc485SJakub Mazurkiewicz bool eq = std::ranges::equal(*b1, *b2, [](int x, int y) {
55065dc485SJakub Mazurkiewicz assert(x == y);
56065dc485SJakub Mazurkiewicz return true;
57065dc485SJakub Mazurkiewicz });
58065dc485SJakub Mazurkiewicz assert(eq);
59065dc485SJakub Mazurkiewicz }
60065dc485SJakub Mazurkiewicz assert(b1 == e1);
61065dc485SJakub Mazurkiewicz assert(b2 == e2);
62065dc485SJakub Mazurkiewicz }
63065dc485SJakub Mazurkiewicz
absoluteValue(int x)64065dc485SJakub Mazurkiewicz constexpr int absoluteValue(int x) { return x < 0 ? -x : x; }
65065dc485SJakub Mazurkiewicz
66065dc485SJakub Mazurkiewicz template <class T>
asConstRvalue(T && t)67065dc485SJakub Mazurkiewicz constexpr const T&& asConstRvalue(T&& t) {
68065dc485SJakub Mazurkiewicz return static_cast<T const&&>(t);
69065dc485SJakub Mazurkiewicz }
70065dc485SJakub Mazurkiewicz
test()71065dc485SJakub Mazurkiewicz constexpr bool test() {
72065dc485SJakub Mazurkiewicz int buff[] = {-4, -3, -2, -1, 1, 2, 3, 4};
73065dc485SJakub Mazurkiewicz
74065dc485SJakub Mazurkiewicz // Test range adaptor object
75065dc485SJakub Mazurkiewicz {
76065dc485SJakub Mazurkiewicz using RangeAdaptorObject = decltype(std::views::chunk_by);
77065dc485SJakub Mazurkiewicz static_assert(std::is_const_v<RangeAdaptorObject>);
78065dc485SJakub Mazurkiewicz
79065dc485SJakub Mazurkiewicz // The type of a customization point object, ignoring cv-qualifiers, shall model semiregular
80065dc485SJakub Mazurkiewicz static_assert(std::semiregular<std::remove_const<RangeAdaptorObject>>);
81065dc485SJakub Mazurkiewicz }
82065dc485SJakub Mazurkiewicz
83065dc485SJakub Mazurkiewicz // Test `views::chunk_by(pred)(v)`
84065dc485SJakub Mazurkiewicz {
85065dc485SJakub Mazurkiewicz using Result = std::ranges::chunk_by_view<Range, Pred>;
86065dc485SJakub Mazurkiewicz Range const range(buff, buff + 8);
87065dc485SJakub Mazurkiewicz Pred pred;
88065dc485SJakub Mazurkiewicz
89065dc485SJakub Mazurkiewicz {
90065dc485SJakub Mazurkiewicz // 'views::chunk_by(pred)' - &&
91065dc485SJakub Mazurkiewicz std::same_as<Result> decltype(auto) result = std::views::chunk_by(pred)(range);
92065dc485SJakub Mazurkiewicz compareViews(result, {{-4, -3, -2, -1}, {1, 2, 3, 4}});
93065dc485SJakub Mazurkiewicz }
94065dc485SJakub Mazurkiewicz {
95065dc485SJakub Mazurkiewicz // 'views::chunk_by(pred)' - const&&
96065dc485SJakub Mazurkiewicz std::same_as<Result> decltype(auto) result = asConstRvalue(std::views::chunk_by(pred))(range);
97065dc485SJakub Mazurkiewicz compareViews(result, {{-4, -3, -2, -1}, {1, 2, 3, 4}});
98065dc485SJakub Mazurkiewicz }
99065dc485SJakub Mazurkiewicz {
100065dc485SJakub Mazurkiewicz // 'views::chunk_by(pred)' - &
101065dc485SJakub Mazurkiewicz auto partial = std::views::chunk_by(pred);
102065dc485SJakub Mazurkiewicz std::same_as<Result> decltype(auto) result = partial(range);
103065dc485SJakub Mazurkiewicz compareViews(result, {{-4, -3, -2, -1}, {1, 2, 3, 4}});
104065dc485SJakub Mazurkiewicz }
105065dc485SJakub Mazurkiewicz {
106065dc485SJakub Mazurkiewicz // 'views::chunk_by(pred)' - const&
107065dc485SJakub Mazurkiewicz auto const partial = std::views::chunk_by(pred);
108065dc485SJakub Mazurkiewicz std::same_as<Result> decltype(auto) result = partial(range);
109065dc485SJakub Mazurkiewicz compareViews(result, {{-4, -3, -2, -1}, {1, 2, 3, 4}});
110065dc485SJakub Mazurkiewicz }
111065dc485SJakub Mazurkiewicz }
112065dc485SJakub Mazurkiewicz
113065dc485SJakub Mazurkiewicz // Test `v | views::chunk_by(pred)`
114065dc485SJakub Mazurkiewicz {
115065dc485SJakub Mazurkiewicz using Result = std::ranges::chunk_by_view<Range, Pred>;
116065dc485SJakub Mazurkiewicz Range const range(buff, buff + 8);
117065dc485SJakub Mazurkiewicz Pred pred;
118065dc485SJakub Mazurkiewicz
119065dc485SJakub Mazurkiewicz {
120065dc485SJakub Mazurkiewicz // 'views::chunk_by(pred)' - &&
121065dc485SJakub Mazurkiewicz std::same_as<Result> decltype(auto) result = range | std::views::chunk_by(pred);
122065dc485SJakub Mazurkiewicz compareViews(result, {{-4, -3, -2, -1}, {1, 2, 3, 4}});
123065dc485SJakub Mazurkiewicz }
124065dc485SJakub Mazurkiewicz {
125065dc485SJakub Mazurkiewicz // 'views::chunk_by(pred)' - const&&
126065dc485SJakub Mazurkiewicz std::same_as<Result> decltype(auto) result = range | asConstRvalue(std::views::chunk_by(pred));
127065dc485SJakub Mazurkiewicz compareViews(result, {{-4, -3, -2, -1}, {1, 2, 3, 4}});
128065dc485SJakub Mazurkiewicz }
129065dc485SJakub Mazurkiewicz {
130065dc485SJakub Mazurkiewicz // 'views::chunk_by(pred)' - &
131065dc485SJakub Mazurkiewicz auto partial = std::views::chunk_by(pred);
132065dc485SJakub Mazurkiewicz std::same_as<Result> decltype(auto) result = range | partial;
133065dc485SJakub Mazurkiewicz compareViews(result, {{-4, -3, -2, -1}, {1, 2, 3, 4}});
134065dc485SJakub Mazurkiewicz }
135065dc485SJakub Mazurkiewicz {
136065dc485SJakub Mazurkiewicz // 'views::chunk_by(pred)' - const&
137065dc485SJakub Mazurkiewicz auto const partial = std::views::chunk_by(pred);
138065dc485SJakub Mazurkiewicz std::same_as<Result> decltype(auto) result = range | partial;
139065dc485SJakub Mazurkiewicz compareViews(result, {{-4, -3, -2, -1}, {1, 2, 3, 4}});
140065dc485SJakub Mazurkiewicz }
141065dc485SJakub Mazurkiewicz }
142065dc485SJakub Mazurkiewicz
143065dc485SJakub Mazurkiewicz // Test `views::chunk_by(v, pred)` range adaptor object
144065dc485SJakub Mazurkiewicz {
145065dc485SJakub Mazurkiewicz using Result = std::ranges::chunk_by_view<Range, Pred>;
146065dc485SJakub Mazurkiewicz Range const range(buff, buff + 8);
147065dc485SJakub Mazurkiewicz Pred pred;
148065dc485SJakub Mazurkiewicz
149065dc485SJakub Mazurkiewicz {
150065dc485SJakub Mazurkiewicz // 'views::chunk_by' - &&
151065dc485SJakub Mazurkiewicz auto range_adaptor = std::views::chunk_by;
152065dc485SJakub Mazurkiewicz std::same_as<Result> decltype(auto) result = std::move(range_adaptor)(range, pred);
153065dc485SJakub Mazurkiewicz compareViews(result, {{-4, -3, -2, -1}, {1, 2, 3, 4}});
154065dc485SJakub Mazurkiewicz }
155065dc485SJakub Mazurkiewicz {
156065dc485SJakub Mazurkiewicz // 'views::chunk_by' - const&&
157065dc485SJakub Mazurkiewicz auto const range_adaptor = std::views::chunk_by;
158065dc485SJakub Mazurkiewicz std::same_as<Result> decltype(auto) result = std::move(range_adaptor)(range, pred);
159065dc485SJakub Mazurkiewicz compareViews(result, {{-4, -3, -2, -1}, {1, 2, 3, 4}});
160065dc485SJakub Mazurkiewicz }
161065dc485SJakub Mazurkiewicz {
162065dc485SJakub Mazurkiewicz // 'views::chunk_by' - &
163065dc485SJakub Mazurkiewicz auto range_adaptor = std::views::chunk_by;
164065dc485SJakub Mazurkiewicz std::same_as<Result> decltype(auto) result = range_adaptor(range, pred);
165065dc485SJakub Mazurkiewicz compareViews(result, {{-4, -3, -2, -1}, {1, 2, 3, 4}});
166065dc485SJakub Mazurkiewicz }
167065dc485SJakub Mazurkiewicz {
168065dc485SJakub Mazurkiewicz // 'views::chunk_by' - const&
169065dc485SJakub Mazurkiewicz auto const range_adaptor = std::views::chunk_by;
170065dc485SJakub Mazurkiewicz std::same_as<Result> decltype(auto) result = range_adaptor(range, pred);
171065dc485SJakub Mazurkiewicz compareViews(result, {{-4, -3, -2, -1}, {1, 2, 3, 4}});
172065dc485SJakub Mazurkiewicz }
173065dc485SJakub Mazurkiewicz }
174065dc485SJakub Mazurkiewicz
175065dc485SJakub Mazurkiewicz // Test that one can call std::views::chunk_by with arbitrary stuff, as long as we
176065dc485SJakub Mazurkiewicz // don't try to actually complete the call by passing it a range.
177065dc485SJakub Mazurkiewicz //
178065dc485SJakub Mazurkiewicz // That makes no sense and we can't do anything with the result, but it's valid.
179065dc485SJakub Mazurkiewicz {
180065dc485SJakub Mazurkiewicz int array[3] = {1, 2, 3};
181065dc485SJakub Mazurkiewicz [[maybe_unused]] auto partial = std::views::chunk_by(std::move(array));
182065dc485SJakub Mazurkiewicz }
183065dc485SJakub Mazurkiewicz
184065dc485SJakub Mazurkiewicz // Test `adaptor | views::chunk_by(pred)`
185065dc485SJakub Mazurkiewicz {
186065dc485SJakub Mazurkiewicz Range const range(buff, buff + 8);
187065dc485SJakub Mazurkiewicz
188065dc485SJakub Mazurkiewicz {
189065dc485SJakub Mazurkiewicz auto pred1 = [](int i) { return absoluteValue(i) < 3; };
190065dc485SJakub Mazurkiewicz Pred pred2;
191065dc485SJakub Mazurkiewicz using Result = std::ranges::chunk_by_view<std::ranges::filter_view<Range, decltype(pred1)>, Pred>;
192065dc485SJakub Mazurkiewicz std::same_as<Result> decltype(auto) result = range | std::views::filter(pred1) | std::views::chunk_by(pred2);
193065dc485SJakub Mazurkiewicz compareViews(result, {{-2, -1}, {1, 2}});
194065dc485SJakub Mazurkiewicz }
195065dc485SJakub Mazurkiewicz {
196065dc485SJakub Mazurkiewicz auto pred1 = [](int i) { return absoluteValue(i) < 3; };
197065dc485SJakub Mazurkiewicz Pred pred2;
198065dc485SJakub Mazurkiewicz using Result = std::ranges::chunk_by_view<std::ranges::filter_view<Range, decltype(pred1)>, Pred>;
199065dc485SJakub Mazurkiewicz auto const partial = std::views::filter(pred1) | std::views::chunk_by(pred2);
200065dc485SJakub Mazurkiewicz std::same_as<Result> decltype(auto) result = range | partial;
201065dc485SJakub Mazurkiewicz compareViews(result, {{-2, -1}, {1, 2}});
202065dc485SJakub Mazurkiewicz }
203065dc485SJakub Mazurkiewicz }
204065dc485SJakub Mazurkiewicz
205065dc485SJakub Mazurkiewicz // Test SFINAE friendliness
206065dc485SJakub Mazurkiewicz {
207065dc485SJakub Mazurkiewicz struct NotAView {};
208065dc485SJakub Mazurkiewicz struct NotInvocable {};
209065dc485SJakub Mazurkiewicz
210065dc485SJakub Mazurkiewicz static_assert(!CanBePiped<Range, decltype(std::views::chunk_by)>);
211065dc485SJakub Mazurkiewicz static_assert(CanBePiped<Range, decltype(std::views::chunk_by(Pred{}))>);
212065dc485SJakub Mazurkiewicz static_assert(!CanBePiped<NotAView, decltype(std::views::chunk_by(Pred{}))>);
213065dc485SJakub Mazurkiewicz static_assert(!CanBePiped<std::initializer_list<int>, decltype(std::views::chunk_by(Pred{}))>);
214065dc485SJakub Mazurkiewicz static_assert(!CanBePiped<Range, decltype(std::views::chunk_by(NotInvocable{}))>);
215065dc485SJakub Mazurkiewicz
216065dc485SJakub Mazurkiewicz static_assert(!std::is_invocable_v<decltype(std::views::chunk_by)>);
217065dc485SJakub Mazurkiewicz static_assert(!std::is_invocable_v<decltype(std::views::chunk_by), Pred, Range>);
218065dc485SJakub Mazurkiewicz static_assert(std::is_invocable_v<decltype(std::views::chunk_by), Range, Pred>);
219065dc485SJakub Mazurkiewicz static_assert(!std::is_invocable_v<decltype(std::views::chunk_by), Range, Pred, Pred>);
220065dc485SJakub Mazurkiewicz static_assert(!std::is_invocable_v<decltype(std::views::chunk_by), NonCopyablePredicate>);
221065dc485SJakub Mazurkiewicz }
222065dc485SJakub Mazurkiewicz
223065dc485SJakub Mazurkiewicz { static_assert(std::is_same_v<decltype(std::ranges::views::chunk_by), decltype(std::views::chunk_by)>); }
224065dc485SJakub Mazurkiewicz
225065dc485SJakub Mazurkiewicz return true;
226065dc485SJakub Mazurkiewicz }
227065dc485SJakub Mazurkiewicz
main(int,char **)228065dc485SJakub Mazurkiewicz int main(int, char**) {
229065dc485SJakub Mazurkiewicz test();
230065dc485SJakub Mazurkiewicz static_assert(test());
231065dc485SJakub Mazurkiewicz
232065dc485SJakub Mazurkiewicz return 0;
233065dc485SJakub Mazurkiewicz }
234