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<input_iterator I1, sentinel_for<I1> S1, input_iterator I2, sentinel_for<I2> S2>
14 //   requires indirectly_swappable<I1, I2>
15 //   constexpr ranges::swap_ranges_result<I1, I2>
16 //     ranges::swap_ranges(I1 first1, S1 last1, I2 first2, S2 last2);
17 // template<input_range R1, input_range R2>
18 //   requires indirectly_swappable<iterator_t<R1>, iterator_t<R2>>
19 //   constexpr ranges::swap_ranges_result<borrowed_iterator_t<R1>, borrowed_iterator_t<R2>>
20 //     ranges::swap_ranges(R1&& r1, R2&& r2);
21 
22 #include <algorithm>
23 #include <array>
24 #include <cassert>
25 #include <ranges>
26 
27 #include "test_iterators.h"
28 
test_different_lengths()29 constexpr void test_different_lengths() {
30   using Expected = std::ranges::swap_ranges_result<int*, int*>;
31   int i[3] = {1, 2, 3};
32   int j[1] = {4};
33   std::same_as<Expected> auto r = std::ranges::swap_ranges(i, i + 3, j, j + 1);
34   assert(r.in1 == i + 1);
35   assert(r.in2 == j + 1);
36   assert(i[0] == 4);
37   assert(i[1] == 2);
38   assert(i[2] == 3);
39   assert(j[0] == 1);
40   std::same_as<Expected> auto r2 = std::ranges::swap_ranges(i, j);
41   assert(r2.in1 == i + 1);
42   assert(r2.in2 == j + 1);
43   assert(i[0] == 1);
44   assert(i[1] == 2);
45   assert(i[2] == 3);
46   assert(j[0] == 4);
47   std::same_as<Expected> auto r3 = std::ranges::swap_ranges(j, j + 1, i, i + 3);
48   assert(r3.in1 == j + 1);
49   assert(r3.in2 == i + 1);
50   assert(i[0] == 4);
51   assert(i[1] == 2);
52   assert(i[2] == 3);
53   assert(j[0] == 1);
54   std::same_as<Expected> auto r4 = std::ranges::swap_ranges(j, i);
55   assert(r4.in1 == j + 1);
56   assert(r4.in2 == i + 1);
57   assert(i[0] == 1);
58   assert(i[1] == 2);
59   assert(i[2] == 3);
60   assert(j[0] == 4);
61 }
62 
test_range()63 constexpr void test_range() {
64   std::array r1 = {1, 2, 3};
65   std::array r2 = {4, 5, 6};
66 
67 
68   std::same_as<std::ranges::in_in_result<std::array<int, 3>::iterator, std::array<int, 3>::iterator>> auto r = std::ranges::swap_ranges(r1, r2);
69   assert(r.in1 == r1.end());
70   assert(r.in2 == r2.end());
71 
72   assert((r1 == std::array{4, 5, 6}));
73   assert((r2 == std::array{1, 2, 3}));
74 }
75 
test_borrowed_input_range()76 constexpr void test_borrowed_input_range() {
77   {
78     int r1[] = {1, 2, 3};
79     int r2[] = {4, 5, 6};
80     std::ranges::swap_ranges(std::views::all(r1), r2);
81     assert(r1[0] == 4);
82     assert(r1[1] == 5);
83     assert(r1[2] == 6);
84     assert(r2[0] == 1);
85     assert(r2[1] == 2);
86     assert(r2[2] == 3);
87   }
88   {
89     int r1[] = {1, 2, 3};
90     int r2[] = {4, 5, 6};
91     std::ranges::swap_ranges(r1, std::views::all(r2));
92     assert(r1[0] == 4);
93     assert(r1[1] == 5);
94     assert(r1[2] == 6);
95     assert(r2[0] == 1);
96     assert(r2[1] == 2);
97     assert(r2[2] == 3);
98   }
99   {
100     int r1[] = {1, 2, 3};
101     int r2[] = {4, 5, 6};
102     std::ranges::swap_ranges(std::views::all(r1), std::views::all(r2));
103     assert(r1[0] == 4);
104     assert(r1[1] == 5);
105     assert(r1[2] == 6);
106     assert(r2[0] == 1);
107     assert(r2[1] == 2);
108     assert(r2[2] == 3);
109   }
110 }
111 
test_sentinel()112 constexpr void test_sentinel() {
113   int i[3] = {1, 2, 3};
114   int j[3] = {4, 5, 6};
115   using It = cpp17_input_iterator<int*>;
116   using Sent = sentinel_wrapper<It>;
117   using Expected = std::ranges::swap_ranges_result<It, It>;
118   std::same_as<Expected> auto r =
119       std::ranges::swap_ranges(It(i), Sent(It(i + 3)), It(j), Sent(It(j + 3)));
120   assert(base(r.in1) == i + 3);
121   assert(base(r.in2) == j + 3);
122   assert(i[0] == 4);
123   assert(i[1] == 5);
124   assert(i[2] == 6);
125   assert(j[0] == 1);
126   assert(j[1] == 2);
127   assert(j[2] == 3);
128 }
129 
130 template <class Iter1, class Iter2>
test_iterators()131 constexpr void test_iterators() {
132   using Expected = std::ranges::swap_ranges_result<Iter1, Iter2>;
133   int i[3] = {1, 2, 3};
134   int j[3] = {4, 5, 6};
135   std::same_as<Expected> auto r =
136       std::ranges::swap_ranges(Iter1(i), sentinel_wrapper(Iter1(i + 3)), Iter2(j), sentinel_wrapper(Iter2(j + 3)));
137   assert(base(r.in1) == i + 3);
138   assert(base(r.in2) == j + 3);
139   assert(i[0] == 4);
140   assert(i[1] == 5);
141   assert(i[2] == 6);
142   assert(j[0] == 1);
143   assert(j[1] == 2);
144   assert(j[2] == 3);
145 }
146 
test_rval_range()147 constexpr void test_rval_range() {
148   {
149     using Expected = std::ranges::swap_ranges_result<std::array<int, 3>::iterator, std::ranges::dangling>;
150     std::array<int, 3> r = {1, 2, 3};
151     std::same_as<Expected> auto a = std::ranges::swap_ranges(r, std::array{4, 5, 6});
152     assert((r == std::array{4, 5, 6}));
153     assert(a.in1 == r.begin() + 3);
154   }
155   {
156     std::array<int, 3> r = {1, 2, 3};
157     using Expected = std::ranges::swap_ranges_result<std::ranges::dangling, std::array<int, 3>::iterator>;
158     std::same_as<Expected> auto b = std::ranges::swap_ranges(std::array{4, 5, 6}, r);
159     assert((r == std::array{4, 5, 6}));
160     assert(b.in2 == r.begin() + 3);
161   }
162 }
163 
164 template <class Out>
test_proxy_in_iterators()165 constexpr void test_proxy_in_iterators() {
166   test_iterators<ProxyIterator<cpp20_input_iterator<int*>>, Out>();
167   test_iterators<ProxyIterator<forward_iterator<int*>>, Out>();
168   test_iterators<ProxyIterator<bidirectional_iterator<int*>>, Out>();
169   test_iterators<ProxyIterator<random_access_iterator<int*>>, Out>();
170   test_iterators<ProxyIterator<contiguous_iterator<int*>>, Out>();
171 }
172 
test()173 constexpr bool test() {
174   test_range();
175 
176   test_iterators<cpp20_input_iterator<int*>, cpp20_input_iterator<int*>>();
177   test_iterators<cpp20_input_iterator<int*>, forward_iterator<int*>>();
178   test_iterators<cpp20_input_iterator<int*>, bidirectional_iterator<int*>>();
179   test_iterators<cpp20_input_iterator<int*>, random_access_iterator<int*>>();
180   test_iterators<cpp20_input_iterator<int*>, int*>();
181 
182   test_iterators<forward_iterator<int*>, cpp20_input_iterator<int*>>();
183   test_iterators<forward_iterator<int*>, forward_iterator<int*>>();
184   test_iterators<forward_iterator<int*>, bidirectional_iterator<int*>>();
185   test_iterators<forward_iterator<int*>, random_access_iterator<int*>>();
186   test_iterators<forward_iterator<int*>, int*>();
187 
188   test_iterators<bidirectional_iterator<int*>, cpp20_input_iterator<int*>>();
189   test_iterators<bidirectional_iterator<int*>, forward_iterator<int*>>();
190   test_iterators<bidirectional_iterator<int*>, bidirectional_iterator<int*>>();
191   test_iterators<bidirectional_iterator<int*>, random_access_iterator<int*>>();
192   test_iterators<bidirectional_iterator<int*>, int*>();
193 
194   test_iterators<random_access_iterator<int*>, cpp20_input_iterator<int*>>();
195   test_iterators<random_access_iterator<int*>, forward_iterator<int*>>();
196   test_iterators<random_access_iterator<int*>, bidirectional_iterator<int*>>();
197   test_iterators<random_access_iterator<int*>, random_access_iterator<int*>>();
198   test_iterators<random_access_iterator<int*>, int*>();
199 
200   test_iterators<int*, cpp20_input_iterator<int*>>();
201   test_iterators<int*, forward_iterator<int*>>();
202   test_iterators<int*, bidirectional_iterator<int*>>();
203   test_iterators<int*, random_access_iterator<int*>>();
204   test_iterators<int*, int*>();
205 
206   test_proxy_in_iterators<ProxyIterator<cpp20_input_iterator<int*>>>();
207   test_proxy_in_iterators<ProxyIterator<forward_iterator<int*>>>();
208   test_proxy_in_iterators<ProxyIterator<bidirectional_iterator<int*>>>();
209   test_proxy_in_iterators<ProxyIterator<random_access_iterator<int*>>>();
210   test_proxy_in_iterators<ProxyIterator<contiguous_iterator<int*>>>();
211 
212   test_sentinel();
213   test_different_lengths();
214   test_borrowed_input_range();
215   test_rval_range();
216 
217   return true;
218 }
219 
220 static_assert(std::same_as<std::ranges::swap_ranges_result<int, char>, std::ranges::in_in_result<int, char>>);
221 
main(int,char **)222 int main(int, char**) {
223   test();
224   static_assert(test());
225 
226   return 0;
227 }
228