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