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, class Proj = identity,
14// indirectly_unary_invocable<projected<I, Proj>> Fun>
15// constexpr ranges::for_each_n_result<I, Fun>
16// ranges::for_each_n(I first, iter_difference_t<I> n, Fun f, Proj proj = {});
17
18#include <algorithm>
19#include <array>
20#include <cassert>
21#include <deque>
22#include <iterator>
23#include <ranges>
24#include <ranges>
25#include <vector>
26
27#include "almost_satisfies_types.h"
28#include "test_iterators.h"
29
30struct Callable {
31 void operator()(int);
32};
33
34template <class Iter>
35concept HasForEachN = requires(Iter iter) { std::ranges::for_each_n(iter, 0, Callable{}); };
36
37static_assert(HasForEachN<int*>);
38static_assert(!HasForEachN<InputIteratorNotDerivedFrom>);
39static_assert(!HasForEachN<InputIteratorNotIndirectlyReadable>);
40static_assert(!HasForEachN<InputIteratorNotInputOrOutputIterator>);
41
42template <class Func>
43concept HasForEachItFunc = requires(int* a, int b, Func func) { std::ranges::for_each_n(a, b, func); };
44
45static_assert(HasForEachItFunc<Callable>);
46static_assert(!HasForEachItFunc<IndirectUnaryPredicateNotPredicate>);
47static_assert(!HasForEachItFunc<IndirectUnaryPredicateNotCopyConstructible>);
48
49template <class Iter>
50constexpr void test_iterator() {
51 { // simple test
52 auto func = [i = 0](int& a) mutable { a += i++; };
53 int a[] = {1, 6, 3, 4};
54 std::same_as<std::ranges::for_each_result<Iter, decltype(func)>> auto ret =
55 std::ranges::for_each_n(Iter(a), 4, func);
56 assert(a[0] == 1);
57 assert(a[1] == 7);
58 assert(a[2] == 5);
59 assert(a[3] == 7);
60 assert(base(ret.in) == a + 4);
61 int i = 0;
62 ret.fun(i);
63 assert(i == 4);
64 }
65
66 { // check that an empty range works
67 std::array<int, 0> a = {};
68 std::ranges::for_each_n(Iter(a.data()), 0, [](auto&) { assert(false); });
69 }
70}
71
72struct deque_test {
73 std::deque<int>* d_;
74 int* i_;
75
76 deque_test(std::deque<int>& d, int& i) : d_(&d), i_(&i) {}
77
78 void operator()(int& v) {
79 assert(&(*d_)[*i_] == &v);
80 ++*i_;
81 }
82};
83
84/*TEST_CONSTEXPR_CXX26*/
85void test_segmented_deque_iterator() { // TODO: Mark as TEST_CONSTEXPR_CXX26 once std::deque is constexpr
86 // check that segmented deque iterators work properly
87 int sizes[] = {0, 1, 2, 1023, 1024, 1025, 2047, 2048, 2049};
88 for (const int size : sizes) {
89 std::deque<int> d(size);
90 int index = 0;
91
92 std::ranges::for_each_n(d.begin(), d.size(), deque_test(d, index));
93 }
94}
95
96constexpr bool test() {
97 test_iterator<cpp17_input_iterator<int*>>();
98 test_iterator<cpp20_input_iterator<int*>>();
99 test_iterator<forward_iterator<int*>>();
100 test_iterator<bidirectional_iterator<int*>>();
101 test_iterator<random_access_iterator<int*>>();
102 test_iterator<contiguous_iterator<int*>>();
103 test_iterator<int*>();
104
105 { // check that std::invoke is used
106 struct S {
107 int check;
108 int other;
109 };
110
111 S a[] = {{.check: 1, .other: 2}, {.check: 3, .other: 4}, {.check: 5, .other: 6}};
112 std::ranges::for_each_n(a, 3, [](int& i) { i = 0; }, &S::check);
113 assert(a[0].check == 0);
114 assert(a[0].other == 2);
115 assert(a[1].check == 0);
116 assert(a[1].other == 4);
117 assert(a[2].check == 0);
118 assert(a[2].other == 6);
119 }
120
121 if (!TEST_IS_CONSTANT_EVALUATED) // TODO: Use TEST_STD_AT_LEAST_26_OR_RUNTIME_EVALUATED when std::deque is made constexpr
122 test_segmented_deque_iterator();
123
124 {
125 std::vector<std::vector<int>> vec = {{0}, {1, 2}, {3, 4, 5}, {6, 7, 8, 9}, {10}, {11, 12, 13}};
126 auto v = vec | std::views::join;
127 std::ranges::for_each_n(
128 v.begin(),
129 std::ranges::distance(v),
130 [i = 0](int x) mutable { assert(x == 2 * i++); },
131 [](int x) { return 2 * x; });
132 }
133
134 return true;
135}
136
137int main(int, char**) {
138 test();
139 static_assert(test());
140
141 return 0;
142}
143

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