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, class T> |
14 | // requires constructible_from<iter_value_t<ForwardIterator>, const T&> |
15 | // ForwardIterator ranges::uninitialized_fill_n(ForwardIterator first, iter_difference_t<ForwardIterator> n); |
16 | |
17 | #include <algorithm> |
18 | #include <cassert> |
19 | #include <iterator> |
20 | #include <memory> |
21 | #include <ranges> |
22 | #include <type_traits> |
23 | |
24 | #include "../buffer.h" |
25 | #include "../counted.h" |
26 | #include "test_macros.h" |
27 | #include "test_iterators.h" |
28 | |
29 | // TODO(varconst): consolidate the ADL checks into a single file. |
30 | // Because this is a variable and not a function, it's guaranteed that ADL won't be used. However, |
31 | // implementations are allowed to use a different mechanism to achieve this effect, so this check is |
32 | // libc++-specific. |
33 | LIBCPP_STATIC_ASSERT(std::is_class_v<decltype(std::ranges::uninitialized_fill_n)>); |
34 | |
35 | struct NotConvertibleFromInt {}; |
36 | static_assert(!std::is_invocable_v<decltype(std::ranges::uninitialized_fill_n), NotConvertibleFromInt*, std::size_t, int>); |
37 | |
38 | int main(int, char**) { |
39 | constexpr int value = 42; |
40 | Counted x(value); |
41 | Counted::reset(); |
42 | auto pred = [](const Counted& e) { return e.value == value; }; |
43 | |
44 | // An empty range -- no default constructors should be invoked. |
45 | { |
46 | Buffer<Counted, 1> buf; |
47 | |
48 | std::ranges::uninitialized_fill_n(buf.begin(), 0, x); |
49 | assert(Counted::current_objects == 0); |
50 | assert(Counted::total_objects == 0); |
51 | } |
52 | |
53 | // A range containing several objects. |
54 | { |
55 | constexpr int N = 5; |
56 | Buffer<Counted, N> buf; |
57 | |
58 | std::ranges::uninitialized_fill_n(buf.begin(), N, x); |
59 | assert(Counted::current_objects == N); |
60 | assert(Counted::total_objects == N); |
61 | assert(std::all_of(buf.begin(), buf.end(), pred)); |
62 | |
63 | std::destroy(first: buf.begin(), last: buf.end()); |
64 | Counted::reset(); |
65 | } |
66 | |
67 | // Any existing values should be overwritten by value constructors. |
68 | { |
69 | constexpr int N = 5; |
70 | int buffer[N] = {value, value, value, value, value}; |
71 | |
72 | std::ranges::uninitialized_fill_n(buffer, 1, 0); |
73 | assert(buffer[0] == 0); |
74 | assert(buffer[1] == value); |
75 | |
76 | std::ranges::uninitialized_fill_n(buffer, N, 0); |
77 | assert(buffer[0] == 0); |
78 | assert(buffer[1] == 0); |
79 | assert(buffer[2] == 0); |
80 | assert(buffer[3] == 0); |
81 | assert(buffer[4] == 0); |
82 | } |
83 | |
84 | // An exception is thrown while objects are being created -- the existing objects should stay |
85 | // valid. (iterator, sentinel) overload. |
86 | #ifndef TEST_HAS_NO_EXCEPTIONS |
87 | { |
88 | constexpr int N = 5; |
89 | Buffer<Counted, N> buf; |
90 | |
91 | Counted::throw_on = 3; // When constructing the fourth object. |
92 | try { |
93 | std::ranges::uninitialized_fill_n(buf.begin(), N, x); |
94 | } catch (...) { |
95 | } |
96 | assert(Counted::current_objects == 0); |
97 | assert(Counted::total_objects == 3); |
98 | |
99 | std::destroy(first: buf.begin(), last: buf.begin() + 3); |
100 | Counted::reset(); |
101 | } |
102 | #endif // TEST_HAS_NO_EXCEPTIONS |
103 | |
104 | // Works with const iterators. |
105 | { |
106 | constexpr int N = 5; |
107 | Buffer<Counted, N> buf; |
108 | |
109 | std::ranges::uninitialized_fill_n(buf.cbegin(), N, x); |
110 | assert(Counted::current_objects == N); |
111 | assert(Counted::total_objects == N); |
112 | assert(std::all_of(buf.begin(), buf.end(), pred)); |
113 | |
114 | std::destroy(first: buf.begin(), last: buf.end()); |
115 | Counted::reset(); |
116 | } |
117 | |
118 | return 0; |
119 | } |
120 | |