[ORC-RT][LoongArch] Add initial support for loongarch64 in ELFNixPlatform (#123575)
[llvm-project.git] / libcxx / test / std / algorithms / alg.modifying.operations / alg.copy / ranges.copy_if.pass.cpp
blob64d8bf9b4f7e650c2ac408d6cbfd0fda3abc45c1
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 //===----------------------------------------------------------------------===//
9 // <algorithm>
11 // UNSUPPORTED: c++03, c++11, c++14, c++17
13 // template<input_iterator I, sentinel_for<I> S, weakly_incrementable O, class Proj = identity,
14 // indirect_unary_predicate<projected<I, Proj>> Pred>
15 // requires indirectly_copyable<I, O>
16 // constexpr ranges::copy_if_result<I, O>
17 // ranges::copy_if(I first, S last, O result, Pred pred, Proj proj = {});
18 // template<input_range R, weakly_incrementable O, class Proj = identity,
19 // indirect_unary_predicate<projected<iterator_t<R>, Proj>> Pred>
20 // requires indirectly_copyable<iterator_t<R>, O>
21 // constexpr ranges::copy_if_result<borrowed_iterator_t<R>, O>
22 // ranges::copy_if(R&& r, O result, Pred pred, Proj proj = {});
24 #include <algorithm>
25 #include <array>
26 #include <cassert>
27 #include <ranges>
29 #include "almost_satisfies_types.h"
30 #include "test_iterators.h"
32 struct Functor {
33 bool operator()(int);
36 template <class In, class Out = In, class Sent = sentinel_wrapper<In>, class Func = Functor>
37 concept HasCopyIfIt = requires(In first, Sent last, Out result) { std::ranges::copy_if(first, last, result, Func{}); };
39 static_assert(HasCopyIfIt<int*>);
40 static_assert(!HasCopyIfIt<InputIteratorNotDerivedFrom>);
41 static_assert(!HasCopyIfIt<InputIteratorNotIndirectlyReadable>);
42 static_assert(!HasCopyIfIt<InputIteratorNotInputOrOutputIterator>);
43 static_assert(!HasCopyIfIt<int*, WeaklyIncrementableNotMovable>);
44 struct NotIndirectlyCopyable {};
45 static_assert(!HasCopyIfIt<int*, NotIndirectlyCopyable*>);
46 static_assert(!HasCopyIfIt<int*, int*, SentinelForNotSemiregular>);
47 static_assert(!HasCopyIfIt<int*, int*, SentinelForNotWeaklyEqualityComparableWith>);
49 static_assert(!HasCopyIfIt<int*, int*, int*, IndirectUnaryPredicateNotCopyConstructible>);
50 static_assert(!HasCopyIfIt<int*, int*, int*, IndirectUnaryPredicateNotPredicate>);
52 template <class Range, class Out, class Func = Functor>
53 concept HasCopyIfR = requires(Range range, Out out) { std::ranges::copy_if(range, out, Func{}); };
55 static_assert(HasCopyIfR<std::array<int, 10>, int*>);
56 static_assert(!HasCopyIfR<InputRangeNotDerivedFrom, int*>);
57 static_assert(!HasCopyIfR<InputRangeNotIndirectlyReadable, int*>);
58 static_assert(!HasCopyIfR<InputRangeNotInputOrOutputIterator, int*>);
59 static_assert(!HasCopyIfR<WeaklyIncrementableNotMovable, int*>);
60 static_assert(!HasCopyIfR<UncheckedRange<NotIndirectlyCopyable*>, int*>);
61 static_assert(!HasCopyIfR<InputRangeNotSentinelSemiregular, int*>);
62 static_assert(!HasCopyIfR<InputRangeNotSentinelEqualityComparableWith, int*>);
64 static_assert(std::is_same_v<std::ranges::copy_if_result<int, long>, std::ranges::in_out_result<int, long>>);
66 template <class In, class Out, class Sent = In>
67 constexpr void test_iterators() {
68 { // simple test
70 std::array in = {1, 2, 3, 4};
71 std::array<int, 4> out;
72 std::same_as<std::ranges::copy_if_result<In, Out>> auto ret =
73 std::ranges::copy_if(In(in.data()),
74 Sent(In(in.data() + in.size())),
75 Out(out.data()),
76 [](int) { return true; });
77 assert(in == out);
78 assert(base(ret.in) == in.data() + in.size());
79 assert(base(ret.out) == out.data() + out.size());
82 std::array in = {1, 2, 3, 4};
83 std::array<int, 4> out;
84 auto range = std::ranges::subrange(In(in.data()), Sent(In(in.data() + in.size())));
85 std::same_as<std::ranges::copy_if_result<In, Out>> auto ret =
86 std::ranges::copy_if(range, Out(out.data()), [](int) { return true; });
87 assert(in == out);
88 assert(base(ret.in) == in.data() + in.size());
89 assert(base(ret.out) == out.data() + out.size());
93 { // check that an empty range works
95 std::array<int, 0> in;
96 std::array<int, 0> out;
97 auto ret = std::ranges::copy_if(In(in.data()), Sent(In(in.data())), Out(out.data()), [](int) { return true; });
98 assert(base(ret.in) == in.data());
99 assert(base(ret.out) == out.data());
102 std::array<int, 0> in;
103 std::array<int, 0> out;
104 auto range = std::ranges::subrange(In(in.data()), Sent(In(in.data())));
105 auto ret = std::ranges::copy_if(range, Out(out.data()), [](int) { return true; });
106 assert(base(ret.in) == in.data());
107 assert(base(ret.out) == out.data());
111 { // check that the predicate is used
113 std::array in = {4, 6, 87, 3, 88, 44, 45, 9};
114 std::array<int, 4> out;
115 auto ret = std::ranges::copy_if(In(in.data()),
116 Sent(In(in.data() + in.size())),
117 Out(out.data()),
118 [](int i) { return i % 2 == 0; });
119 assert((out == std::array{4, 6, 88, 44}));
120 assert(base(ret.in) == in.data() + in.size());
121 assert(base(ret.out) == out.data() + out.size());
124 std::array in = {4, 6, 87, 3, 88, 44, 45, 9};
125 std::array<int, 4> out;
126 auto range = std::ranges::subrange(In(in.data()), Sent(In(in.data() + in.size())));
127 auto ret = std::ranges::copy_if(range, Out(out.data()), [](int i) { return i % 2 == 0; });
128 assert((out == std::array{4, 6, 88, 44}));
129 assert(base(ret.in) == in.data() + in.size());
130 assert(base(ret.out) == out.data() + out.size());
135 template <class Out>
136 constexpr bool test_in_iterators() {
137 test_iterators<cpp17_input_iterator<int*>, Out, sentinel_wrapper<cpp17_input_iterator<int*>>>();
138 test_iterators<cpp20_input_iterator<int*>, Out, sentinel_wrapper<cpp20_input_iterator<int*>>>();
139 test_iterators<forward_iterator<int*>, Out>();
140 test_iterators<bidirectional_iterator<int*>, Out>();
141 test_iterators<random_access_iterator<int*>, Out>();
142 test_iterators<contiguous_iterator<int*>, Out>();
143 test_iterators<int*, Out>();
145 return true;
148 constexpr bool test() {
149 test_in_iterators<cpp17_output_iterator<int*>>();
150 test_in_iterators<cpp20_output_iterator<int*>>();
151 test_in_iterators<forward_iterator<int*>>();
152 test_in_iterators<bidirectional_iterator<int*>>();
153 test_in_iterators<random_access_iterator<int*>>();
154 test_in_iterators<contiguous_iterator<int*>>();
155 test_in_iterators<int*>();
157 { // check that std::invoke is used
159 struct S { int val; int other; };
160 std::array<S, 4> in = {{{4, 2}, {1, 3}, {3, 4}, {3, 5}}};
161 std::array<S, 2> out;
162 auto ret = std::ranges::copy_if(in.begin(), in.end(), out.begin(), [](int i) { return i == 3; }, &S::val);
163 assert(ret.in == in.end());
164 assert(ret.out == out.end());
165 assert(out[0].val == 3);
166 assert(out[0].other == 4);
167 assert(out[1].val == 3);
168 assert(out[1].other == 5);
171 struct S { int val; int other; };
172 std::array<S, 4> in = {{{4, 2}, {1, 3}, {3, 4}, {3, 5}}};
173 std::array<S, 2> out;
174 auto ret = std::ranges::copy_if(in, out.begin(), [](int i) { return i == 3; }, &S::val);
175 assert(ret.in == in.end());
176 assert(ret.out == out.end());
177 assert(out[0].val == 3);
178 assert(out[0].other == 4);
179 assert(out[1].val == 3);
180 assert(out[1].other == 5);
184 { // check that the complexity requirements are met
186 int predicateCount = 0;
187 int projectionCount = 0;
188 auto pred = [&](int i) { ++predicateCount; return i != 0; };
189 auto proj = [&](int i) { ++projectionCount; return i; };
191 int a[] = {5, 4, 3, 2, 1};
192 int b[5];
193 std::ranges::copy_if(a, a + 5, b, pred, proj);
194 assert(predicateCount == 5);
195 assert(projectionCount == 5);
198 int predicateCount = 0;
199 int projectionCount = 0;
200 auto pred = [&](int i) { ++predicateCount; return i != 0; };
201 auto proj = [&](int i) { ++projectionCount; return i; };
203 int a[] = {5, 4, 3, 2, 1};
204 int b[5];
205 std::ranges::copy_if(a, b, pred, proj);
206 assert(predicateCount == 5);
207 assert(projectionCount == 5);
211 { // test proxy iterator
213 std::array in = {4, 6, 87, 3, 88, 44, 45, 9};
214 std::array<int, 4> out;
216 ProxyRange proxyIn{in};
217 ProxyRange proxyOut{out};
219 std::ranges::copy_if(proxyIn.begin(), proxyIn.end(), proxyOut.begin(),
220 [](auto const& i) { return i.data % 2 == 0; });
221 assert((out == std::array{4, 6, 88, 44}));
224 std::array in = {4, 6, 87, 3, 88, 44, 45, 9};
225 std::array<int, 4> out;
227 ProxyRange proxyIn{in};
228 ProxyRange proxyOut{out};
230 std::ranges::copy_if(proxyIn, proxyOut.begin(), [](const auto& i) { return i.data % 2 == 0; });
231 assert((out == std::array{4, 6, 88, 44}));
235 return true;
238 int main(int, char**) {
239 test();
240 static_assert(test());
242 return 0;