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(buf.begin(), 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(buf.begin(), 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(buf.begin(), 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(buf.begin(), 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(buf.begin(), 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(buf.begin(), 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(buf.begin(), buf.begin() + N); 197 Counted::reset(); 198 } 199 #endif // TEST_HAS_NO_EXCEPTIONS 200 201 return 0; 202 } 203