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.
37LIBCPP_STATIC_ASSERT(std::is_class_v<decltype(std::ranges::uninitialized_fill)>);
38
39struct NotConvertibleFromInt {};
40static_assert(!std::is_invocable_v<decltype(std::ranges::uninitialized_fill), NotConvertibleFromInt*,
41 NotConvertibleFromInt*, int>);
42
43int 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

source code of libcxx/test/std/utilities/memory/specialized.algorithms/uninitialized.fill/ranges_uninitialized_fill.pass.cpp