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