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 | // <algorithm> |
10 | |
11 | // UNSUPPORTED: c++03, c++11, c++14, c++17 |
12 | |
13 | // template<class T, output_iterator<const T&> O, sentinel_for<O> S> |
14 | // constexpr O ranges::fill(O first, S last, const T& value); |
15 | // template<class T, output_range<const T&> R> |
16 | // constexpr borrowed_iterator_t<R> ranges::fill(R&& r, const T& value); |
17 | |
18 | #include <algorithm> |
19 | #include <array> |
20 | #include <cassert> |
21 | #include <ranges> |
22 | #include <string> |
23 | |
24 | #include "almost_satisfies_types.h" |
25 | #include "test_iterators.h" |
26 | |
27 | template <class Iter, class Sent = sentinel_wrapper<Iter>> |
28 | concept HasFillIt = requires(Iter iter, Sent sent) { std::ranges::fill(iter, sent, int{}); }; |
29 | |
30 | static_assert(HasFillIt<int*>); |
31 | static_assert(!HasFillIt<OutputIteratorNotIndirectlyWritable>); |
32 | static_assert(!HasFillIt<OutputIteratorNotInputOrOutputIterator>); |
33 | static_assert(!HasFillIt<int*, SentinelForNotSemiregular>); |
34 | static_assert(!HasFillIt<int*, SentinelForNotWeaklyEqualityComparableWith>); |
35 | |
36 | template <class Range> |
37 | concept HasFillR = requires(Range range) { std::ranges::fill(range, int{}); }; |
38 | |
39 | static_assert(HasFillR<UncheckedRange<int*>>); |
40 | static_assert(!HasFillR<OutputRangeNotIndirectlyWritable>); |
41 | static_assert(!HasFillR<OutputRangeNotInputOrOutputIterator>); |
42 | static_assert(!HasFillR<OutputRangeNotSentinelSemiregular>); |
43 | static_assert(!HasFillR<OutputRangeNotSentinelEqualityComparableWith>); |
44 | |
45 | template <class It, class Sent = It> |
46 | constexpr void test_iterators() { |
47 | { // simple test |
48 | { |
49 | int a[3]; |
50 | std::same_as<It> auto ret = std::ranges::fill(It(a), Sent(It(a + 3)), 1); |
51 | assert(std::all_of(a, a + 3, [](int i) { return i == 1; })); |
52 | assert(base(ret) == a + 3); |
53 | } |
54 | { |
55 | int a[3]; |
56 | auto range = std::ranges::subrange(It(a), Sent(It(a + 3))); |
57 | std::same_as<It> auto ret = std::ranges::fill(range, 1); |
58 | assert(std::all_of(a, a + 3, [](int i) { return i == 1; })); |
59 | assert(base(ret) == a + 3); |
60 | } |
61 | } |
62 | |
63 | { // check that an empty range works |
64 | { |
65 | std::array<int, 0> a; |
66 | auto ret = std::ranges::fill(It(a.data()), Sent(It(a.data())), 1); |
67 | assert(base(ret) == a.data()); |
68 | } |
69 | { |
70 | std::array<int, 0> a; |
71 | auto range = std::ranges::subrange(It(a.data()), Sent(It(a.data()))); |
72 | auto ret = std::ranges::fill(range, 1); |
73 | assert(base(ret) == a.data()); |
74 | } |
75 | } |
76 | } |
77 | |
78 | constexpr bool test() { |
79 | test_iterators<cpp17_output_iterator<int*>, sentinel_wrapper<cpp17_output_iterator<int*>>>(); |
80 | test_iterators<cpp20_output_iterator<int*>, sentinel_wrapper<cpp20_output_iterator<int*>>>(); |
81 | test_iterators<forward_iterator<int*>>(); |
82 | test_iterators<bidirectional_iterator<int*>>(); |
83 | test_iterators<random_access_iterator<int*>>(); |
84 | test_iterators<contiguous_iterator<int*>>(); |
85 | test_iterators<int*>(); |
86 | |
87 | { // check that every element is copied once |
88 | struct S { |
89 | bool copied = false; |
90 | constexpr S& operator=(const S&) { |
91 | copied = true; |
92 | return *this; |
93 | } |
94 | }; |
95 | { |
96 | S a[5]; |
97 | std::ranges::fill(a, a + 5, S {true}); |
98 | assert(std::all_of(a, a + 5, [](S& s) { return s.copied; })); |
99 | } |
100 | { |
101 | S a[5]; |
102 | std::ranges::fill(a, S {true}); |
103 | assert(std::all_of(a, a + 5, [](S& s) { return s.copied; })); |
104 | } |
105 | } |
106 | |
107 | { // check that std::ranges::dangling is returned |
108 | [[maybe_unused]] std::same_as<std::ranges::dangling> decltype(auto) ret = |
109 | std::ranges::fill(std::array<int, 10> {}, 1); |
110 | } |
111 | |
112 | { // check that std::ranges::dangling isn't returned with a borrowing range |
113 | std::array<int, 10> a{}; |
114 | [[maybe_unused]] std::same_as<std::array<int, 10>::iterator> decltype(auto) ret = |
115 | std::ranges::fill(std::views::all(a), 1); |
116 | assert(std::all_of(a.begin(), a.end(), [](int i) { return i == 1; })); |
117 | } |
118 | |
119 | { // check that non-trivially copyable items are copied properly |
120 | { |
121 | std::array<std::string, 10> a; |
122 | auto ret = std::ranges::fill(a.begin(), a.end(), "long long string so no SSO" ); |
123 | assert(ret == a.end()); |
124 | assert(std::all_of(a.begin(), a.end(), [](auto& s) { return s == "long long string so no SSO" ; })); |
125 | } |
126 | { |
127 | std::array<std::string, 10> a; |
128 | auto ret = std::ranges::fill(a, "long long string so no SSO" ); |
129 | assert(ret == a.end()); |
130 | assert(std::all_of(a.begin(), a.end(), [](auto& s) { return s == "long long string so no SSO" ; })); |
131 | } |
132 | } |
133 | |
134 | return true; |
135 | } |
136 | |
137 | int main(int, char**) { |
138 | test(); |
139 | static_assert(test()); |
140 | |
141 | return 0; |
142 | } |
143 | |