11306b102SNikolas Klauser //===----------------------------------------------------------------------===// 21306b102SNikolas Klauser // 31306b102SNikolas Klauser // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 41306b102SNikolas Klauser // See https://llvm.org/LICENSE.txt for license information. 51306b102SNikolas Klauser // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 61306b102SNikolas Klauser // 71306b102SNikolas Klauser //===----------------------------------------------------------------------===// 81306b102SNikolas Klauser 91306b102SNikolas Klauser // <algorithm> 101306b102SNikolas Klauser 111306b102SNikolas Klauser // UNSUPPORTED: c++03, c++11, c++14, c++17 121306b102SNikolas Klauser 13a9138cdbSNikolas Klauser // ADDITIONAL_COMPILE_FLAGS(has-fconstexpr-steps): -fconstexpr-steps=20000000 1407b18c5eSNikolas Klauser // ADDITIONAL_COMPILE_FLAGS(has-fconstexpr-ops-limit): -fconstexpr-ops-limit=80000000 15a9138cdbSNikolas Klauser 161306b102SNikolas Klauser // template<input_iterator I, sentinel_for<I> S, class T, class Proj = identity> 171306b102SNikolas Klauser // requires indirect_binary_predicate<ranges::equal_to, projected<I, Proj>, const T*> 181306b102SNikolas Klauser // constexpr iter_difference_t<I> 191306b102SNikolas Klauser // ranges::count(I first, S last, const T& value, Proj proj = {}); 201306b102SNikolas Klauser // template<input_range R, class T, class Proj = identity> 211306b102SNikolas Klauser // requires indirect_binary_predicate<ranges::equal_to, projected<iterator_t<R>, Proj>, const T*> 221306b102SNikolas Klauser // constexpr range_difference_t<R> 231306b102SNikolas Klauser // ranges::count(R&& r, const T& value, Proj proj = {}); 241306b102SNikolas Klauser 251306b102SNikolas Klauser #include <algorithm> 261306b102SNikolas Klauser #include <array> 271306b102SNikolas Klauser #include <cassert> 28*e99c4906SNikolas Klauser #include <cstddef> 291306b102SNikolas Klauser #include <ranges> 30a9138cdbSNikolas Klauser #include <vector> 311306b102SNikolas Klauser 321306b102SNikolas Klauser #include "almost_satisfies_types.h" 331306b102SNikolas Klauser #include "test_iterators.h" 341306b102SNikolas Klauser 351306b102SNikolas Klauser struct NotEqualityComparable { 361306b102SNikolas Klauser bool operator==(NotEqualityComparable&&) const; 371306b102SNikolas Klauser bool operator==(NotEqualityComparable&) const; 381306b102SNikolas Klauser bool operator==(const NotEqualityComparable&&) const; 391306b102SNikolas Klauser }; 401306b102SNikolas Klauser 411306b102SNikolas Klauser template <class It, class Sent = It> 421306b102SNikolas Klauser concept HasCountIt = requires(It it, Sent sent) { std::ranges::count(it, sent, *it); }; 431306b102SNikolas Klauser static_assert(HasCountIt<int*>); 441306b102SNikolas Klauser static_assert(!HasCountIt<NotEqualityComparable*>); 451306b102SNikolas Klauser static_assert(!HasCountIt<InputIteratorNotDerivedFrom>); 461306b102SNikolas Klauser static_assert(!HasCountIt<InputIteratorNotIndirectlyReadable>); 471306b102SNikolas Klauser static_assert(!HasCountIt<InputIteratorNotInputOrOutputIterator>); 481306b102SNikolas Klauser static_assert(!HasCountIt<cpp20_input_iterator<int*>, SentinelForNotSemiregular>); 491306b102SNikolas Klauser static_assert(!HasCountIt<cpp20_input_iterator<int*>, InputRangeNotSentinelEqualityComparableWith>); 501306b102SNikolas Klauser 511306b102SNikolas Klauser static_assert(!HasCountIt<int*, int>); 521306b102SNikolas Klauser static_assert(!HasCountIt<int, int*>); 531306b102SNikolas Klauser 541306b102SNikolas Klauser template <class Range, class ValT> 551306b102SNikolas Klauser concept HasCountR = requires(Range r) { std::ranges::count(r, ValT{}); }; 561306b102SNikolas Klauser static_assert(HasCountR<std::array<int, 1>, int>); 571306b102SNikolas Klauser static_assert(!HasCountR<int, int>); 581306b102SNikolas Klauser static_assert(!HasCountR<std::array<NotEqualityComparable, 1>, NotEqualityComparable>); 591306b102SNikolas Klauser static_assert(!HasCountR<InputRangeNotDerivedFrom, int>); 601306b102SNikolas Klauser static_assert(!HasCountR<InputRangeNotIndirectlyReadable, int>); 611306b102SNikolas Klauser static_assert(!HasCountR<InputRangeNotInputOrOutputIterator, int>); 621306b102SNikolas Klauser static_assert(!HasCountR<InputRangeNotSentinelSemiregular, int>); 631306b102SNikolas Klauser static_assert(!HasCountR<InputRangeNotSentinelEqualityComparableWith, int>); 641306b102SNikolas Klauser 651306b102SNikolas Klauser template <class It, class Sent = It> 661306b102SNikolas Klauser constexpr void test_iterators() { 671306b102SNikolas Klauser { 681306b102SNikolas Klauser // simple test 691306b102SNikolas Klauser { 701306b102SNikolas Klauser int a[] = {1, 2, 3, 4}; 711306b102SNikolas Klauser std::same_as<std::ptrdiff_t> auto ret = std::ranges::count(It(a), Sent(It(a + 4)), 3); 721306b102SNikolas Klauser assert(ret == 1); 731306b102SNikolas Klauser } 741306b102SNikolas Klauser { 751306b102SNikolas Klauser int a[] = {1, 2, 3, 4}; 761306b102SNikolas Klauser auto range = std::ranges::subrange(It(a), Sent(It(a + 4))); 771306b102SNikolas Klauser std::same_as<std::ptrdiff_t> auto ret = std::ranges::count(range, 3); 781306b102SNikolas Klauser assert(ret == 1); 791306b102SNikolas Klauser } 801306b102SNikolas Klauser } 811306b102SNikolas Klauser 821306b102SNikolas Klauser { 831306b102SNikolas Klauser // check that an empty range works 841306b102SNikolas Klauser { 851306b102SNikolas Klauser std::array<int, 0> a = {}; 861306b102SNikolas Klauser auto ret = std::ranges::count(It(a.data()), Sent(It(a.data() + a.size())), 1); 871306b102SNikolas Klauser assert(ret == 0); 881306b102SNikolas Klauser } 891306b102SNikolas Klauser { 901306b102SNikolas Klauser std::array<int, 0> a = {}; 911306b102SNikolas Klauser auto range = std::ranges::subrange(It(a.data()), Sent(It(a.data() + a.size()))); 921306b102SNikolas Klauser auto ret = std::ranges::count(range, 1); 931306b102SNikolas Klauser assert(ret == 0); 941306b102SNikolas Klauser } 951306b102SNikolas Klauser } 961306b102SNikolas Klauser 971306b102SNikolas Klauser { 981306b102SNikolas Klauser // check that a range with a single element works 991306b102SNikolas Klauser { 1001306b102SNikolas Klauser std::array a = {2}; 1011306b102SNikolas Klauser auto ret = std::ranges::count(It(a.data()), Sent(It(a.data() + a.size())), 2); 1021306b102SNikolas Klauser assert(ret == 1); 1031306b102SNikolas Klauser } 1041306b102SNikolas Klauser { 1051306b102SNikolas Klauser std::array a = {2}; 1061306b102SNikolas Klauser auto range = std::ranges::subrange(It(a.data()), Sent(It(a.data() + a.size()))); 1071306b102SNikolas Klauser auto ret = std::ranges::count(range, 2); 1081306b102SNikolas Klauser assert(ret == 1); 1091306b102SNikolas Klauser } 1101306b102SNikolas Klauser } 1111306b102SNikolas Klauser 1121306b102SNikolas Klauser { 1131306b102SNikolas Klauser // check that 0 is returned with no match 1141306b102SNikolas Klauser { 1151306b102SNikolas Klauser std::array a = {1, 1, 1}; 1161306b102SNikolas Klauser auto ret = std::ranges::count(It(a.data()), Sent(It(a.data() + a.size())), 0); 1171306b102SNikolas Klauser assert(ret == 0); 1181306b102SNikolas Klauser } 1191306b102SNikolas Klauser { 1201306b102SNikolas Klauser std::array a = {1, 1, 1}; 1211306b102SNikolas Klauser auto range = std::ranges::subrange(It(a.data()), Sent(It(a.data() + a.size()))); 1221306b102SNikolas Klauser auto ret = std::ranges::count(range, 0); 1231306b102SNikolas Klauser assert(ret == 0); 1241306b102SNikolas Klauser } 1251306b102SNikolas Klauser } 1261306b102SNikolas Klauser 1271306b102SNikolas Klauser { 1281306b102SNikolas Klauser // check that more than one element is counted 1291306b102SNikolas Klauser { 1301306b102SNikolas Klauser std::array a = {3, 3, 4, 3, 3}; 1311306b102SNikolas Klauser auto ret = std::ranges::count(It(a.data()), Sent(It(a.data() + a.size())), 3); 1321306b102SNikolas Klauser assert(ret == 4); 1331306b102SNikolas Klauser } 1341306b102SNikolas Klauser { 1351306b102SNikolas Klauser std::array a = {3, 3, 4, 3, 3}; 1361306b102SNikolas Klauser auto range = std::ranges::subrange(It(a.data()), Sent(It(a.data() + a.size()))); 1371306b102SNikolas Klauser auto ret = std::ranges::count(range, 3); 1381306b102SNikolas Klauser assert(ret == 4); 1391306b102SNikolas Klauser } 1401306b102SNikolas Klauser } 1411306b102SNikolas Klauser 1421306b102SNikolas Klauser { 1431306b102SNikolas Klauser // check that all elements are counted 1441306b102SNikolas Klauser { 1451306b102SNikolas Klauser std::array a = {5, 5, 5, 5}; 1461306b102SNikolas Klauser auto ret = std::ranges::count(It(a.data()), Sent(It(a.data() + a.size())), 5); 1471306b102SNikolas Klauser assert(ret == 4); 1481306b102SNikolas Klauser } 1491306b102SNikolas Klauser { 1501306b102SNikolas Klauser std::array a = {5, 5, 5, 5}; 1511306b102SNikolas Klauser auto range = std::ranges::subrange(It(a.data()), Sent(It(a.data() + a.size()))); 1521306b102SNikolas Klauser auto ret = std::ranges::count(range, 5); 1531306b102SNikolas Klauser assert(ret == 4); 1541306b102SNikolas Klauser } 1551306b102SNikolas Klauser } 1561306b102SNikolas Klauser } 1571306b102SNikolas Klauser 1581306b102SNikolas Klauser constexpr bool test() { 1591306b102SNikolas Klauser test_iterators<int*>(); 1601306b102SNikolas Klauser test_iterators<const int*>(); 1611306b102SNikolas Klauser test_iterators<cpp20_input_iterator<int*>, sentinel_wrapper<cpp20_input_iterator<int*>>>(); 1621306b102SNikolas Klauser test_iterators<bidirectional_iterator<int*>>(); 1631306b102SNikolas Klauser test_iterators<forward_iterator<int*>>(); 1641306b102SNikolas Klauser test_iterators<random_access_iterator<int*>>(); 1651306b102SNikolas Klauser test_iterators<contiguous_iterator<int*>>(); 1661306b102SNikolas Klauser 1671306b102SNikolas Klauser { 1681306b102SNikolas Klauser // check that projections are used properly and that they are called with the iterator directly 1691306b102SNikolas Klauser { 1701306b102SNikolas Klauser int a[] = {1, 2, 3, 4}; 1711306b102SNikolas Klauser auto ret = std::ranges::count(a, a + 4, a + 3, [](int& i) { return &i; }); 1721306b102SNikolas Klauser assert(ret == 1); 1731306b102SNikolas Klauser } 1741306b102SNikolas Klauser { 1751306b102SNikolas Klauser int a[] = {1, 2, 3, 4}; 1761306b102SNikolas Klauser auto ret = std::ranges::count(a, a + 3, [](int& i) { return &i; }); 1771306b102SNikolas Klauser assert(ret == 1); 1781306b102SNikolas Klauser } 1791306b102SNikolas Klauser } 1801306b102SNikolas Klauser 1811306b102SNikolas Klauser { 1821306b102SNikolas Klauser // check that std::invoke is used 1831306b102SNikolas Klauser struct S { int i; }; 1841306b102SNikolas Klauser S a[] = { S{1}, S{3}, S{2} }; 1851306b102SNikolas Klauser std::same_as<std::ptrdiff_t> auto ret = std::ranges::count(a, 4, &S::i); 1861306b102SNikolas Klauser assert(ret == 0); 1871306b102SNikolas Klauser } 1881306b102SNikolas Klauser 1891306b102SNikolas Klauser { 1901306b102SNikolas Klauser // count invocations of the projection 1911306b102SNikolas Klauser { 1921306b102SNikolas Klauser int a[] = {1, 2, 3, 4}; 1931306b102SNikolas Klauser int projection_count = 0; 1941306b102SNikolas Klauser auto ret = std::ranges::count(a, a + 4, 2, [&](int i) { ++projection_count; return i; }); 1951306b102SNikolas Klauser assert(ret == 1); 1961306b102SNikolas Klauser assert(projection_count == 4); 1971306b102SNikolas Klauser } 1981306b102SNikolas Klauser { 1991306b102SNikolas Klauser int a[] = {1, 2, 3, 4}; 2001306b102SNikolas Klauser int projection_count = 0; 2011306b102SNikolas Klauser auto ret = std::ranges::count(a, 2, [&](int i) { ++projection_count; return i; }); 2021306b102SNikolas Klauser assert(ret == 1); 2031306b102SNikolas Klauser assert(projection_count == 4); 2041306b102SNikolas Klauser } 2051306b102SNikolas Klauser } 2061306b102SNikolas Klauser 2071306b102SNikolas Klauser { 2081306b102SNikolas Klauser // check that an immobile type works 2091306b102SNikolas Klauser struct NonMovable { 2101306b102SNikolas Klauser NonMovable(const NonMovable&) = delete; 2111306b102SNikolas Klauser NonMovable(NonMovable&&) = delete; 2121306b102SNikolas Klauser constexpr NonMovable(int i_) : i(i_) {} 2131306b102SNikolas Klauser int i; 2141306b102SNikolas Klauser 2151306b102SNikolas Klauser bool operator==(const NonMovable&) const = default; 2161306b102SNikolas Klauser }; 2171306b102SNikolas Klauser { 2181306b102SNikolas Klauser NonMovable a[] = {9, 8, 4, 3}; 2191306b102SNikolas Klauser auto ret = std::ranges::count(a, a + 4, NonMovable(8)); 2201306b102SNikolas Klauser assert(ret == 1); 2211306b102SNikolas Klauser } 2221306b102SNikolas Klauser { 2231306b102SNikolas Klauser NonMovable a[] = {9, 8, 4, 3}; 2241306b102SNikolas Klauser auto ret = std::ranges::count(a, NonMovable(8)); 2251306b102SNikolas Klauser assert(ret == 1); 2261306b102SNikolas Klauser } 2271306b102SNikolas Klauser } 2281306b102SNikolas Klauser 2291306b102SNikolas Klauser { 2301306b102SNikolas Klauser // check that difference_type is used 2311306b102SNikolas Klauser struct DiffTypeIterator { 2321306b102SNikolas Klauser using difference_type = signed char; 2331306b102SNikolas Klauser using value_type = int; 2341306b102SNikolas Klauser 2351306b102SNikolas Klauser int* it = nullptr; 2361306b102SNikolas Klauser 2371306b102SNikolas Klauser constexpr DiffTypeIterator() = default; 2381306b102SNikolas Klauser constexpr DiffTypeIterator(int* i) : it(i) {} 2391306b102SNikolas Klauser 2401306b102SNikolas Klauser constexpr int& operator*() const { return *it; } 2411306b102SNikolas Klauser constexpr DiffTypeIterator& operator++() { ++it; return *this; } 2421306b102SNikolas Klauser constexpr void operator++(int) { ++it; } 2431306b102SNikolas Klauser 2441306b102SNikolas Klauser bool operator==(const DiffTypeIterator&) const = default; 2451306b102SNikolas Klauser }; 2461306b102SNikolas Klauser 2471306b102SNikolas Klauser { 2481306b102SNikolas Klauser int a[] = {5, 5, 4, 3, 2, 1}; 2491306b102SNikolas Klauser std::same_as<signed char> decltype(auto) ret = 2501306b102SNikolas Klauser std::ranges::count(DiffTypeIterator(a), DiffTypeIterator(a + 6), 4); 2511306b102SNikolas Klauser assert(ret == 1); 2521306b102SNikolas Klauser } 2531306b102SNikolas Klauser { 2541306b102SNikolas Klauser int a[] = {5, 5, 4, 3, 2, 1}; 2551306b102SNikolas Klauser auto range = std::ranges::subrange(DiffTypeIterator(a), DiffTypeIterator(a + 6)); 2561306b102SNikolas Klauser std::same_as<signed char> decltype(auto) ret = std::ranges::count(range, 4); 2571306b102SNikolas Klauser assert(ret == 1); 2581306b102SNikolas Klauser } 2591306b102SNikolas Klauser } 2601306b102SNikolas Klauser 261a9138cdbSNikolas Klauser { // check that __bit_iterator optimizations work as expected 262a9138cdbSNikolas Klauser std::vector<bool> vec(256 + 64); 263a9138cdbSNikolas Klauser for (ptrdiff_t i = 0; i != 256; ++i) { 264a9138cdbSNikolas Klauser for (size_t offset = 0; offset != 64; ++offset) { 265a9138cdbSNikolas Klauser std::fill(vec.begin(), vec.end(), false); 266a9138cdbSNikolas Klauser std::fill(vec.begin() + offset, vec.begin() + i + offset, true); 267a9138cdbSNikolas Klauser assert(std::ranges::count(vec.begin() + offset, vec.begin() + offset + 256, true) == i); 268a9138cdbSNikolas Klauser assert(std::ranges::count(vec.begin() + offset, vec.begin() + offset + 256, false) == 256 - i); 269a9138cdbSNikolas Klauser } 270a9138cdbSNikolas Klauser } 271a9138cdbSNikolas Klauser } 272a9138cdbSNikolas Klauser 2731306b102SNikolas Klauser return true; 2741306b102SNikolas Klauser } 2751306b102SNikolas Klauser 2761306b102SNikolas Klauser int main(int, char**) { 2771306b102SNikolas Klauser test(); 2781306b102SNikolas Klauser static_assert(test()); 2791306b102SNikolas Klauser 2801306b102SNikolas Klauser return 0; 2811306b102SNikolas Klauser } 282