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 | |
13 | // template<input_iterator I, sentinel_for<I> S, class Proj = identity, |
14 | // indirect_unary_predicate<projected<I, Proj>> Pred> |
15 | // constexpr bool ranges::all_of(I first, S last, Pred pred, Proj proj = {}); |
16 | // template<input_range R, class Proj = identity, |
17 | // indirect_unary_predicate<projected<iterator_t<R>, Proj>> Pred> |
18 | // constexpr bool ranges::all_of(R&& r, Pred pred, Proj proj = {}); |
19 | |
20 | #include <algorithm> |
21 | #include <array> |
22 | #include <cassert> |
23 | #include <ranges> |
24 | |
25 | #include "almost_satisfies_types.h" |
26 | #include "test_iterators.h" |
27 | |
28 | struct UnaryFunctor { |
29 | bool operator()(auto&&); |
30 | }; |
31 | |
32 | template <class It, class Sent = sentinel_wrapper<It>> |
33 | concept HasAllOfIt = requires(It first, Sent last) { std::ranges::all_of(first, last, UnaryFunctor{}); }; |
34 | |
35 | static_assert(HasAllOfIt<int*>); |
36 | static_assert(!HasAllOfIt<InputIteratorNotDerivedFrom>); |
37 | static_assert(!HasAllOfIt<InputIteratorNotIndirectlyReadable>); |
38 | static_assert(!HasAllOfIt<InputIteratorNotInputOrOutputIterator>); |
39 | static_assert(!HasAllOfIt<int*, SentinelForNotSemiregular>); |
40 | static_assert(!HasAllOfIt<int*, SentinelForNotWeaklyEqualityComparableWith>); |
41 | |
42 | template <class Func> |
43 | concept HasAllOfItFunc = requires(int* ptr) { std::ranges::all_of(ptr, ptr, Func{}); }; |
44 | |
45 | static_assert(HasAllOfItFunc<UnaryFunctor>); |
46 | static_assert(!HasAllOfItFunc<IndirectUnaryPredicateNotCopyConstructible>); |
47 | static_assert(!HasAllOfItFunc<IndirectUnaryPredicateNotPredicate>); |
48 | |
49 | template <class Range> |
50 | concept HasAllOfR = requires(Range range) { std::ranges::all_of(range, UnaryFunctor{}); }; |
51 | |
52 | static_assert(HasAllOfR<std::array<int, 10>>); |
53 | static_assert(!HasAllOfR<InputRangeNotDerivedFrom>); |
54 | static_assert(!HasAllOfR<InputRangeNotIndirectlyReadable>); |
55 | static_assert(!HasAllOfR<InputRangeNotInputOrOutputIterator>); |
56 | static_assert(!HasAllOfR<InputRangeNotSentinelSemiregular>); |
57 | static_assert(!HasAllOfR<InputRangeNotSentinelEqualityComparableWith>); |
58 | |
59 | template <class Func> |
60 | concept HasAllOfRFunc = requires(std::array<int, 10> range) { std::ranges::all_of(range, Func{}); }; |
61 | |
62 | static_assert(HasAllOfRFunc<UnaryFunctor>); |
63 | static_assert(!HasAllOfRFunc<IndirectUnaryPredicateNotCopyConstructible>); |
64 | static_assert(!HasAllOfRFunc<IndirectUnaryPredicateNotPredicate>); |
65 | |
66 | template <class It, class Sent = It> |
67 | constexpr void test_iterators() { |
68 | { // simple test |
69 | { |
70 | int a[] = {1, 2, 3, 4}; |
71 | std::same_as<bool> decltype(auto) ret = std::ranges::all_of(It(a), Sent(It(a + 4)), [](int) { return true; }); |
72 | assert(ret); |
73 | } |
74 | { |
75 | int a[] = {1, 2, 3, 4}; |
76 | auto range = std::ranges::subrange(It(a), Sent(It(a + 4))); |
77 | std::same_as<bool> decltype(auto) ret = std::ranges::all_of(range, [](int) { return true; }); |
78 | assert(ret); |
79 | } |
80 | } |
81 | |
82 | { // check that an empty range works |
83 | std::array<int, 0> a; |
84 | assert(std::ranges::all_of(It(a.data()), Sent(It(a.data())), [](int) { return false; })); |
85 | auto range = std::ranges::subrange(It(a.data()), Sent(It(a.data()))); |
86 | assert(std::ranges::all_of(range, [](int) { return false; })); |
87 | } |
88 | |
89 | { // check that the complexity requirements are met |
90 | { |
91 | int predicateCount = 0; |
92 | int projectionCount = 0; |
93 | auto pred = [&](int) { ++predicateCount; return true; }; |
94 | auto proj = [&](int i) { ++projectionCount; return i; }; |
95 | std::array a = {9, 7, 5, 3}; |
96 | assert(std::ranges::all_of(It(a.data()), Sent(It(a.data() + a.size())), pred, proj)); |
97 | assert(predicateCount == 4); |
98 | assert(projectionCount == 4); |
99 | } |
100 | { |
101 | int predicateCount = 0; |
102 | int projectionCount = 0; |
103 | auto pred = [&](int) { ++predicateCount; return true; }; |
104 | auto proj = [&](int i) { ++projectionCount; return i; }; |
105 | std::array a = {9, 7, 5, 3}; |
106 | auto range = std::ranges::subrange(It(a.data()), Sent(It(a.data() + a.size()))); |
107 | assert(std::ranges::all_of(range, pred, proj)); |
108 | assert(predicateCount == 4); |
109 | assert(projectionCount == 4); |
110 | } |
111 | } |
112 | |
113 | { // check that false is returned if no element satisfies the condition |
114 | std::array a = {1, 2, 3, 4}; |
115 | assert(!std::ranges::all_of(It(a.data()), Sent(It(a.data() + a.size())), [](int i) { return i > 5; })); |
116 | auto range = std::ranges::subrange(It(a.data()), Sent(It(a.data() + a.size()))); |
117 | assert(!std::ranges::all_of(range, [](int i) { return i > 5; })); |
118 | } |
119 | |
120 | { // check that true is returned if all elements satisfy the condition |
121 | std::array a = {1, 2, 3, 4}; |
122 | assert(std::ranges::all_of(It(a.data()), Sent(It(a.data() + a.size())), [](int i) { return i < 5; })); |
123 | auto range = std::ranges::subrange(It(a.data()), Sent(It(a.data() + a.size()))); |
124 | assert(std::ranges::all_of(range, [](int i) { return i < 5; })); |
125 | } |
126 | |
127 | { // check that false is returned if ony one elements satisfies the condition |
128 | std::array a = {1, 2, 3, 4, 6}; |
129 | assert(!std::ranges::all_of(It(a.data()), Sent(It(a.data() + a.size())), [](int i) { return i > 5; })); |
130 | auto range = std::ranges::subrange(It(a.data()), Sent(It(a.data() + a.size()))); |
131 | assert(!std::ranges::all_of(range, [](int i) { return i > 5; })); |
132 | } |
133 | } |
134 | |
135 | constexpr bool test() { |
136 | test_iterators<cpp20_input_iterator<int*>, sentinel_wrapper<cpp20_input_iterator<int*>>>(); |
137 | test_iterators<forward_iterator<int*>>(); |
138 | test_iterators<bidirectional_iterator<int*>>(); |
139 | test_iterators<random_access_iterator<int*>>(); |
140 | test_iterators<contiguous_iterator<int*>>(); |
141 | test_iterators<int*>(); |
142 | |
143 | { // check that std::invoke is used |
144 | struct S { int check; int other; }; |
145 | S a[] = {{.check: 1, .other: 2}, {.check: 1, .other: 7}, {.check: 1, .other: 3}}; |
146 | assert(std::ranges::all_of(a, a + 3, [](int i) { return i == 1; }, &S::check)); |
147 | assert(std::ranges::all_of(a, [](int i) { return i == 1; }, &S::check)); |
148 | } |
149 | |
150 | return true; |
151 | } |
152 | |
153 | int main(int, char**) { |
154 | test(); |
155 | static_assert(test()); |
156 | |
157 | return 0; |
158 | } |
159 | |