[flang][runtime] Make defined formatted I/O process format elementally (#74150)
[llvm-project.git] / libcxx / test / support / test.support / test_proxy.pass.cpp
blob668caf175add3c04dba10a4ac53034ecd0a89374
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 //===----------------------------------------------------------------------===//
9 // UNSUPPORTED: c++03, c++11, c++14, c++17
11 #include "MoveOnly.h"
12 #include "test_iterators.h"
14 #include <cassert>
16 constexpr void testProxy() {
17 // constructor value
19 Proxy<int> p{5};
20 assert(p.data == 5);
23 // constructor reference
25 int i = 5;
26 Proxy<int&> p{i};
27 assert(&p.data == &i);
30 // constructor conversion
32 int i = 5;
33 Proxy<int&> p1{i};
34 Proxy<int> p2 = p1;
35 assert(p2.data == 5);
37 Proxy<int&> p3{p2};
38 assert(&(p3.data) == &(p2.data));
40 MoveOnly m1{8};
41 Proxy<MoveOnly&&> p4 = std::move(m1);
43 Proxy<MoveOnly> p5 = std::move(p4);
44 assert(p5.data.get() == 8);
47 // assignment
49 Proxy<int> p1{5};
50 Proxy<int> p2{6};
51 p1 = p2;
52 assert(p1.data == 6);
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);
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);
76 // const assignment
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);
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);
93 // compare
95 Proxy<int> p1{5};
96 Proxy<int> p2{6};
97 assert(p1 != p2);
98 assert(p1 < p2);
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);
114 static_assert(std::input_iterator<ProxyIterator<cpp20_input_iterator<int*>>>);
115 static_assert(!std::forward_iterator<ProxyIterator<cpp20_input_iterator<int*>>>);
117 static_assert(std::forward_iterator<ProxyIterator<forward_iterator<int*>>>);
118 static_assert(!std::bidirectional_iterator<ProxyIterator<forward_iterator<int*>>>);
120 static_assert(std::bidirectional_iterator<ProxyIterator<bidirectional_iterator<int*>>>);
121 static_assert(!std::random_access_iterator<ProxyIterator<bidirectional_iterator<int*>>>);
123 static_assert(std::random_access_iterator<ProxyIterator<random_access_iterator<int*>>>);
124 static_assert(!std::contiguous_iterator<ProxyIterator<random_access_iterator<int*>>>);
126 static_assert(std::random_access_iterator<ProxyIterator<contiguous_iterator<int*>>>);
127 static_assert(!std::contiguous_iterator<ProxyIterator<contiguous_iterator<int*>>>);
129 template <class Iter>
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}}};
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);
145 template <class Iter>
146 constexpr void testForwardIteratorOperation() {
147 int data[] = {1, 2};
148 ProxyIterator<Iter> iter{Iter{data}};
150 std::same_as<ProxyIterator<Iter>> decltype(auto) it2 = iter++;
151 assert((*it2).data == 1);
152 assert((*iter).data == 2);
155 template <class Iter>
156 constexpr void testBidirectionalIteratorOperation() {
157 int data[] = {1, 2};
158 ProxyIterator<Iter> iter{Iter{data}};
159 ++iter;
160 assert((*iter).data == 2);
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;
168 std::same_as<ProxyIterator<Iter>> decltype(auto) iter3 = iter--;
169 assert((*iter).data == 1);
170 assert((*iter3).data == 2);
173 template <class Iter>
174 constexpr void testRandomAccessIteratorOperation() {
175 int data[] = {1, 2, 3, 4, 5};
176 ProxyIterator<Iter> iter{Iter{data}};
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);
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);
188 std::same_as<Proxy<int&>> decltype(auto) r = iter[2];
189 assert(r.data == 4);
191 std::same_as<ProxyIterator<Iter>> decltype(auto) iter4 = iter - 1;
192 assert((*iter4).data == 1);
194 std::same_as<ProxyIterator<Iter>> decltype(auto) iter5 = iter4 + 2;
195 assert((*iter5).data == 3);
197 std::same_as<ProxyIterator<Iter>> decltype(auto) iter6 = 3 + iter4;
198 assert((*iter6).data == 4);
200 std::same_as<std::iter_difference_t<Iter>> decltype(auto) n = iter6 - iter5;
201 assert(n == 1);
203 assert(iter4 < iter5);
204 assert(iter3 <= iter5);
205 assert(iter5 > iter4);
206 assert(iter6 >= iter4);
209 constexpr void testProxyIterator() {
210 // input iterator operations
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*>>();
219 // forward iterator operations
221 testForwardIteratorOperation<forward_iterator<int*>>();
222 testForwardIteratorOperation<bidirectional_iterator<int*>>();
223 testForwardIteratorOperation<random_access_iterator<int*>>();
224 testForwardIteratorOperation<contiguous_iterator<int*>>();
227 // bidirectional iterator operations
229 testBidirectionalIteratorOperation<bidirectional_iterator<int*>>();
230 testBidirectionalIteratorOperation<random_access_iterator<int*>>();
231 testBidirectionalIteratorOperation<contiguous_iterator<int*>>();
234 // random access iterator operations
236 testRandomAccessIteratorOperation<random_access_iterator<int*>>();
237 testRandomAccessIteratorOperation<contiguous_iterator<int*>>();
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));
250 template <class Iter>
251 concept StdMoveWorks = requires(std::iter_value_t<Iter> val, Iter iter) { val = std::move(*iter); };
253 static_assert(StdMoveWorks<MoveOnly*>);
254 static_assert(!StdMoveWorks<ProxyIterator<MoveOnly*>>);
256 // although this "works" but it actually creates a copy instead of move
257 static_assert(StdMoveWorks<ProxyIterator<int*>>);
259 using std::swap;
261 template <class Iter>
262 concept SwapWorks = requires(Iter iter1, Iter iter2) { swap(*iter1, *iter2); };
264 static_assert(SwapWorks<int*>);
265 static_assert(!SwapWorks<ProxyIterator<int*>>);
267 constexpr bool test() {
268 testProxy();
269 testProxyIterator();
270 testProxyRange();
272 // iter_move
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);
281 // iter_swap
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);
292 return true;
295 int main(int, char**) {
296 test();
297 static_assert(test());
299 return 0;