Revert "[libc] Use best-fit binary trie to make malloc logarithmic" (#117065)
[llvm-project.git] / libcxx / test / std / algorithms / alg.nonmodifying / alg.count / ranges.count_if.pass.cpp
blobdf346186cfad881515c8a2d9a2c4b74ac3ce7275
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, class Proj = identity,
14 // indirect_unary_predicate<projected<I, Proj>> Pred>
15 // constexpr iter_difference_t<I>
16 // ranges::count_if(I first, S last, Pred pred, Proj proj = {});
17 // template<input_range R, class Proj = identity,
18 // indirect_unary_predicate<projected<iterator_t<R>, Proj>> Pred>
19 // constexpr range_difference_t<R>
20 // ranges::count_if(R&& r, Pred pred, Proj proj = {});
22 #include <algorithm>
23 #include <array>
24 #include <cassert>
25 #include <ranges>
27 #include "almost_satisfies_types.h"
28 #include "test_iterators.h"
30 struct Predicate {
31 bool operator()(int);
34 template <class It, class Sent = It>
35 concept HasCountIfIt = requires(It it, Sent sent) { std::ranges::count_if(it, sent, Predicate{}); };
36 static_assert(HasCountIfIt<int*>);
37 static_assert(!HasCountIfIt<InputIteratorNotDerivedFrom>);
38 static_assert(!HasCountIfIt<InputIteratorNotIndirectlyReadable>);
39 static_assert(!HasCountIfIt<InputIteratorNotInputOrOutputIterator>);
40 static_assert(!HasCountIfIt<cpp20_input_iterator<int*>, SentinelForNotSemiregular>);
41 static_assert(!HasCountIfIt<cpp20_input_iterator<int*>, InputRangeNotSentinelEqualityComparableWith>);
43 static_assert(!HasCountIfIt<int*, int>);
44 static_assert(!HasCountIfIt<int, int*>);
46 template <class Pred>
47 concept HasCountIfPred = requires(int* it, Pred pred) {std::ranges::count_if(it, it, pred); };
49 static_assert(!HasCountIfPred<IndirectUnaryPredicateNotCopyConstructible>);
50 static_assert(!HasCountIfPred<IndirectUnaryPredicateNotPredicate>);
52 template <class R>
53 concept HasCountIfR = requires(R r) { std::ranges::count_if(r, Predicate{}); };
54 static_assert(HasCountIfR<std::array<int, 0>>);
55 static_assert(!HasCountIfR<int>);
56 static_assert(!HasCountIfR<InputRangeNotDerivedFrom>);
57 static_assert(!HasCountIfR<InputRangeNotIndirectlyReadable>);
58 static_assert(!HasCountIfR<InputRangeNotInputOrOutputIterator>);
59 static_assert(!HasCountIfR<InputRangeNotSentinelSemiregular>);
60 static_assert(!HasCountIfR<InputRangeNotSentinelEqualityComparableWith>);
62 template <class It, class Sent = It>
63 constexpr void test_iterators() {
65 // simple test
67 int a[] = {1, 2, 3, 4};
68 std::same_as<std::ptrdiff_t> auto ret =
69 std::ranges::count_if(It(a), Sent(It(a + 4)), [](int x) { return x == 4; });
70 assert(ret == 1);
73 int a[] = {1, 2, 3, 4};
74 auto range = std::ranges::subrange(It(a), Sent(It(a + 4)));
75 std::same_as<std::ptrdiff_t> auto ret =
76 std::ranges::count_if(range, [](int x) { return x == 4; });
77 assert(ret == 1);
82 // check that an empty range works
84 std::array<int, 0> a = {};
85 auto ret = std::ranges::count_if(It(a.data()), Sent(It(a.data() + a.size())), [](int) { return true; });
86 assert(ret == 0);
89 std::array<int, 0> a = {};
90 auto range = std::ranges::subrange(It(a.data()), Sent(It(a.data() + a.size())));
91 auto ret = std::ranges::count_if(range, [](int) { return true; });
92 assert(ret == 0);
97 // check that a range with a single element works
99 std::array a = {2};
100 auto ret = std::ranges::count_if(It(a.data()), Sent(It(a.data() + a.size())), [](int i) { return i == 2; });
101 assert(ret == 1);
104 std::array a = {2};
105 auto range = std::ranges::subrange(It(a.data()), Sent(It(a.data() + a.size())));
106 auto ret = std::ranges::count_if(range, [](int i) { return i == 2; });
107 assert(ret == 1);
112 // check that 0 is returned with no match
114 int a[] = {1, 1, 1};
115 auto ret = std::ranges::count_if(It(a), Sent(It(a + 3)), [](int) { return false; });
116 assert(ret == 0);
119 int a[] = {1, 1, 1};
120 auto range = std::ranges::subrange(It(a), Sent(It(a + 3)));
121 auto ret = std::ranges::count_if(range, [](int){ return false; });
122 assert(ret == 0);
127 // check that more than one element is counted
129 std::array a = {3, 3, 4, 3, 3};
130 auto ret = std::ranges::count_if(It(a.data()), Sent(It(a.data() + a.size())), [](int i) { return i == 3; });
131 assert(ret == 4);
134 std::array a = {3, 3, 4, 3, 3};
135 auto range = std::ranges::subrange(It(a.data()), Sent(It(a.data() + a.size())));
136 auto ret = std::ranges::count_if(range, [](int i) { return i == 3; });
137 assert(ret == 4);
142 // check that all elements are counted
144 std::array a = {5, 5, 5, 5};
145 auto ret = std::ranges::count_if(It(a.data()), Sent(It(a.data() + a.size())), [](int) { return true; });
146 assert(ret == 4);
149 std::array a = {5, 5, 5, 5};
150 auto range = std::ranges::subrange(It(a.data()), Sent(It(a.data() + a.size())));
151 auto ret = std::ranges::count_if(range, [](int) { return true; });
152 assert(ret == 4);
157 constexpr bool test() {
158 test_iterators<int*>();
159 test_iterators<const int*>();
160 test_iterators<cpp20_input_iterator<int*>, sentinel_wrapper<cpp20_input_iterator<int*>>>();
161 test_iterators<bidirectional_iterator<int*>>();
162 test_iterators<forward_iterator<int*>>();
163 test_iterators<random_access_iterator<int*>>();
164 test_iterators<contiguous_iterator<int*>>();
167 // check that projections are used properly and that they are called with the iterator directly
169 int a[] = {1, 2, 3, 4};
170 auto ret = std::ranges::count_if(a, a + 4, [&](int* i) { return i == a + 3; }, [](int& i) { return &i; });
171 assert(ret == 1);
174 int a[] = {1, 2, 3, 4};
175 auto ret = std::ranges::count_if(a, [&](int* i) { return i == a + 3; }, [](int& i) { return &i; });
176 assert(ret == 1);
181 // check that std::invoke is used
183 struct S {
184 int comp;
185 int other;
187 S a[] = { {0, 0}, {0, 2}, {0, 1} };
188 auto ret = std::ranges::count_if(a, [](int i){ return i == 0; }, &S::comp);
189 assert(ret == 3);
192 struct S {
193 int comp;
194 int other;
196 S a[] = { {0, 0}, {0, 2}, {0, 1} };
197 auto ret = std::ranges::count_if(a, a + 3, [](int i) { return i == 0; }, &S::comp);
198 assert(ret == 3);
203 // check projection and predicate invocation count
205 int a[] = {1, 2, 3, 4};
206 int predicate_count = 0;
207 int projection_count = 0;
208 auto ret = std::ranges::count_if(a, a + 4,
209 [&](int i) { ++predicate_count; return i == 2; },
210 [&](int i) { ++projection_count; return i; });
211 assert(ret == 1);
212 assert(predicate_count == 4);
213 assert(projection_count == 4);
216 int a[] = {1, 2, 3, 4};
217 int predicate_count = 0;
218 int projection_count = 0;
219 auto ret = std::ranges::count_if(a,
220 [&](int i) { ++predicate_count; return i == 2; },
221 [&](int i) { ++projection_count; return i; });
222 assert(ret == 1);
223 assert(predicate_count == 4);
224 assert(projection_count == 4);
229 // check that an immobile type works
230 struct NonMovable {
231 NonMovable(const NonMovable&) = delete;
232 NonMovable(NonMovable&&) = delete;
233 constexpr NonMovable(int i_) : i(i_) {}
234 int i;
236 bool operator==(const NonMovable&) const = default;
239 NonMovable a[] = {9, 8, 4, 3};
240 auto ret = std::ranges::count_if(a, a + 4, [](const NonMovable& i) { return i == NonMovable(8); });
241 assert(ret == 1);
244 NonMovable a[] = {9, 8, 4, 3};
245 auto ret = std::ranges::count_if(a, [](const NonMovable& i) { return i == NonMovable(8); });
246 assert(ret == 1);
251 // check that difference_type is used
252 struct DiffTypeIterator {
253 using difference_type = signed char;
254 using value_type = int;
256 int* it = nullptr;
258 constexpr DiffTypeIterator() = default;
259 constexpr DiffTypeIterator(int* i) : it(i) {}
261 constexpr int& operator*() const { return *it; }
262 constexpr DiffTypeIterator& operator++() { ++it; return *this; }
263 constexpr void operator++(int) { ++it; }
265 bool operator==(const DiffTypeIterator&) const = default;
269 int a[] = {5, 5, 4, 3, 2, 1};
270 std::same_as<signed char> auto ret =
271 std::ranges::count_if(DiffTypeIterator(a), DiffTypeIterator(a + 6), [](int& i) { return i == 4; });
272 assert(ret == 1);
275 int a[] = {5, 5, 4, 3, 2, 1};
276 auto range = std::ranges::subrange(DiffTypeIterator(a), DiffTypeIterator(a + 6));
277 std::same_as<signed char> auto ret = std::ranges::count_if(range, [](int& i) { return i == 4; });
278 assert(ret == 1);
283 // check that the predicate can take the argument by lvalue ref
285 int a[] = {9, 8, 4, 3};
286 auto ret = std::ranges::count_if(a, a + 4, [](int& i) { return i == 8; });
287 assert(ret == 1);
290 int a[] = {9, 8, 4, 3};
291 auto ret = std::ranges::count_if(a, [](int& i) { return i == 8; });
292 assert(ret == 1);
297 // check that the predicate isn't made const
298 struct MutablePredicate {
299 constexpr bool operator()(int i) & { return i == 8; }
300 constexpr bool operator()(int i) && { return i == 8; }
303 int a[] = {9, 8, 4, 3};
304 auto ret = std::ranges::count_if(a, a + 4, MutablePredicate{});
305 assert(ret == 1);
308 int a[] = {9, 8, 4, 3};
309 auto ret = std::ranges::count_if(a, MutablePredicate{});
310 assert(ret == 1);
314 return true;
317 int main(int, char**) {
318 test();
319 static_assert(test());
321 return 0;