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_default_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_default_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_default_construct)>);
37
38struct NotDefaultCtrable { NotDefaultCtrable() = delete; };
39static_assert(!std::is_invocable_v<decltype(std::ranges::uninitialized_default_construct),
40 NotDefaultCtrable*, NotDefaultCtrable*>);
41
42int main(int, char**) {
43 // An empty range -- no default constructors should be invoked.
44 {
45 Buffer<Counted, 1> buf;
46
47 std::ranges::uninitialized_default_construct(buf.begin(), buf.begin());
48 assert(Counted::current_objects == 0);
49 assert(Counted::total_objects == 0);
50
51 std::ranges::uninitialized_default_construct(std::ranges::empty_view<Counted>());
52 assert(Counted::current_objects == 0);
53 assert(Counted::total_objects == 0);
54
55 forward_iterator<Counted*> it(buf.begin());
56 auto range = std::ranges::subrange(it, sentinel_wrapper<forward_iterator<Counted*>>(it));
57 std::ranges::uninitialized_default_construct(range.begin(), range.end());
58 assert(Counted::current_objects == 0);
59 assert(Counted::total_objects == 0);
60
61 std::ranges::uninitialized_default_construct(range);
62 assert(Counted::current_objects == 0);
63 assert(Counted::total_objects == 0);
64 }
65
66 // A range containing several objects, (iter, sentinel) overload.
67 {
68 constexpr int N = 5;
69 Buffer<Counted, 5> buf;
70
71 std::ranges::uninitialized_default_construct(buf.begin(), buf.end());
72 assert(Counted::current_objects == N);
73 assert(Counted::total_objects == N);
74
75 std::destroy(first: buf.begin(), last: buf.end());
76 Counted::reset();
77 }
78
79 // A range containing several objects, (range) overload.
80 {
81 constexpr int N = 5;
82 Buffer<Counted, N> buf;
83
84 auto range = std::ranges::subrange(buf.begin(), buf.end());
85 std::ranges::uninitialized_default_construct(range);
86 assert(Counted::current_objects == N);
87 assert(Counted::total_objects == N);
88
89 std::destroy(first: buf.begin(), last: buf.end());
90 Counted::reset();
91 }
92
93 // Using `counted_iterator`.
94 {
95 constexpr int N = 3;
96 Buffer<Counted, 5> buf;
97
98 std::ranges::uninitialized_default_construct(
99 std::counted_iterator(buf.begin(), N), std::default_sentinel);
100 assert(Counted::current_objects == N);
101 assert(Counted::total_objects == N);
102
103 std::destroy(first: buf.begin(), last: buf.begin() + N);
104 Counted::reset();
105 }
106
107 // Using `views::counted`.
108 {
109 constexpr int N = 3;
110 Buffer<Counted, 5> buf;
111
112 std::ranges::uninitialized_default_construct(std::views::counted(buf.begin(), N));
113 assert(Counted::current_objects == N);
114 assert(Counted::total_objects == N);
115
116 std::destroy(first: buf.begin(), last: buf.begin() + N);
117 Counted::reset();
118 }
119
120 // Using `reverse_view`.
121 {
122 constexpr int N = 3;
123 Buffer<Counted, 5> buf;
124
125 auto range = std::ranges::subrange(buf.begin(), buf.begin() + N);
126 std::ranges::uninitialized_default_construct(std::ranges::reverse_view(range));
127 assert(Counted::current_objects == N);
128 assert(Counted::total_objects == N);
129
130 std::destroy(first: buf.begin(), last: buf.begin() + N);
131 Counted::reset();
132 }
133
134 // An exception is thrown while objects are being created -- the existing objects should stay
135 // valid. (iterator, sentinel) overload.
136#ifndef TEST_HAS_NO_EXCEPTIONS
137 {
138 Buffer<Counted, 5> buf;
139
140 Counted::throw_on = 3; // When constructing the fourth object (counting from one).
141 try {
142 std::ranges::uninitialized_default_construct(buf.begin(), buf.end());
143 } catch(...) {}
144 assert(Counted::current_objects == 0);
145 assert(Counted::total_objects == 3);
146 std::destroy(first: buf.begin(), last: buf.begin() + Counted::total_objects);
147 Counted::reset();
148 }
149
150 // An exception is thrown while objects are being created -- the existing objects should stay
151 // valid. (range) overload.
152 {
153 Buffer<Counted, 5> buf;
154
155 Counted::throw_on = 3; // When constructing the fourth object.
156 try {
157 std::ranges::uninitialized_default_construct(buf);
158 } catch(...) {}
159 assert(Counted::current_objects == 0);
160 assert(Counted::total_objects == 3);
161 std::destroy(first: buf.begin(), last: buf.begin() + Counted::total_objects);
162 Counted::reset();
163 }
164#endif // TEST_HAS_NO_EXCEPTIONS
165
166 // Works with const iterators, (iter, sentinel) overload.
167 {
168 constexpr int N = 5;
169 Buffer<Counted, N> buf;
170
171 std::ranges::uninitialized_default_construct(buf.cbegin(), buf.cend());
172 assert(Counted::current_objects == N);
173 assert(Counted::total_objects == N);
174 std::destroy(first: buf.begin(), last: buf.end());
175 Counted::reset();
176 }
177
178 // Works with const iterators, (range) overload.
179 {
180 constexpr int N = 5;
181 Buffer<Counted, N> buf;
182 auto range = std::ranges::subrange(buf.cbegin(), buf.cend());
183
184 std::ranges::uninitialized_default_construct(range);
185 assert(Counted::current_objects == N);
186 assert(Counted::total_objects == N);
187 std::destroy(first: buf.begin(), last: buf.end());
188 Counted::reset();
189 }
190
191 return 0;
192}
193

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