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 | // std::views::counted; |
12 | |
13 | #include <ranges> |
14 | #include <cassert> |
15 | #include <concepts> |
16 | #include <cstddef> |
17 | #include <memory> |
18 | #include <span> |
19 | #include <utility> |
20 | |
21 | #include "test_macros.h" |
22 | #include "test_iterators.h" |
23 | |
24 | struct RvalueConvertible { |
25 | RvalueConvertible(const RvalueConvertible&) = delete; |
26 | operator int() &&; |
27 | }; |
28 | |
29 | struct LvalueConvertible { |
30 | LvalueConvertible(const LvalueConvertible&) = delete; |
31 | operator int() &; |
32 | }; |
33 | |
34 | struct OnlyExplicitlyConvertible { |
35 | explicit operator int() const; |
36 | }; |
37 | |
38 | template<class... Ts> |
39 | concept CountedInvocable = requires (Ts&&... ts) { |
40 | std::views::counted(std::forward<Ts>(ts)...); |
41 | }; |
42 | |
43 | constexpr bool test() { |
44 | int buffer[8] = {1, 2, 3, 4, 5, 6, 7, 8}; |
45 | |
46 | { |
47 | static_assert(std::addressof(std::views::counted) == std::addressof(std::ranges::views::counted)); |
48 | |
49 | static_assert( CountedInvocable<int*, std::size_t>); |
50 | static_assert(!CountedInvocable<int*, LvalueConvertible>); |
51 | static_assert( CountedInvocable<int*, LvalueConvertible&>); |
52 | static_assert( CountedInvocable<int*, RvalueConvertible>); |
53 | static_assert(!CountedInvocable<int*, RvalueConvertible&>); |
54 | static_assert(!CountedInvocable<int*, OnlyExplicitlyConvertible>); |
55 | static_assert(!CountedInvocable<int*, int*>); |
56 | static_assert(!CountedInvocable<int*>); |
57 | static_assert(!CountedInvocable<std::size_t>); |
58 | static_assert(!CountedInvocable<>); |
59 | } |
60 | |
61 | { |
62 | auto c1 = std::views::counted(buffer, 3); |
63 | auto c2 = std::views::counted(std::as_const(buffer), 3); |
64 | |
65 | ASSERT_SAME_TYPE(decltype(c1), std::span<int>); |
66 | ASSERT_SAME_TYPE(decltype(c2), std::span<const int>); |
67 | |
68 | assert(c1.data() == buffer && c1.size() == 3); |
69 | assert(c2.data() == buffer && c2.size() == 3); |
70 | } |
71 | |
72 | { |
73 | auto it = contiguous_iterator<int*>(buffer); |
74 | auto cit = contiguous_iterator<const int*>(buffer); |
75 | |
76 | auto c1 = std::views::counted(it, 3); |
77 | auto c2 = std::views::counted(std::as_const(it), 3); |
78 | auto c3 = std::views::counted(std::move(it), 3); |
79 | auto c4 = std::views::counted(contiguous_iterator<int*>(buffer), 3); |
80 | auto c5 = std::views::counted(cit, 3); |
81 | auto c6 = std::views::counted(std::as_const(cit), 3); |
82 | auto c7 = std::views::counted(std::move(cit), 3); |
83 | auto c8 = std::views::counted(contiguous_iterator<const int*>(buffer), 3); |
84 | |
85 | ASSERT_SAME_TYPE(decltype(c1), std::span<int>); |
86 | ASSERT_SAME_TYPE(decltype(c2), std::span<int>); |
87 | ASSERT_SAME_TYPE(decltype(c3), std::span<int>); |
88 | ASSERT_SAME_TYPE(decltype(c4), std::span<int>); |
89 | ASSERT_SAME_TYPE(decltype(c5), std::span<const int>); |
90 | ASSERT_SAME_TYPE(decltype(c6), std::span<const int>); |
91 | ASSERT_SAME_TYPE(decltype(c7), std::span<const int>); |
92 | ASSERT_SAME_TYPE(decltype(c8), std::span<const int>); |
93 | |
94 | assert(c1.data() == buffer && c1.size() == 3); |
95 | assert(c2.data() == buffer && c2.size() == 3); |
96 | assert(c3.data() == buffer && c3.size() == 3); |
97 | assert(c4.data() == buffer && c4.size() == 3); |
98 | assert(c5.data() == buffer && c5.size() == 3); |
99 | assert(c6.data() == buffer && c6.size() == 3); |
100 | assert(c7.data() == buffer && c7.size() == 3); |
101 | assert(c8.data() == buffer && c8.size() == 3); |
102 | } |
103 | |
104 | { |
105 | auto it = random_access_iterator<int*>(buffer); |
106 | auto cit = random_access_iterator<const int*>(buffer); |
107 | |
108 | auto c1 = std::views::counted(it, 3); |
109 | auto c2 = std::views::counted(std::as_const(it), 3); |
110 | auto c3 = std::views::counted(std::move(it), 3); |
111 | auto c4 = std::views::counted(random_access_iterator<int*>(buffer), 3); |
112 | auto c5 = std::views::counted(cit, 3); |
113 | auto c6 = std::views::counted(std::as_const(cit), 3); |
114 | auto c7 = std::views::counted(std::move(cit), 3); |
115 | auto c8 = std::views::counted(random_access_iterator<const int*>(buffer), 3); |
116 | |
117 | ASSERT_SAME_TYPE(decltype(c1), std::ranges::subrange<random_access_iterator<int*>>); |
118 | ASSERT_SAME_TYPE(decltype(c2), std::ranges::subrange<random_access_iterator<int*>>); |
119 | ASSERT_SAME_TYPE(decltype(c3), std::ranges::subrange<random_access_iterator<int*>>); |
120 | ASSERT_SAME_TYPE(decltype(c4), std::ranges::subrange<random_access_iterator<int*>>); |
121 | ASSERT_SAME_TYPE(decltype(c5), std::ranges::subrange<random_access_iterator<const int*>>); |
122 | ASSERT_SAME_TYPE(decltype(c6), std::ranges::subrange<random_access_iterator<const int*>>); |
123 | ASSERT_SAME_TYPE(decltype(c7), std::ranges::subrange<random_access_iterator<const int*>>); |
124 | ASSERT_SAME_TYPE(decltype(c8), std::ranges::subrange<random_access_iterator<const int*>>); |
125 | |
126 | assert(c1.begin() == it && c1.end() == it + 3); |
127 | assert(c2.begin() == it && c2.end() == it + 3); |
128 | assert(c3.begin() == it && c3.end() == it + 3); |
129 | assert(c4.begin() == it && c4.end() == it + 3); |
130 | assert(c5.begin() == cit && c5.end() == cit + 3); |
131 | assert(c6.begin() == cit && c6.end() == cit + 3); |
132 | assert(c7.begin() == cit && c7.end() == cit + 3); |
133 | assert(c8.begin() == cit && c8.end() == cit + 3); |
134 | } |
135 | |
136 | { |
137 | auto it = bidirectional_iterator<int*>(buffer); |
138 | auto cit = bidirectional_iterator<const int*>(buffer); |
139 | |
140 | auto c1 = std::views::counted(it, 3); |
141 | auto c2 = std::views::counted(std::as_const(it), 3); |
142 | auto c3 = std::views::counted(std::move(it), 3); |
143 | auto c4 = std::views::counted(bidirectional_iterator<int*>(buffer), 3); |
144 | auto c5 = std::views::counted(cit, 3); |
145 | auto c6 = std::views::counted(std::as_const(cit), 3); |
146 | auto c7 = std::views::counted(std::move(cit), 3); |
147 | auto c8 = std::views::counted(bidirectional_iterator<const int*>(buffer), 3); |
148 | |
149 | using Expected = std::ranges::subrange<std::counted_iterator<decltype(it)>, std::default_sentinel_t>; |
150 | using ConstExpected = std::ranges::subrange<std::counted_iterator<decltype(cit)>, std::default_sentinel_t>; |
151 | |
152 | ASSERT_SAME_TYPE(decltype(c1), Expected); |
153 | ASSERT_SAME_TYPE(decltype(c2), Expected); |
154 | ASSERT_SAME_TYPE(decltype(c3), Expected); |
155 | ASSERT_SAME_TYPE(decltype(c4), Expected); |
156 | ASSERT_SAME_TYPE(decltype(c5), ConstExpected); |
157 | ASSERT_SAME_TYPE(decltype(c6), ConstExpected); |
158 | ASSERT_SAME_TYPE(decltype(c7), ConstExpected); |
159 | ASSERT_SAME_TYPE(decltype(c8), ConstExpected); |
160 | |
161 | assert(c1.begin().base() == it && c1.size() == 3); |
162 | assert(c2.begin().base() == it && c2.size() == 3); |
163 | assert(c3.begin().base() == it && c3.size() == 3); |
164 | assert(c4.begin().base() == it && c4.size() == 3); |
165 | assert(c5.begin().base() == cit && c5.size() == 3); |
166 | assert(c6.begin().base() == cit && c6.size() == 3); |
167 | assert(c7.begin().base() == cit && c7.size() == 3); |
168 | assert(c8.begin().base() == cit && c8.size() == 3); |
169 | } |
170 | |
171 | { |
172 | auto it = cpp17_output_iterator<int*>(buffer); |
173 | |
174 | auto c1 = std::views::counted(it, 3); |
175 | auto c2 = std::views::counted(std::as_const(it), 3); |
176 | auto c3 = std::views::counted(std::move(it), 3); |
177 | auto c4 = std::views::counted(cpp17_output_iterator<int*>(buffer), 3); |
178 | |
179 | using Expected = std::ranges::subrange<std::counted_iterator<decltype(it)>, std::default_sentinel_t>; |
180 | |
181 | ASSERT_SAME_TYPE(decltype(c1), Expected); |
182 | ASSERT_SAME_TYPE(decltype(c2), Expected); |
183 | ASSERT_SAME_TYPE(decltype(c3), Expected); |
184 | ASSERT_SAME_TYPE(decltype(c4), Expected); |
185 | |
186 | assert(base(c1.begin().base()) == buffer && c1.size() == 3); |
187 | assert(base(c2.begin().base()) == buffer && c2.size() == 3); |
188 | assert(base(c3.begin().base()) == buffer && c3.size() == 3); |
189 | assert(base(c4.begin().base()) == buffer && c4.size() == 3); |
190 | } |
191 | |
192 | { |
193 | auto it = cpp17_input_iterator<int*>(buffer); |
194 | |
195 | auto c1 = std::views::counted(it, 3); |
196 | auto c2 = std::views::counted(std::as_const(it), 3); |
197 | auto c3 = std::views::counted(std::move(it), 3); |
198 | auto c4 = std::views::counted(cpp17_input_iterator<int*>(buffer), 3); |
199 | |
200 | using Expected = std::ranges::subrange<std::counted_iterator<decltype(it)>, std::default_sentinel_t>; |
201 | |
202 | ASSERT_SAME_TYPE(decltype(c1), Expected); |
203 | ASSERT_SAME_TYPE(decltype(c2), Expected); |
204 | ASSERT_SAME_TYPE(decltype(c3), Expected); |
205 | ASSERT_SAME_TYPE(decltype(c4), Expected); |
206 | |
207 | assert(base(c1.begin().base()) == buffer && c1.size() == 3); |
208 | assert(base(c2.begin().base()) == buffer && c2.size() == 3); |
209 | assert(base(c3.begin().base()) == buffer && c3.size() == 3); |
210 | assert(base(c4.begin().base()) == buffer && c4.size() == 3); |
211 | } |
212 | |
213 | { |
214 | auto it = cpp20_input_iterator<int*>(buffer); |
215 | |
216 | static_assert(!std::copyable<cpp20_input_iterator<int*>>); |
217 | static_assert(!CountedInvocable<cpp20_input_iterator<int*>&, int>); |
218 | static_assert(!CountedInvocable<const cpp20_input_iterator<int*>&, int>); |
219 | auto c3 = std::views::counted(std::move(it), 3); |
220 | auto c4 = std::views::counted(cpp20_input_iterator<int*>(buffer), 3); |
221 | |
222 | using Expected = std::ranges::subrange<std::counted_iterator<decltype(it)>, std::default_sentinel_t>; |
223 | |
224 | ASSERT_SAME_TYPE(decltype(c3), Expected); |
225 | ASSERT_SAME_TYPE(decltype(c4), Expected); |
226 | |
227 | assert(base(c3.begin().base()) == buffer && c3.size() == 3); |
228 | assert(base(c4.begin().base()) == buffer && c4.size() == 3); |
229 | } |
230 | |
231 | return true; |
232 | } |
233 | |
234 | int main(int, char**) { |
235 | test(); |
236 | static_assert(test()); |
237 | |
238 | return 0; |
239 | } |
240 | |