173ebcabfSKonstantin Varlamov //===----------------------------------------------------------------------===//
273ebcabfSKonstantin Varlamov //
373ebcabfSKonstantin Varlamov // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
473ebcabfSKonstantin Varlamov // See https://llvm.org/LICENSE.txt for license information.
573ebcabfSKonstantin Varlamov // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
673ebcabfSKonstantin Varlamov //
773ebcabfSKonstantin Varlamov //===----------------------------------------------------------------------===//
873ebcabfSKonstantin Varlamov
973ebcabfSKonstantin Varlamov // UNSUPPORTED: c++03, c++11, c++14, c++17
1073ebcabfSKonstantin Varlamov
1173ebcabfSKonstantin Varlamov // <algorithm>
1273ebcabfSKonstantin Varlamov
1373ebcabfSKonstantin Varlamov // template<input_iterator I, sentinel_for<I> S,
1473ebcabfSKonstantin Varlamov // weakly_incrementable O1, weakly_incrementable O2,
1573ebcabfSKonstantin Varlamov // class Proj = identity, indirect_unary_predicate<projected<I, Proj>> Pred>
1673ebcabfSKonstantin Varlamov // requires indirectly_copyable<I, O1> && indirectly_copyable<I, O2>
1773ebcabfSKonstantin Varlamov // constexpr partition_copy_result<I, O1, O2>
1873ebcabfSKonstantin Varlamov // partition_copy(I first, S last, O1 out_true, O2 out_false, Pred pred,
1973ebcabfSKonstantin Varlamov // Proj proj = {}); // Since C++20
2073ebcabfSKonstantin Varlamov //
2173ebcabfSKonstantin Varlamov // template<input_range R, weakly_incrementable O1, weakly_incrementable O2,
2273ebcabfSKonstantin Varlamov // class Proj = identity,
2373ebcabfSKonstantin Varlamov // indirect_unary_predicate<projected<iterator_t<R>, Proj>> Pred>
2473ebcabfSKonstantin Varlamov // requires indirectly_copyable<iterator_t<R>, O1> &&
2573ebcabfSKonstantin Varlamov // indirectly_copyable<iterator_t<R>, O2>
2673ebcabfSKonstantin Varlamov // constexpr partition_copy_result<borrowed_iterator_t<R>, O1, O2>
2773ebcabfSKonstantin Varlamov // partition_copy(R&& r, O1 out_true, O2 out_false, Pred pred, Proj proj = {}); // Since C++20
2873ebcabfSKonstantin Varlamov
2973ebcabfSKonstantin Varlamov #include <algorithm>
3073ebcabfSKonstantin Varlamov #include <array>
3173ebcabfSKonstantin Varlamov #include <concepts>
3273ebcabfSKonstantin Varlamov #include <functional>
3373ebcabfSKonstantin Varlamov #include <ranges>
34065202f3SKonstantin Varlamov #include <utility>
3573ebcabfSKonstantin Varlamov
3673ebcabfSKonstantin Varlamov #include "almost_satisfies_types.h"
37065202f3SKonstantin Varlamov #include "counting_predicates.h"
38065202f3SKonstantin Varlamov #include "counting_projection.h"
3973ebcabfSKonstantin Varlamov #include "test_iterators.h"
4073ebcabfSKonstantin Varlamov
41065202f3SKonstantin Varlamov struct UnaryPred { bool operator()(int) const; };
42065202f3SKonstantin Varlamov
43065202f3SKonstantin Varlamov // Test constraints of the (iterator, sentinel) overload.
44065202f3SKonstantin Varlamov // ======================================================
45065202f3SKonstantin Varlamov
46065202f3SKonstantin Varlamov template <class InIter = int*, class Sent = int*, class Output1 = int*, class Output2 = int*, class Pred = UnaryPred>
47065202f3SKonstantin Varlamov concept HasPartitionCopyIter =
48065202f3SKonstantin Varlamov requires(InIter&& input, Sent&& sent, Output1&& output1, Output2&& output2, Pred&& pred) {
49065202f3SKonstantin Varlamov std::ranges::partition_copy(std::forward<InIter>(input), std::forward<Sent>(sent),
50065202f3SKonstantin Varlamov std::forward<Output1>(output1), std::forward<Output2>(output2), std::forward<Pred>(pred));
51065202f3SKonstantin Varlamov };
52065202f3SKonstantin Varlamov
53065202f3SKonstantin Varlamov static_assert(HasPartitionCopyIter<int*, int*, int*, int*, UnaryPred>);
54065202f3SKonstantin Varlamov
55065202f3SKonstantin Varlamov // !input_iterator<I>
56065202f3SKonstantin Varlamov static_assert(!HasPartitionCopyIter<InputIteratorNotDerivedFrom>);
57065202f3SKonstantin Varlamov static_assert(!HasPartitionCopyIter<InputIteratorNotIndirectlyReadable>);
58065202f3SKonstantin Varlamov static_assert(!HasPartitionCopyIter<InputIteratorNotInputOrOutputIterator>);
59065202f3SKonstantin Varlamov
60065202f3SKonstantin Varlamov // !sentinel_for<S, I>
61065202f3SKonstantin Varlamov static_assert(!HasPartitionCopyIter<int*, SentinelForNotSemiregular>);
62065202f3SKonstantin Varlamov static_assert(!HasPartitionCopyIter<int*, SentinelForNotWeaklyEqualityComparableWith>);
63065202f3SKonstantin Varlamov
64065202f3SKonstantin Varlamov // !weakly_incrementable<O1>
65065202f3SKonstantin Varlamov static_assert(!HasPartitionCopyIter<int*, int*, WeaklyIncrementableNotMovable>);
66065202f3SKonstantin Varlamov
67065202f3SKonstantin Varlamov // !weakly_incrementable<O2>
68065202f3SKonstantin Varlamov static_assert(!HasPartitionCopyIter<int*, int*, int*, WeaklyIncrementableNotMovable>);
69065202f3SKonstantin Varlamov
70065202f3SKonstantin Varlamov // !indirect_unary_predicate<projected<I, Proj>>
71065202f3SKonstantin Varlamov static_assert(!HasPartitionCopyIter<int*, int*, int*, int*, IndirectUnaryPredicateNotPredicate>);
72065202f3SKonstantin Varlamov static_assert(!HasPartitionCopyIter<int*, int*, int*, int*, IndirectUnaryPredicateNotCopyConstructible>);
73065202f3SKonstantin Varlamov
74065202f3SKonstantin Varlamov struct Uncopyable {
75065202f3SKonstantin Varlamov Uncopyable(int&&);
76065202f3SKonstantin Varlamov Uncopyable(const int&) = delete;
77065202f3SKonstantin Varlamov };
78065202f3SKonstantin Varlamov // !indirectly_copyable<I, O1>
79065202f3SKonstantin Varlamov static_assert(!HasPartitionCopyIter<int*, int*, Uncopyable*>);
80065202f3SKonstantin Varlamov // !indirectly_copyable<I, O2>
81065202f3SKonstantin Varlamov static_assert(!HasPartitionCopyIter<int*, int*, int*, Uncopyable*>);
82065202f3SKonstantin Varlamov
83065202f3SKonstantin Varlamov // Test constraints of the (range) overload.
84065202f3SKonstantin Varlamov // =========================================
85065202f3SKonstantin Varlamov
86065202f3SKonstantin Varlamov template <class InputRange, class Output1 = int*, class Output2 = int*, class Pred = UnaryPred>
87065202f3SKonstantin Varlamov concept HasPartitionCopyRange =
88065202f3SKonstantin Varlamov requires(InputRange&& input, Output1&& output1, Output2&& output2, Pred&& pred) {
89065202f3SKonstantin Varlamov std::ranges::partition_copy(std::forward<InputRange>(input),
90065202f3SKonstantin Varlamov std::forward<Output1>(output1), std::forward<Output2>(output2), std::forward<Pred>(pred));
91065202f3SKonstantin Varlamov };
92065202f3SKonstantin Varlamov
93065202f3SKonstantin Varlamov template <class T>
94065202f3SKonstantin Varlamov using R = UncheckedRange<T>;
95065202f3SKonstantin Varlamov
96065202f3SKonstantin Varlamov static_assert(HasPartitionCopyRange<R<int*>, int*, int*, UnaryPred>);
97065202f3SKonstantin Varlamov
98065202f3SKonstantin Varlamov // !input_iterator<I>
99065202f3SKonstantin Varlamov static_assert(!HasPartitionCopyRange<InputRangeNotDerivedFrom>);
100065202f3SKonstantin Varlamov static_assert(!HasPartitionCopyRange<InputRangeNotIndirectlyReadable>);
101065202f3SKonstantin Varlamov static_assert(!HasPartitionCopyRange<InputRangeNotInputOrOutputIterator>);
102065202f3SKonstantin Varlamov
103065202f3SKonstantin Varlamov // !weakly_incrementable<O1>
104065202f3SKonstantin Varlamov static_assert(!HasPartitionCopyRange<R<int*>, WeaklyIncrementableNotMovable>);
105065202f3SKonstantin Varlamov
106065202f3SKonstantin Varlamov // !weakly_incrementable<O2>
107065202f3SKonstantin Varlamov static_assert(!HasPartitionCopyRange<R<int*>, int*, WeaklyIncrementableNotMovable>);
108065202f3SKonstantin Varlamov
109065202f3SKonstantin Varlamov // !indirect_unary_predicate<projected<I, Proj>>
110065202f3SKonstantin Varlamov static_assert(!HasPartitionCopyRange<R<int*>, int*, int*, IndirectUnaryPredicateNotPredicate>);
111065202f3SKonstantin Varlamov static_assert(!HasPartitionCopyRange<R<int*>, int*, int*, IndirectUnaryPredicateNotCopyConstructible>);
112065202f3SKonstantin Varlamov
113065202f3SKonstantin Varlamov // !indirectly_copyable<I, O1>
114065202f3SKonstantin Varlamov static_assert(!HasPartitionCopyRange<R<int*>, Uncopyable*>);
115065202f3SKonstantin Varlamov // !indirectly_copyable<I, O2>
116065202f3SKonstantin Varlamov static_assert(!HasPartitionCopyRange<R<int*>, int*, Uncopyable*>);
117065202f3SKonstantin Varlamov
118065202f3SKonstantin Varlamov static_assert(std::is_same_v<std::ranges::partition_copy_result<int, int, int>,
119065202f3SKonstantin Varlamov std::ranges::in_out_out_result<int, int, int>>);
120065202f3SKonstantin Varlamov
121fb855eb9SMark de Wever template <class Iter, class Sent, class OutIter1, class OutIter2, std::size_t N1, size_t N2, size_t N3, class Pred>
test_one(std::array<int,N1> input,Pred pred,std::array<int,N2> expected_true,std::array<int,N3> expected_false)122065202f3SKonstantin Varlamov constexpr void test_one(std::array<int, N1> input, Pred pred, std::array<int, N2> expected_true,
123065202f3SKonstantin Varlamov std::array<int, N3> expected_false) {
124065202f3SKonstantin Varlamov static_assert(N2 + N3 == N1);
125065202f3SKonstantin Varlamov using ResultT = std::ranges::partition_copy_result<Iter, OutIter1, OutIter2>;
126065202f3SKonstantin Varlamov
127065202f3SKonstantin Varlamov auto begin = input.data();
128065202f3SKonstantin Varlamov auto end = input.data() + input.size();
129065202f3SKonstantin Varlamov
130065202f3SKonstantin Varlamov { // (iterator, sentinel) overload.
131065202f3SKonstantin Varlamov std::array<int, N2> out1;
132065202f3SKonstantin Varlamov std::array<int, N3> out2;
133065202f3SKonstantin Varlamov
134065202f3SKonstantin Varlamov std::same_as<ResultT> decltype(auto) result = std::ranges::partition_copy(
135*d05bada5SDuo Wang Iter(begin), Sent(Iter(end)), OutIter1(out1.data()), OutIter2(out2.data()), pred);
136065202f3SKonstantin Varlamov
137065202f3SKonstantin Varlamov assert(base(result.in) == input.data() + input.size());
138065202f3SKonstantin Varlamov assert(base(result.out1) == out1.data() + expected_true.size());
139065202f3SKonstantin Varlamov assert(base(result.out2) == out2.data() + expected_false.size());
140065202f3SKonstantin Varlamov
141065202f3SKonstantin Varlamov assert(std::ranges::equal(out1, expected_true));
142065202f3SKonstantin Varlamov assert(std::ranges::equal(out2, expected_false));
143065202f3SKonstantin Varlamov }
144065202f3SKonstantin Varlamov
145065202f3SKonstantin Varlamov { // (range) overload.
146065202f3SKonstantin Varlamov std::ranges::subrange range{Iter(begin), Sent(Iter(end))};
147065202f3SKonstantin Varlamov std::array<int, N2> out1;
148065202f3SKonstantin Varlamov std::array<int, N3> out2;
149065202f3SKonstantin Varlamov
150065202f3SKonstantin Varlamov std::same_as<ResultT> decltype(auto) result = std::ranges::partition_copy(
151*d05bada5SDuo Wang range, OutIter1(out1.data()), OutIter2(out2.data()), pred);
152065202f3SKonstantin Varlamov
153065202f3SKonstantin Varlamov assert(base(result.in) == input.data() + input.size());
154065202f3SKonstantin Varlamov assert(base(result.out1) == out1.data() + expected_true.size());
155065202f3SKonstantin Varlamov assert(base(result.out2) == out2.data() + expected_false.size());
156065202f3SKonstantin Varlamov
157065202f3SKonstantin Varlamov assert(std::ranges::equal(out1, expected_true));
158065202f3SKonstantin Varlamov assert(std::ranges::equal(out2, expected_false));
159065202f3SKonstantin Varlamov }
160065202f3SKonstantin Varlamov }
161065202f3SKonstantin Varlamov
162065202f3SKonstantin Varlamov template <class InIter, class Sent, class Out1, class Out2>
test_iterators_in_sent_out1_out2()163065202f3SKonstantin Varlamov constexpr void test_iterators_in_sent_out1_out2() {
164065202f3SKonstantin Varlamov auto is_odd = [](int x) { return x % 2 != 0; };
165065202f3SKonstantin Varlamov
166065202f3SKonstantin Varlamov // Empty sequence.
167065202f3SKonstantin Varlamov test_one<InIter, Sent, Out1, Out2, 0, 0, 0>({}, is_odd, {}, {});
168065202f3SKonstantin Varlamov // 1-element sequence, the element satisfies the predicate.
169065202f3SKonstantin Varlamov test_one<InIter, Sent, Out1, Out2, 1, 1, 0>({1}, is_odd, {1}, {});
170065202f3SKonstantin Varlamov // 1-element sequence, the element doesn't satisfy the predicate.
171065202f3SKonstantin Varlamov test_one<InIter, Sent, Out1, Out2, 1, 0, 1>({2}, is_odd, {}, {2});
172065202f3SKonstantin Varlamov // 2-element sequence, not in order.
173065202f3SKonstantin Varlamov test_one<InIter, Sent, Out1, Out2, 2, 1, 1>({2, 1}, is_odd, {1}, {2});
174065202f3SKonstantin Varlamov // 2-element sequence, already in order.
175065202f3SKonstantin Varlamov test_one<InIter, Sent, Out1, Out2, 2, 1, 1>({1, 2}, is_odd, {1}, {2});
176065202f3SKonstantin Varlamov // 3-element sequence.
177065202f3SKonstantin Varlamov test_one<InIter, Sent, Out1, Out2, 3, 2, 1>({2, 1, 3}, is_odd, {1, 3}, {2});
178065202f3SKonstantin Varlamov // Longer sequence.
179065202f3SKonstantin Varlamov test_one<InIter, Sent, Out1, Out2, 8, 4, 4>({2, 1, 3, 6, 8, 4, 11, 5}, is_odd, {1, 3, 11, 5}, {2, 6, 8, 4});
180065202f3SKonstantin Varlamov // Longer sequence with duplicates.
181065202f3SKonstantin Varlamov test_one<InIter, Sent, Out1, Out2, 8, 3, 5>({2, 1, 3, 6, 2, 8, 1, 6}, is_odd, {1, 3, 1}, {2, 6, 2, 8, 6});
182065202f3SKonstantin Varlamov // All elements are the same and satisfy the predicate.
183065202f3SKonstantin Varlamov test_one<InIter, Sent, Out1, Out2, 3, 3, 0>({1, 1, 1}, is_odd, {1, 1, 1}, {});
184065202f3SKonstantin Varlamov // All elements are the same and don't satisfy the predicate.
185065202f3SKonstantin Varlamov test_one<InIter, Sent, Out1, Out2, 3, 0, 3>({2, 2, 2}, is_odd, {}, {2, 2, 2});
186065202f3SKonstantin Varlamov // Already partitioned.
187065202f3SKonstantin Varlamov test_one<InIter, Sent, Out1, Out2, 6, 3, 3>({1, 3, 5, 4, 6, 8}, is_odd, {1, 3, 5}, {4, 6, 8});
188065202f3SKonstantin Varlamov // Reverse-partitioned.
189065202f3SKonstantin Varlamov test_one<InIter, Sent, Out1, Out2, 6, 3, 3>({4, 6, 8, 1, 3, 5}, is_odd, {1, 3, 5}, {4, 6, 8});
190065202f3SKonstantin Varlamov // Repeating pattern.
191065202f3SKonstantin Varlamov test_one<InIter, Sent, Out1, Out2, 6, 3, 3>({1, 2, 1, 2, 1, 2}, is_odd, {1, 1, 1}, {2, 2, 2});
192065202f3SKonstantin Varlamov
193065202f3SKonstantin Varlamov auto is_negative = [](int x) { return x < 0; };
194065202f3SKonstantin Varlamov // Different comparator.
195065202f3SKonstantin Varlamov test_one<InIter, Sent, Out1, Out2, 5, 2, 3>({-3, 5, 7, -6, 2}, is_negative, {-3, -6}, {5, 7, 2});
196065202f3SKonstantin Varlamov }
197065202f3SKonstantin Varlamov
198065202f3SKonstantin Varlamov template <class InIter, class Sent, class Out1>
test_iterators_in_sent_out1()199065202f3SKonstantin Varlamov constexpr void test_iterators_in_sent_out1() {
200065202f3SKonstantin Varlamov test_iterators_in_sent_out1_out2<InIter, Sent, Out1, cpp20_output_iterator<int*>>();
201065202f3SKonstantin Varlamov test_iterators_in_sent_out1_out2<InIter, Sent, Out1, random_access_iterator<int*>>();
202065202f3SKonstantin Varlamov test_iterators_in_sent_out1_out2<InIter, Sent, Out1, int*>();
203065202f3SKonstantin Varlamov }
204065202f3SKonstantin Varlamov
205065202f3SKonstantin Varlamov template <class InIter, class Sent>
test_iterators_in_sent()206065202f3SKonstantin Varlamov constexpr void test_iterators_in_sent() {
207065202f3SKonstantin Varlamov test_iterators_in_sent_out1<InIter, Sent, cpp17_output_iterator<int*>>();
208065202f3SKonstantin Varlamov test_iterators_in_sent_out1<InIter, Sent, cpp20_output_iterator<int*>>();
209065202f3SKonstantin Varlamov test_iterators_in_sent_out1<InIter, Sent, random_access_iterator<int*>>();
210065202f3SKonstantin Varlamov test_iterators_in_sent_out1<InIter, Sent, int*>();
211065202f3SKonstantin Varlamov }
212065202f3SKonstantin Varlamov
213065202f3SKonstantin Varlamov template <class InIter>
test_iterators_in()214065202f3SKonstantin Varlamov constexpr void test_iterators_in() {
215065202f3SKonstantin Varlamov if constexpr (std::sentinel_for<InIter, InIter>) {
216065202f3SKonstantin Varlamov test_iterators_in_sent<InIter, InIter>();
217065202f3SKonstantin Varlamov }
218065202f3SKonstantin Varlamov test_iterators_in_sent<InIter, sentinel_wrapper<InIter>>();
219065202f3SKonstantin Varlamov }
220065202f3SKonstantin Varlamov
test_iterators()221065202f3SKonstantin Varlamov constexpr void test_iterators() {
222065202f3SKonstantin Varlamov // Note: deliberately testing with only the weakest and "strongest" iterator types to minimize combinatorial
223065202f3SKonstantin Varlamov // explosion.
224065202f3SKonstantin Varlamov test_iterators_in<cpp20_input_iterator<int*>>();
225065202f3SKonstantin Varlamov test_iterators_in<int*>();
226065202f3SKonstantin Varlamov }
22773ebcabfSKonstantin Varlamov
test()22873ebcabfSKonstantin Varlamov constexpr bool test() {
229065202f3SKonstantin Varlamov test_iterators();
230065202f3SKonstantin Varlamov
231065202f3SKonstantin Varlamov { // A custom projection works.
232065202f3SKonstantin Varlamov const std::array in = {1, 3, 9, -2, -5, -8};
233065202f3SKonstantin Varlamov auto is_negative = [](int x) { return x < 0; };
234065202f3SKonstantin Varlamov auto negate = [](int x) { return -x; };
235065202f3SKonstantin Varlamov const std::array expected_negative = {-2, -5, -8};
236065202f3SKonstantin Varlamov const std::array expected_positive = {1, 3, 9};
237065202f3SKonstantin Varlamov
238065202f3SKonstantin Varlamov { // (iterator, sentinel) overload.
239065202f3SKonstantin Varlamov {
240065202f3SKonstantin Varlamov std::array<int, 3> out1, out2;
241065202f3SKonstantin Varlamov std::ranges::partition_copy(in.begin(), in.end(), out1.begin(), out2.begin(), is_negative);
242065202f3SKonstantin Varlamov assert(out1 == expected_negative);
243065202f3SKonstantin Varlamov assert(out2 == expected_positive);
244065202f3SKonstantin Varlamov }
245065202f3SKonstantin Varlamov {
246065202f3SKonstantin Varlamov std::array<int, 3> out1, out2;
247065202f3SKonstantin Varlamov std::ranges::partition_copy(in.begin(), in.end(), out1.begin(), out2.begin(), is_negative, negate);
248065202f3SKonstantin Varlamov assert(out1 == expected_positive);
249065202f3SKonstantin Varlamov assert(out2 == expected_negative);
250065202f3SKonstantin Varlamov }
251065202f3SKonstantin Varlamov }
252065202f3SKonstantin Varlamov
253065202f3SKonstantin Varlamov { // (range) overload.
254065202f3SKonstantin Varlamov {
255065202f3SKonstantin Varlamov std::array<int, 3> out1, out2;
256065202f3SKonstantin Varlamov std::ranges::partition_copy(in, out1.begin(), out2.begin(), is_negative);
257065202f3SKonstantin Varlamov assert(out1 == expected_negative);
258065202f3SKonstantin Varlamov assert(out2 == expected_positive);
259065202f3SKonstantin Varlamov }
260065202f3SKonstantin Varlamov {
261065202f3SKonstantin Varlamov std::array<int, 3> out1, out2;
262065202f3SKonstantin Varlamov std::ranges::partition_copy(in, out1.begin(), out2.begin(), is_negative, negate);
263065202f3SKonstantin Varlamov assert(out1 == expected_positive);
264065202f3SKonstantin Varlamov assert(out2 == expected_negative);
265065202f3SKonstantin Varlamov }
266065202f3SKonstantin Varlamov }
267065202f3SKonstantin Varlamov }
268065202f3SKonstantin Varlamov
269065202f3SKonstantin Varlamov { // Complexity: Exactly `last - first` applications of `pred` and `proj`.
270065202f3SKonstantin Varlamov {
271065202f3SKonstantin Varlamov const std::array in = {-2, -5, -8, -11, -10, -5, 1, 3, 9, 6, 8, 2, 4, 2};
272065202f3SKonstantin Varlamov auto is_negative = [](int x) { return x < 0; };
273065202f3SKonstantin Varlamov std::array<int, 6> out1;
274065202f3SKonstantin Varlamov std::array<int, 8> out2;
275065202f3SKonstantin Varlamov
276065202f3SKonstantin Varlamov int pred_count = 0, proj_count = 0;
277065202f3SKonstantin Varlamov counting_predicate pred(is_negative, pred_count);
278065202f3SKonstantin Varlamov counting_projection proj(proj_count);
279065202f3SKonstantin Varlamov auto expected = static_cast<int>(in.size());
280065202f3SKonstantin Varlamov
281065202f3SKonstantin Varlamov {
282065202f3SKonstantin Varlamov std::ranges::partition_copy(in.begin(), in.end(), out1.begin(), out2.begin(), pred, proj);
283065202f3SKonstantin Varlamov assert(pred_count == expected);
284065202f3SKonstantin Varlamov assert(proj_count == expected);
285065202f3SKonstantin Varlamov pred_count = proj_count = 0;
286065202f3SKonstantin Varlamov }
287065202f3SKonstantin Varlamov
288065202f3SKonstantin Varlamov {
289065202f3SKonstantin Varlamov std::ranges::partition_copy(in, out1.begin(), out2.begin(), pred, proj);
290065202f3SKonstantin Varlamov assert(pred_count == expected);
291065202f3SKonstantin Varlamov assert(proj_count == expected);
292065202f3SKonstantin Varlamov pred_count = proj_count = 0;
293065202f3SKonstantin Varlamov }
294065202f3SKonstantin Varlamov }
295065202f3SKonstantin Varlamov }
29673ebcabfSKonstantin Varlamov
29773ebcabfSKonstantin Varlamov return true;
29873ebcabfSKonstantin Varlamov }
29973ebcabfSKonstantin Varlamov
main(int,char **)30073ebcabfSKonstantin Varlamov int main(int, char**) {
30173ebcabfSKonstantin Varlamov test();
30273ebcabfSKonstantin Varlamov static_assert(test());
30373ebcabfSKonstantin Varlamov
30473ebcabfSKonstantin Varlamov return 0;
30573ebcabfSKonstantin Varlamov }
306