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 | // UNSUPPORTED: c++03, c++11, c++14, c++17 |
10 | |
11 | // <memory> |
12 | |
13 | // template <nothrow-forward-iterator ForwardIterator, nothrow-sentinel-for<ForwardIterator> Sentinel, class T> |
14 | // requires constructible_from<iter_value_t<ForwardIterator>, const T&> |
15 | // ForwardIterator ranges::uninitialized_fill(ForwardIterator first, Sentinel last, const T& x); |
16 | // |
17 | // template <nothrow-forward-range ForwardRange, class T> |
18 | // requires constructible_from<range_value_t<ForwardRange>, const T&> |
19 | // borrowed_iterator_t<ForwardRange> ranges::uninitialized_fill(ForwardRange&& range, const T& x); |
20 | |
21 | #include <algorithm> |
22 | #include <cassert> |
23 | #include <iterator> |
24 | #include <memory> |
25 | #include <ranges> |
26 | #include <type_traits> |
27 | |
28 | #include "../buffer.h" |
29 | #include "../counted.h" |
30 | #include "test_macros.h" |
31 | #include "test_iterators.h" |
32 | |
33 | // TODO(varconst): consolidate the ADL checks into a single file. |
34 | // Because this is a variable and not a function, it's guaranteed that ADL won't be used. However, |
35 | // implementations are allowed to use a different mechanism to achieve this effect, so this check is |
36 | // libc++-specific. |
37 | LIBCPP_STATIC_ASSERT(std::is_class_v<decltype(std::ranges::uninitialized_fill)>); |
38 | |
39 | struct NotConvertibleFromInt {}; |
40 | static_assert(!std::is_invocable_v<decltype(std::ranges::uninitialized_fill), NotConvertibleFromInt*, |
41 | NotConvertibleFromInt*, int>); |
42 | |
43 | int main(int, char**) { |
44 | constexpr int value = 42; |
45 | Counted x(value); |
46 | Counted::reset(); |
47 | auto pred = [](const Counted& e) { return e.value == value; }; |
48 | |
49 | // An empty range -- no default constructors should be invoked. |
50 | { |
51 | Buffer<Counted, 1> buf; |
52 | |
53 | std::ranges::uninitialized_fill(buf.begin(), buf.begin(), x); |
54 | assert(Counted::current_objects == 0); |
55 | assert(Counted::total_objects == 0); |
56 | |
57 | std::ranges::uninitialized_fill(std::ranges::empty_view<Counted>(), x); |
58 | assert(Counted::current_objects == 0); |
59 | assert(Counted::total_objects == 0); |
60 | |
61 | forward_iterator<Counted*> it(buf.begin()); |
62 | auto range = std::ranges::subrange(it, sentinel_wrapper<forward_iterator<Counted*>>(it)); |
63 | std::ranges::uninitialized_fill(range.begin(), range.end(), x); |
64 | assert(Counted::current_objects == 0); |
65 | assert(Counted::total_objects == 0); |
66 | Counted::reset(); |
67 | |
68 | std::ranges::uninitialized_fill(range, x); |
69 | assert(Counted::current_objects == 0); |
70 | assert(Counted::total_objects == 0); |
71 | Counted::reset(); |
72 | } |
73 | |
74 | // A range containing several objects, (iter, sentinel) overload. |
75 | { |
76 | constexpr int N = 5; |
77 | Buffer<Counted, N> buf; |
78 | |
79 | std::ranges::uninitialized_fill(buf.begin(), buf.end(), x); |
80 | assert(Counted::current_objects == N); |
81 | assert(Counted::total_objects == N); |
82 | assert(std::all_of(buf.begin(), buf.end(), pred)); |
83 | |
84 | std::destroy(first: buf.begin(), last: buf.end()); |
85 | Counted::reset(); |
86 | } |
87 | |
88 | // A range containing several objects, (range) overload. |
89 | { |
90 | constexpr int N = 5; |
91 | Buffer<Counted, N> buf; |
92 | |
93 | auto range = std::ranges::subrange(buf.begin(), buf.end()); |
94 | std::ranges::uninitialized_fill(range, x); |
95 | assert(Counted::current_objects == N); |
96 | assert(Counted::total_objects == N); |
97 | assert(std::all_of(buf.begin(), buf.end(), pred)); |
98 | |
99 | std::destroy(first: buf.begin(), last: buf.end()); |
100 | Counted::reset(); |
101 | } |
102 | |
103 | // Using `counted_iterator`. |
104 | { |
105 | constexpr int N = 3; |
106 | Buffer<Counted, 5> buf; |
107 | |
108 | std::ranges::uninitialized_fill(std::counted_iterator(buf.begin(), N), std::default_sentinel, x); |
109 | assert(Counted::current_objects == N); |
110 | assert(Counted::total_objects == N); |
111 | assert(std::all_of(buf.begin(), buf.begin() + N, pred)); |
112 | |
113 | std::destroy(first: buf.begin(), last: buf.begin() + N); |
114 | Counted::reset(); |
115 | } |
116 | |
117 | // Using `views::counted`. |
118 | { |
119 | constexpr int N = 3; |
120 | Buffer<Counted, 5> buf; |
121 | |
122 | std::ranges::uninitialized_fill(std::views::counted(buf.begin(), N), x); |
123 | assert(Counted::current_objects == N); |
124 | assert(Counted::total_objects == N); |
125 | assert(std::all_of(buf.begin(), buf.begin() + N, pred)); |
126 | |
127 | std::destroy(first: buf.begin(), last: buf.begin() + N); |
128 | Counted::reset(); |
129 | } |
130 | |
131 | // Using `reverse_view`. |
132 | { |
133 | constexpr int N = 3; |
134 | Buffer<Counted, 5> buf; |
135 | |
136 | auto range = std::ranges::subrange(buf.begin(), buf.begin() + N); |
137 | std::ranges::uninitialized_fill(std::ranges::reverse_view(range), x); |
138 | assert(Counted::current_objects == N); |
139 | assert(Counted::total_objects == N); |
140 | assert(std::all_of(buf.begin(), buf.begin() + N, pred)); |
141 | |
142 | std::destroy(first: buf.begin(), last: buf.begin() + N); |
143 | Counted::reset(); |
144 | } |
145 | |
146 | // Any existing values should be overwritten by value constructors. |
147 | { |
148 | constexpr int N = 5; |
149 | int buffer[N] = {value, value, value, value, value}; |
150 | |
151 | std::ranges::uninitialized_fill(buffer, buffer + 1, 0); |
152 | assert(buffer[0] == 0); |
153 | assert(buffer[1] == value); |
154 | |
155 | std::ranges::uninitialized_fill(buffer, buffer + N, 0); |
156 | assert(buffer[0] == 0); |
157 | assert(buffer[1] == 0); |
158 | assert(buffer[2] == 0); |
159 | assert(buffer[3] == 0); |
160 | assert(buffer[4] == 0); |
161 | } |
162 | |
163 | // An exception is thrown while objects are being created -- the existing objects should stay |
164 | // valid. (iterator, sentinel) overload. |
165 | #ifndef TEST_HAS_NO_EXCEPTIONS |
166 | { |
167 | constexpr int N = 3; |
168 | Buffer<Counted, 5> buf; |
169 | |
170 | Counted::throw_on = N; // When constructing the fourth object. |
171 | try { |
172 | std::ranges::uninitialized_fill(buf.begin(), buf.end(), x); |
173 | } catch (...) { |
174 | } |
175 | assert(Counted::current_objects == 0); |
176 | assert(Counted::total_objects == N); |
177 | |
178 | std::destroy(first: buf.begin(), last: buf.begin() + N); |
179 | Counted::reset(); |
180 | } |
181 | |
182 | // An exception is thrown while objects are being created -- the existing objects should stay |
183 | // valid. (range) overload. |
184 | { |
185 | constexpr int N = 3; |
186 | Buffer<Counted, 5> buf; |
187 | |
188 | Counted::throw_on = N; // When constructing the fourth object. |
189 | try { |
190 | std::ranges::uninitialized_fill(buf, x); |
191 | } catch (...) { |
192 | } |
193 | assert(Counted::current_objects == 0); |
194 | assert(Counted::total_objects == N); |
195 | |
196 | std::destroy(first: buf.begin(), last: buf.begin() + N); |
197 | Counted::reset(); |
198 | } |
199 | #endif // TEST_HAS_NO_EXCEPTIONS |
200 | |
201 | // Works with const iterators, (iter, sentinel) overload. |
202 | { |
203 | constexpr int N = 5; |
204 | Buffer<Counted, N> buf; |
205 | |
206 | std::ranges::uninitialized_fill(buf.cbegin(), buf.cend(), x); |
207 | assert(Counted::current_objects == N); |
208 | assert(Counted::total_objects == N); |
209 | assert(std::all_of(buf.begin(), buf.end(), pred)); |
210 | |
211 | std::destroy(first: buf.begin(), last: buf.end()); |
212 | Counted::reset(); |
213 | } |
214 | |
215 | // Works with const iterators, (range) overload. |
216 | { |
217 | constexpr int N = 5; |
218 | Buffer<Counted, N> buf; |
219 | |
220 | auto range = std::ranges::subrange(buf.cbegin(), buf.cend()); |
221 | std::ranges::uninitialized_fill(range, x); |
222 | assert(Counted::current_objects == N); |
223 | assert(Counted::total_objects == N); |
224 | assert(std::all_of(buf.begin(), buf.end(), pred)); |
225 | |
226 | std::destroy(first: buf.begin(), last: buf.end()); |
227 | Counted::reset(); |
228 | } |
229 | |
230 | return 0; |
231 | } |
232 | |