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> 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 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 260 int main(int, char**) { 261 test(); 262 static_assert(test()); 263 264 return 0; 265 } 266