xref: /aosp_15_r20/external/cronet/third_party/libc++/src/test/support/test.support/test_proxy.pass.cpp (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
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 #include "MoveOnly.h"
12 #include "test_iterators.h"
13 
14 #include <cassert>
15 
testProxy()16 constexpr void testProxy() {
17   // constructor value
18   {
19     Proxy<int> p{5};
20     assert(p.data == 5);
21   }
22 
23   // constructor reference
24   {
25     int i = 5;
26     Proxy<int&> p{i};
27     assert(&p.data == &i);
28   }
29 
30   // constructor conversion
31   {
32     int i = 5;
33     Proxy<int&> p1{i};
34     Proxy<int> p2 = p1;
35     assert(p2.data == 5);
36 
37     Proxy<int&> p3{p2};
38     assert(&(p3.data) == &(p2.data));
39 
40     MoveOnly m1{8};
41     Proxy<MoveOnly&&> p4 = std::move(m1);
42 
43     Proxy<MoveOnly> p5 = std::move(p4);
44     assert(p5.data.get() == 8);
45   }
46 
47   // assignment
48   {
49     Proxy<int> p1{5};
50     Proxy<int> p2{6};
51     p1 = p2;
52     assert(p1.data == 6);
53 
54     MoveOnly m1{8};
55     Proxy<MoveOnly&&> p3 = std::move(m1);
56     Proxy<MoveOnly> p4{MoveOnly{9}};
57     p4 = std::move(p3);
58     assert(p4.data.get() == 8);
59 
60     // `T` is a reference type.
61     int i = 5, j = 6, k = 7, x = 8;
62     Proxy<int&> p5{i};
63     // `Other` is a prvalue.
64     p5 = Proxy<int&>{j};
65     assert(p5.data == 6);
66     // `Other` is a const lvalue.
67     const Proxy<int&> p_ref{k};
68     p5 = p_ref;
69     assert(p5.data == 7);
70     // `Other` is an xvalue.
71     Proxy<int&> px{x};
72     p5 = std::move(px);
73     assert(p5.data == 8);
74   }
75 
76   // const assignment
77   {
78     int i = 5;
79     int j = 6;
80     const Proxy<int&> p1{i};
81     const Proxy<int&> p2{j};
82     p1 = p2;
83     assert(i == 6);
84 
85     MoveOnly m1{8};
86     MoveOnly m2{9};
87     Proxy<MoveOnly&&> p3       = std::move(m1);
88     const Proxy<MoveOnly&&> p4 = std::move(m2);
89     p4                         = std::move(p3);
90     assert(p4.data.get() == 8);
91   }
92 
93   // compare
94   {
95     Proxy<int> p1{5};
96     Proxy<int> p2{6};
97     assert(p1 != p2);
98     assert(p1 < p2);
99 
100     // Comparing `T` and `T&`.
101     int i = 5, j = 6;
102     Proxy<int&> p_ref{i};
103     Proxy<const int&> p_cref{j};
104     assert(p1 == p_ref);
105     assert(p2 == p_cref);
106     assert(p_ref == p1);
107     assert(p_cref == p2);
108     assert(p_ref == p_ref);
109     assert(p_cref == p_cref);
110     assert(p_ref != p_cref);
111   }
112 }
113 
114 static_assert(std::input_iterator<ProxyIterator<cpp20_input_iterator<int*>>>);
115 static_assert(!std::forward_iterator<ProxyIterator<cpp20_input_iterator<int*>>>);
116 
117 static_assert(std::forward_iterator<ProxyIterator<forward_iterator<int*>>>);
118 static_assert(!std::bidirectional_iterator<ProxyIterator<forward_iterator<int*>>>);
119 
120 static_assert(std::bidirectional_iterator<ProxyIterator<bidirectional_iterator<int*>>>);
121 static_assert(!std::random_access_iterator<ProxyIterator<bidirectional_iterator<int*>>>);
122 
123 static_assert(std::random_access_iterator<ProxyIterator<random_access_iterator<int*>>>);
124 static_assert(!std::contiguous_iterator<ProxyIterator<random_access_iterator<int*>>>);
125 
126 static_assert(std::random_access_iterator<ProxyIterator<contiguous_iterator<int*>>>);
127 static_assert(!std::contiguous_iterator<ProxyIterator<contiguous_iterator<int*>>>);
128 
129 template <class Iter>
testInputIteratorOperation()130 constexpr void testInputIteratorOperation() {
131   int data[] = {1, 2};
132   ProxyIterator<Iter> iter{Iter{data}};
133   sentinel_wrapper<ProxyIterator<Iter>> sent{ProxyIterator<Iter>{Iter{data + 2}}};
134 
135   std::same_as<Proxy<int&>> decltype(auto) result = *iter;
136   assert(result.data == 1);
137   auto& iter2 = ++iter;
138   static_assert(std::is_same_v<decltype(++iter), ProxyIterator<Iter>&>);
139   assert(&iter2 == &iter);
140   assert((*iter).data == 2);
141   ++iter;
142   assert(iter == sent);
143 }
144 
145 template <class Iter>
testForwardIteratorOperation()146 constexpr void testForwardIteratorOperation() {
147   int data[] = {1, 2};
148   ProxyIterator<Iter> iter{Iter{data}};
149 
150   std::same_as<ProxyIterator<Iter>> decltype(auto) it2 = iter++;
151   assert((*it2).data == 1);
152   assert((*iter).data == 2);
153 }
154 
155 template <class Iter>
testBidirectionalIteratorOperation()156 constexpr void testBidirectionalIteratorOperation() {
157   int data[] = {1, 2};
158   ProxyIterator<Iter> iter{Iter{data}};
159   ++iter;
160   assert((*iter).data == 2);
161 
162   auto& iter2 = --iter;
163   static_assert(std::is_same_v<decltype(--iter), ProxyIterator<Iter>&>);
164   assert(&iter2 == &iter);
165   assert((*iter).data == 1);
166   ++iter;
167 
168   std::same_as<ProxyIterator<Iter>> decltype(auto) iter3 = iter--;
169   assert((*iter).data == 1);
170   assert((*iter3).data == 2);
171 }
172 
173 template <class Iter>
testRandomAccessIteratorOperation()174 constexpr void testRandomAccessIteratorOperation() {
175   int data[] = {1, 2, 3, 4, 5};
176   ProxyIterator<Iter> iter{Iter{data}};
177 
178   auto& iter2 = iter += 2;
179   static_assert(std::is_same_v<decltype(iter += 2), ProxyIterator<Iter>&>);
180   assert(&iter2 == &iter);
181   assert((*iter).data == 3);
182 
183   auto& iter3 = iter -= 1;
184   static_assert(std::is_same_v<decltype(iter -= 1), ProxyIterator<Iter>&>);
185   assert(&iter3 == &iter);
186   assert((*iter).data == 2);
187 
188   std::same_as<Proxy<int&>> decltype(auto) r = iter[2];
189   assert(r.data == 4);
190 
191   std::same_as<ProxyIterator<Iter>> decltype(auto) iter4 = iter - 1;
192   assert((*iter4).data == 1);
193 
194   std::same_as<ProxyIterator<Iter>> decltype(auto) iter5 = iter4 + 2;
195   assert((*iter5).data == 3);
196 
197   std::same_as<ProxyIterator<Iter>> decltype(auto) iter6 = 3 + iter4;
198   assert((*iter6).data == 4);
199 
200   std::same_as<std::iter_difference_t<Iter>> decltype(auto) n = iter6 - iter5;
201   assert(n == 1);
202 
203   assert(iter4 < iter5);
204   assert(iter3 <= iter5);
205   assert(iter5 > iter4);
206   assert(iter6 >= iter4);
207 }
208 
testProxyIterator()209 constexpr void testProxyIterator() {
210   // input iterator operations
211   {
212     testInputIteratorOperation<cpp20_input_iterator<int*>>();
213     testInputIteratorOperation<forward_iterator<int*>>();
214     testInputIteratorOperation<bidirectional_iterator<int*>>();
215     testInputIteratorOperation<random_access_iterator<int*>>();
216     testInputIteratorOperation<contiguous_iterator<int*>>();
217   }
218 
219   // forward iterator operations
220   {
221     testForwardIteratorOperation<forward_iterator<int*>>();
222     testForwardIteratorOperation<bidirectional_iterator<int*>>();
223     testForwardIteratorOperation<random_access_iterator<int*>>();
224     testForwardIteratorOperation<contiguous_iterator<int*>>();
225   }
226 
227   // bidirectional iterator operations
228   {
229     testBidirectionalIteratorOperation<bidirectional_iterator<int*>>();
230     testBidirectionalIteratorOperation<random_access_iterator<int*>>();
231     testBidirectionalIteratorOperation<contiguous_iterator<int*>>();
232   }
233 
234   // random access iterator operations
235   {
236     testRandomAccessIteratorOperation<random_access_iterator<int*>>();
237     testRandomAccessIteratorOperation<contiguous_iterator<int*>>();
238   }
239 }
240 
testProxyRange()241 constexpr void testProxyRange() {
242   int data[] = {3, 4, 5};
243   ProxyRange r{data};
244   std::same_as<ProxyIterator<int*>> decltype(auto) it = std::ranges::begin(r);
245   assert((*it).data == 3);
246   it += 3;
247   assert(it == std::ranges::end(r));
248 }
249 
250 template <class Iter>
251 concept StdMoveWorks = requires(std::iter_value_t<Iter> val, Iter iter) { val = std::move(*iter); };
252 
253 static_assert(StdMoveWorks<MoveOnly*>);
254 static_assert(!StdMoveWorks<ProxyIterator<MoveOnly*>>);
255 
256 // although this "works" but it actually creates a copy instead of move
257 static_assert(StdMoveWorks<ProxyIterator<int*>>);
258 
259 using std::swap;
260 
261 template <class Iter>
262 concept SwapWorks = requires(Iter iter1, Iter iter2) { swap(*iter1, *iter2); };
263 
264 static_assert(SwapWorks<int*>);
265 static_assert(!SwapWorks<ProxyIterator<int*>>);
266 
test()267 constexpr bool test() {
268   testProxy();
269   testProxyIterator();
270   testProxyRange();
271 
272   // iter_move
273   {
274     MoveOnly data[] = {5, 6, 7};
275     ProxyRange r{data};
276     auto it                               = r.begin();
277     std::iter_value_t<decltype(it)> moved = std::ranges::iter_move(it);
278     assert(moved.data.get() == 5);
279   }
280 
281   // iter_swap
282   {
283     MoveOnly data[] = {5, 6, 7};
284     ProxyRange r{data};
285     auto it1 = r.begin();
286     auto it2 = it1 + 2;
287     std::ranges::iter_swap(it1, it2);
288     assert(data[0].get() == 7);
289     assert(data[2].get() == 5);
290   }
291 
292   return true;
293 }
294 
main(int,char **)295 int main(int, char**) {
296   test();
297   static_assert(test());
298 
299   return 0;
300 }
301