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// template<class Iter, IntegralLike Size, class T>
12// requires OutputIterator<Iter, const T&>
13// constexpr OutputIterator // constexpr after C++17
14// fill_n(Iter first, Size n, const T& value);
15
16#include <algorithm>
17#include <array>
18#include <cassert>
19#include <cstddef>
20#include <vector>
21
22#include "sized_allocator.h"
23#include "test_macros.h"
24#include "test_iterators.h"
25#include "type_algorithms.h"
26#include "user_defined_integral.h"
27
28typedef UserDefinedIntegral<unsigned> UDI;
29
30template <class Iter, class Container>
31TEST_CONSTEXPR_CXX20 void
32test(Container in, size_t from, size_t n, typename Container::value_type value, Container expected) {
33 Iter it = std::fill_n(Iter(in.data() + from), UDI(n), value);
34 assert(base(it) == in.data() + from + n);
35 assert(in == expected);
36}
37
38template <class T>
39struct Test {
40 template <class Iter>
41 TEST_CONSTEXPR_CXX20 void operator()() {
42 {
43 std::array<T, 4> in = {1, 2, 3, 4};
44 std::array<T, 4> expected = {5, 5, 5, 5};
45 test<Iter>(in, 0, 4, 5, expected);
46 }
47 {
48 std::array<T, 4> in = {1, 2, 3, 4};
49 std::array<T, 4> expected = {1, 5, 5, 4};
50 test<Iter>(in, 1, 2, 5, expected);
51 }
52 }
53};
54
55struct source {
56 TEST_CONSTEXPR source() = default;
57 TEST_CONSTEXPR_CXX20 operator int() const { return 1; }
58};
59
60class CharWrapper {
61 char a_;
62
63public:
64 TEST_CONSTEXPR CharWrapper() : a_('a') {};
65 TEST_CONSTEXPR explicit CharWrapper(char a) : a_(a) {}
66 TEST_CONSTEXPR operator unsigned char() const { return 'b'; }
67
68 TEST_CONSTEXPR friend bool operator==(const CharWrapper& x, const CharWrapper& y) { return x.a_ == y.a_; }
69};
70
71struct CharTransformer {
72 TEST_CONSTEXPR CharTransformer() : c(0) {}
73 TEST_CONSTEXPR CharTransformer(char xc) : c(xc + 1) {}
74 char c;
75};
76
77struct CharUnionStorage {
78 union {
79 unsigned char a;
80 unsigned char b;
81 };
82};
83
84TEST_CONSTEXPR_CXX20 bool test_vector_bool(std::size_t N) {
85 { // Test cases validating leading/trailing bits unfilled remain unchanged
86 { // Leading bits are not filled
87 std::vector<bool> in(N, false);
88 std::vector<bool> expected(N, true);
89 expected[0] = expected[1] = false;
90 std::fill_n(first: in.begin() + 2, n: N - 2, value: true);
91 assert(in == expected);
92 }
93 { // Trailing bits are not filled
94 std::vector<bool> in(N, false);
95 std::vector<bool> expected(N, true);
96 expected[N - 1] = expected[N - 2] = false;
97 std::fill_n(first: in.begin(), n: N - 2, value: true);
98 assert(in == expected);
99 }
100 { // Leading and trailing bits are not filled
101 std::vector<bool> in(N, false);
102 std::vector<bool> expected(N, true);
103 expected[0] = expected[1] = expected[N - 1] = expected[N - 2] = false;
104 std::fill_n(first: in.begin() + 2, n: N - 4, value: true);
105 assert(in == expected);
106 }
107 }
108
109 { // Test cases with full or partial bytes filled
110 { // Full bytes filled
111 std::vector<bool> in(N, false);
112 std::vector<bool> expected(N, true);
113 std::fill_n(first: in.begin(), n: N, value: true);
114 assert(in == expected);
115 }
116 { // Partial bytes with offset filled
117 std::vector<bool> in(N, false);
118 std::vector<bool> expected(N, true);
119 std::fill_n(first: in.begin() + 4, n: N - 8, value: true);
120 std::fill_n(first: expected.begin(), n: 4, value: false);
121 std::fill_n(first: expected.end() - 4, n: 4, value: false);
122 assert(in == expected);
123 }
124 }
125
126 return true;
127}
128
129TEST_CONSTEXPR_CXX20 bool test() {
130 types::for_each(types::forward_iterator_list<char*>(), Test<char>());
131 types::for_each(types::forward_iterator_list<int*>(), Test<int>());
132
133 { // Test with int arrays
134 {
135 int a[4] = {};
136 assert(std::fill_n(a, UDI(4), static_cast<char>(1)) == a + 4);
137 assert(a[0] == 1 && a[1] == 1 && a[2] == 1 && a[3] == 1);
138 }
139#if TEST_STD_VER >= 11
140 {
141 const std::size_t N = 5;
142 int ib[] = {0, 0, 0, 0, 0, 0}; // one bigger than N
143
144 auto it = std::fill_n(std::begin(ib), N, 5);
145 assert(it == (std::begin(ib) + N) && std::all_of(std::begin(ib), it, [](int a) { return a == 5; }) &&
146 *it == 0 // don't overwrite the last value in the output array
147 );
148 }
149#endif
150 }
151
152 { // Test with struct arrays
153 {
154 CharWrapper a[3];
155 assert(std::fill_n(&a[0], UDI(3), CharWrapper('a')) == a + 3);
156 assert(a[0] == CharWrapper('a'));
157 assert(a[1] == CharWrapper('a'));
158 assert(a[2] == CharWrapper('a'));
159 }
160 {
161 CharTransformer b[4] = {};
162 assert(std::fill_n(b, UDI(4), static_cast<char>(10)) == b + 4);
163 assert(b[0].c == 11);
164 assert(b[1].c == 11);
165 assert(b[2].c == 11);
166 assert(b[3].c == 11);
167 }
168 {
169 CharUnionStorage foo[5];
170 std::fill_n(first: &foo[0], n: UDI(5), value: CharUnionStorage());
171 }
172 }
173
174 { // Test with an int array and struct source
175 int a[4] = {};
176 assert(std::fill_n(a, UDI(4), source()) == a + 4);
177 assert(a[0] == 1);
178 assert(a[1] == 1);
179 assert(a[2] == 1);
180 assert(a[3] == 1);
181 }
182
183 { // Test vector<bool>::iterator optimization
184 assert(test_vector_bool(8));
185 assert(test_vector_bool(19));
186 assert(test_vector_bool(32));
187 assert(test_vector_bool(49));
188 assert(test_vector_bool(64));
189 assert(test_vector_bool(199));
190 assert(test_vector_bool(256));
191
192 // Make sure std::fill_n behaves properly with std::vector<bool> iterators with custom size types.
193 // See https://github.com/llvm/llvm-project/pull/122410.
194 {
195 using Alloc = sized_allocator<bool, std::uint8_t, std::int8_t>;
196 std::vector<bool, Alloc> in(100, false, Alloc(1));
197 std::vector<bool, Alloc> expected(100, true, Alloc(1));
198 std::fill_n(in.begin(), in.size(), true);
199 assert(in == expected);
200 }
201 {
202 using Alloc = sized_allocator<bool, std::uint16_t, std::int16_t>;
203 std::vector<bool, Alloc> in(200, false, Alloc(1));
204 std::vector<bool, Alloc> expected(200, true, Alloc(1));
205 std::fill_n(in.begin(), in.size(), true);
206 assert(in == expected);
207 }
208 {
209 using Alloc = sized_allocator<bool, std::uint32_t, std::int32_t>;
210 std::vector<bool, Alloc> in(200, false, Alloc(1));
211 std::vector<bool, Alloc> expected(200, true, Alloc(1));
212 std::fill_n(in.begin(), in.size(), true);
213 assert(in == expected);
214 }
215 {
216 using Alloc = sized_allocator<bool, std::uint64_t, std::int64_t>;
217 std::vector<bool, Alloc> in(200, false, Alloc(1));
218 std::vector<bool, Alloc> expected(200, true, Alloc(1));
219 std::fill_n(in.begin(), in.size(), true);
220 assert(in == expected);
221 }
222 }
223
224 return true;
225}
226
227int main(int, char**) {
228 test();
229#if TEST_STD_VER >= 20
230 static_assert(test());
231#endif
232
233 return 0;
234}
235

source code of libcxx/test/std/algorithms/alg.modifying.operations/alg.fill/fill_n.pass.cpp