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// UNSUPPORTED: c++03, c++11, c++14, c++17
11
12// template<input_iterator I, sentinel_for<I> S, class Proj = identity,
13// indirectly_unary_invocable<projected<I, Proj>> Fun>
14// constexpr ranges::for_each_result<I, Fun>
15// ranges::for_each(I first, S last, Fun f, Proj proj = {});
16// template<input_range R, class Proj = identity,
17// indirectly_unary_invocable<projected<iterator_t<R>, Proj>> Fun>
18// constexpr ranges::for_each_result<borrowed_iterator_t<R>, Fun>
19// ranges::for_each(R&& r, Fun f, Proj proj = {});
20
21#include <algorithm>
22#include <array>
23#include <cassert>
24#include <deque>
25#include <ranges>
26#include <vector>
27
28#include "almost_satisfies_types.h"
29#include "test_iterators.h"
30
31struct Callable {
32 void operator()(int);
33};
34
35template <class Iter, class Sent = Iter>
36concept HasForEachIt = requires(Iter iter, Sent sent) { std::ranges::for_each(iter, sent, Callable{}); };
37
38static_assert(HasForEachIt<int*>);
39static_assert(!HasForEachIt<InputIteratorNotDerivedFrom>);
40static_assert(!HasForEachIt<InputIteratorNotIndirectlyReadable>);
41static_assert(!HasForEachIt<InputIteratorNotInputOrOutputIterator>);
42static_assert(!HasForEachIt<int*, SentinelForNotSemiregular>);
43static_assert(!HasForEachIt<int*, SentinelForNotWeaklyEqualityComparableWith>);
44
45template <class Func>
46concept HasForEachItFunc = requires(int* a, int* b, Func func) { std::ranges::for_each(a, b, func); };
47
48static_assert(HasForEachItFunc<Callable>);
49static_assert(!HasForEachItFunc<IndirectUnaryPredicateNotPredicate>);
50static_assert(!HasForEachItFunc<IndirectUnaryPredicateNotCopyConstructible>);
51
52template <class Range>
53concept HasForEachR = requires(Range range) { std::ranges::for_each(range, Callable{}); };
54
55static_assert(HasForEachR<UncheckedRange<int*>>);
56static_assert(!HasForEachR<InputRangeNotDerivedFrom>);
57static_assert(!HasForEachR<InputRangeNotIndirectlyReadable>);
58static_assert(!HasForEachR<InputRangeNotInputOrOutputIterator>);
59static_assert(!HasForEachR<InputRangeNotSentinelSemiregular>);
60static_assert(!HasForEachR<InputRangeNotSentinelEqualityComparableWith>);
61
62template <class Func>
63concept HasForEachRFunc = requires(UncheckedRange<int*> a, Func func) { std::ranges::for_each(a, func); };
64
65static_assert(HasForEachRFunc<Callable>);
66static_assert(!HasForEachRFunc<IndirectUnaryPredicateNotPredicate>);
67static_assert(!HasForEachRFunc<IndirectUnaryPredicateNotCopyConstructible>);
68
69template <class Iter, class Sent = Iter>
70constexpr void test_iterator() {
71 { // simple test
72 {
73 auto func = [i = 0](int& a) mutable { a += i++; };
74 int a[] = {1, 6, 3, 4};
75 std::same_as<std::ranges::for_each_result<Iter, decltype(func)>> decltype(auto) ret =
76 std::ranges::for_each(Iter(a), Sent(Iter(a + 4)), func);
77 assert(a[0] == 1);
78 assert(a[1] == 7);
79 assert(a[2] == 5);
80 assert(a[3] == 7);
81 assert(base(ret.in) == a + 4);
82 int i = 0;
83 ret.fun(i);
84 assert(i == 4);
85 }
86 {
87 auto func = [i = 0](int& a) mutable { a += i++; };
88 int a[] = {1, 6, 3, 4};
89 auto range = std::ranges::subrange(Iter(a), Sent(Iter(a + 4)));
90 std::same_as<std::ranges::for_each_result<Iter, decltype(func)>> decltype(auto) ret =
91 std::ranges::for_each(range, func);
92 assert(a[0] == 1);
93 assert(a[1] == 7);
94 assert(a[2] == 5);
95 assert(a[3] == 7);
96 assert(base(ret.in) == a + 4);
97 int i = 0;
98 ret.fun(i);
99 assert(i == 4);
100 }
101 }
102
103 { // check that an empty range works
104 {
105 std::array<int, 0> a = {};
106 std::ranges::for_each(Iter(a.data()), Sent(Iter(a.data())), [](auto&) { assert(false); });
107 }
108 {
109 std::array<int, 0> a = {};
110 auto range = std::ranges::subrange(Iter(a.data()), Sent(Iter(a.data())));
111 std::ranges::for_each(range, [](auto&) { assert(false); });
112 }
113 }
114}
115
116struct deque_test {
117 std::deque<int>* d_;
118 int* i_;
119
120 deque_test(std::deque<int>& d, int& i) : d_(&d), i_(&i) {}
121
122 void operator()(int& v) {
123 assert(&(*d_)[*i_] == &v);
124 ++*i_;
125 }
126};
127
128/*TEST_CONSTEXPR_CXX26*/
129void test_segmented_deque_iterator() { // TODO: Mark as TEST_CONSTEXPR_CXX26 once std::deque is constexpr
130 // check that segmented deque iterators work properly
131 int sizes[] = {0, 1, 2, 1023, 1024, 1025, 2047, 2048, 2049};
132 for (const int size : sizes) {
133 std::deque<int> d(size);
134 int index = 0;
135
136 std::ranges::for_each(d, deque_test(d, index));
137 }
138}
139
140constexpr bool test() {
141 test_iterator<cpp17_input_iterator<int*>, sentinel_wrapper<cpp17_input_iterator<int*>>>();
142 test_iterator<cpp20_input_iterator<int*>, sentinel_wrapper<cpp20_input_iterator<int*>>>();
143 test_iterator<forward_iterator<int*>>();
144 test_iterator<bidirectional_iterator<int*>>();
145 test_iterator<random_access_iterator<int*>>();
146 test_iterator<contiguous_iterator<int*>>();
147 test_iterator<int*>();
148
149 { // check that std::invoke is used
150 struct S {
151 int check;
152 int other;
153 };
154 {
155 S a[] = {{.check: 1, .other: 2}, {.check: 3, .other: 4}, {.check: 5, .other: 6}};
156 std::ranges::for_each(a, a + 3, [](int& i) { i = 0; }, &S::check);
157 assert(a[0].check == 0);
158 assert(a[0].other == 2);
159 assert(a[1].check == 0);
160 assert(a[1].other == 4);
161 assert(a[2].check == 0);
162 assert(a[2].other == 6);
163 }
164 {
165 S a[] = {{.check: 1, .other: 2}, {.check: 3, .other: 4}, {.check: 5, .other: 6}};
166 std::ranges::for_each(a, [](int& i) { i = 0; }, &S::check);
167 assert(a[0].check == 0);
168 assert(a[0].other == 2);
169 assert(a[1].check == 0);
170 assert(a[1].other == 4);
171 assert(a[2].check == 0);
172 assert(a[2].other == 6);
173 }
174 }
175
176 if (!TEST_IS_CONSTANT_EVALUATED) // TODO: Use TEST_STD_AT_LEAST_26_OR_RUNTIME_EVALUATED when std::deque is made constexpr
177 test_segmented_deque_iterator();
178
179 {
180 std::vector<std::vector<int>> vec = {{0}, {1, 2}, {3, 4, 5}, {6, 7, 8, 9}, {10}, {11, 12, 13}};
181 auto v = vec | std::views::join;
182 std::ranges::for_each(v, [i = 0](int x) mutable { assert(x == 2 * i++); }, [](int x) { return 2 * x; });
183 }
184
185 return true;
186}
187
188int main(int, char**) {
189 test();
190 static_assert(test());
191
192 return 0;
193}
194

source code of libcxx/test/std/algorithms/alg.nonmodifying/alg.foreach/ranges.for_each.pass.cpp