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

source code of libcxx/test/std/utilities/memory/specialized.algorithms/uninitialized.construct.value/ranges_uninitialized_value_construct.pass.cpp