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 // <algorithm>
10
11 // UNSUPPORTED: c++03, c++11, c++14, c++17
12 // UNSUPPORTED: libcpp-has-no-incomplete-ranges
13
14 // template<input_iterator I, sentinel_for<I> S, class T, class Proj = identity>
15 // requires indirect_binary_predicate<ranges::equal_to, projected<I, Proj>, const T*>
16 // constexpr iter_difference_t<I>
17 // ranges::count(I first, S last, const T& value, Proj proj = {});
18 // template<input_range R, class T, class Proj = identity>
19 // requires indirect_binary_predicate<ranges::equal_to, projected<iterator_t<R>, Proj>, const T*>
20 // constexpr range_difference_t<R>
21 // ranges::count(R&& r, const T& value, Proj proj = {});
22
23 #include <algorithm>
24 #include <array>
25 #include <cassert>
26 #include <ranges>
27
28 #include "almost_satisfies_types.h"
29 #include "test_iterators.h"
30
31 struct NotEqualityComparable {
32 bool operator==(NotEqualityComparable&&) const;
33 bool operator==(NotEqualityComparable&) const;
34 bool operator==(const NotEqualityComparable&&) const;
35 };
36
37 template <class It, class Sent = It>
38 concept HasCountIt = requires(It it, Sent sent) { std::ranges::count(it, sent, *it); };
39 static_assert(HasCountIt<int*>);
40 static_assert(!HasCountIt<NotEqualityComparable*>);
41 static_assert(!HasCountIt<InputIteratorNotDerivedFrom>);
42 static_assert(!HasCountIt<InputIteratorNotIndirectlyReadable>);
43 static_assert(!HasCountIt<InputIteratorNotInputOrOutputIterator>);
44 static_assert(!HasCountIt<cpp20_input_iterator<int*>, SentinelForNotSemiregular>);
45 static_assert(!HasCountIt<cpp20_input_iterator<int*>, InputRangeNotSentinelEqualityComparableWith>);
46
47 static_assert(!HasCountIt<int*, int>);
48 static_assert(!HasCountIt<int, int*>);
49
50 template <class Range, class ValT>
51 concept HasCountR = requires(Range r) { std::ranges::count(r, ValT{}); };
52 static_assert(HasCountR<std::array<int, 1>, int>);
53 static_assert(!HasCountR<int, int>);
54 static_assert(!HasCountR<std::array<NotEqualityComparable, 1>, NotEqualityComparable>);
55 static_assert(!HasCountR<InputRangeNotDerivedFrom, int>);
56 static_assert(!HasCountR<InputRangeNotIndirectlyReadable, int>);
57 static_assert(!HasCountR<InputRangeNotInputOrOutputIterator, int>);
58 static_assert(!HasCountR<InputRangeNotSentinelSemiregular, int>);
59 static_assert(!HasCountR<InputRangeNotSentinelEqualityComparableWith, int>);
60
61 template <class It, class Sent = It>
test_iterators()62 constexpr void test_iterators() {
63 {
64 // simple test
65 {
66 int a[] = {1, 2, 3, 4};
67 std::same_as<std::ptrdiff_t> auto ret = std::ranges::count(It(a), Sent(It(a + 4)), 3);
68 assert(ret == 1);
69 }
70 {
71 int a[] = {1, 2, 3, 4};
72 auto range = std::ranges::subrange(It(a), Sent(It(a + 4)));
73 std::same_as<std::ptrdiff_t> auto ret = std::ranges::count(range, 3);
74 assert(ret == 1);
75 }
76 }
77
78 {
79 // check that an empty range works
80 {
81 std::array<int, 0> a = {};
82 auto ret = std::ranges::count(It(a.data()), Sent(It(a.data() + a.size())), 1);
83 assert(ret == 0);
84 }
85 {
86 std::array<int, 0> a = {};
87 auto range = std::ranges::subrange(It(a.data()), Sent(It(a.data() + a.size())));
88 auto ret = std::ranges::count(range, 1);
89 assert(ret == 0);
90 }
91 }
92
93 {
94 // check that a range with a single element works
95 {
96 std::array a = {2};
97 auto ret = std::ranges::count(It(a.data()), Sent(It(a.data() + a.size())), 2);
98 assert(ret == 1);
99 }
100 {
101 std::array a = {2};
102 auto range = std::ranges::subrange(It(a.data()), Sent(It(a.data() + a.size())));
103 auto ret = std::ranges::count(range, 2);
104 assert(ret == 1);
105 }
106 }
107
108 {
109 // check that 0 is returned with no match
110 {
111 std::array a = {1, 1, 1};
112 auto ret = std::ranges::count(It(a.data()), Sent(It(a.data() + a.size())), 0);
113 assert(ret == 0);
114 }
115 {
116 std::array a = {1, 1, 1};
117 auto range = std::ranges::subrange(It(a.data()), Sent(It(a.data() + a.size())));
118 auto ret = std::ranges::count(range, 0);
119 assert(ret == 0);
120 }
121 }
122
123 {
124 // check that more than one element is counted
125 {
126 std::array a = {3, 3, 4, 3, 3};
127 auto ret = std::ranges::count(It(a.data()), Sent(It(a.data() + a.size())), 3);
128 assert(ret == 4);
129 }
130 {
131 std::array a = {3, 3, 4, 3, 3};
132 auto range = std::ranges::subrange(It(a.data()), Sent(It(a.data() + a.size())));
133 auto ret = std::ranges::count(range, 3);
134 assert(ret == 4);
135 }
136 }
137
138 {
139 // check that all elements are counted
140 {
141 std::array a = {5, 5, 5, 5};
142 auto ret = std::ranges::count(It(a.data()), Sent(It(a.data() + a.size())), 5);
143 assert(ret == 4);
144 }
145 {
146 std::array a = {5, 5, 5, 5};
147 auto range = std::ranges::subrange(It(a.data()), Sent(It(a.data() + a.size())));
148 auto ret = std::ranges::count(range, 5);
149 assert(ret == 4);
150 }
151 }
152 }
153
test()154 constexpr bool test() {
155 test_iterators<int*>();
156 test_iterators<const int*>();
157 test_iterators<cpp20_input_iterator<int*>, sentinel_wrapper<cpp20_input_iterator<int*>>>();
158 test_iterators<bidirectional_iterator<int*>>();
159 test_iterators<forward_iterator<int*>>();
160 test_iterators<random_access_iterator<int*>>();
161 test_iterators<contiguous_iterator<int*>>();
162
163 {
164 // check that projections are used properly and that they are called with the iterator directly
165 {
166 int a[] = {1, 2, 3, 4};
167 auto ret = std::ranges::count(a, a + 4, a + 3, [](int& i) { return &i; });
168 assert(ret == 1);
169 }
170 {
171 int a[] = {1, 2, 3, 4};
172 auto ret = std::ranges::count(a, a + 3, [](int& i) { return &i; });
173 assert(ret == 1);
174 }
175 }
176
177 {
178 // check that std::invoke is used
179 struct S { int i; };
180 S a[] = { S{1}, S{3}, S{2} };
181 std::same_as<std::ptrdiff_t> auto ret = std::ranges::count(a, 4, &S::i);
182 assert(ret == 0);
183 }
184
185 {
186 // count invocations of the projection
187 {
188 int a[] = {1, 2, 3, 4};
189 int projection_count = 0;
190 auto ret = std::ranges::count(a, a + 4, 2, [&](int i) { ++projection_count; return i; });
191 assert(ret == 1);
192 assert(projection_count == 4);
193 }
194 {
195 int a[] = {1, 2, 3, 4};
196 int projection_count = 0;
197 auto ret = std::ranges::count(a, 2, [&](int i) { ++projection_count; return i; });
198 assert(ret == 1);
199 assert(projection_count == 4);
200 }
201 }
202
203 {
204 // check that an immobile type works
205 struct NonMovable {
206 NonMovable(const NonMovable&) = delete;
207 NonMovable(NonMovable&&) = delete;
208 constexpr NonMovable(int i_) : i(i_) {}
209 int i;
210
211 bool operator==(const NonMovable&) const = default;
212 };
213 {
214 NonMovable a[] = {9, 8, 4, 3};
215 auto ret = std::ranges::count(a, a + 4, NonMovable(8));
216 assert(ret == 1);
217 }
218 {
219 NonMovable a[] = {9, 8, 4, 3};
220 auto ret = std::ranges::count(a, NonMovable(8));
221 assert(ret == 1);
222 }
223 }
224
225 {
226 // check that difference_type is used
227 struct DiffTypeIterator {
228 using difference_type = signed char;
229 using value_type = int;
230
231 int* it = nullptr;
232
233 constexpr DiffTypeIterator() = default;
234 constexpr DiffTypeIterator(int* i) : it(i) {}
235
236 constexpr int& operator*() const { return *it; }
237 constexpr DiffTypeIterator& operator++() { ++it; return *this; }
238 constexpr void operator++(int) { ++it; }
239
240 bool operator==(const DiffTypeIterator&) const = default;
241 };
242
243 {
244 int a[] = {5, 5, 4, 3, 2, 1};
245 std::same_as<signed char> decltype(auto) ret =
246 std::ranges::count(DiffTypeIterator(a), DiffTypeIterator(a + 6), 4);
247 assert(ret == 1);
248 }
249 {
250 int a[] = {5, 5, 4, 3, 2, 1};
251 auto range = std::ranges::subrange(DiffTypeIterator(a), DiffTypeIterator(a + 6));
252 std::same_as<signed char> decltype(auto) ret = std::ranges::count(range, 4);
253 assert(ret == 1);
254 }
255 }
256
257 return true;
258 }
259
main(int,char **)260 int main(int, char**) {
261 test();
262 static_assert(test());
263
264 return 0;
265 }
266