19d905319SNikolas Klauser //===----------------------------------------------------------------------===//
29d905319SNikolas Klauser //
39d905319SNikolas Klauser // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
49d905319SNikolas Klauser // See https://llvm.org/LICENSE.txt for license information.
59d905319SNikolas Klauser // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
69d905319SNikolas Klauser //
79d905319SNikolas Klauser //===----------------------------------------------------------------------===//
89d905319SNikolas Klauser 
99d905319SNikolas Klauser // <algorithm>
109d905319SNikolas Klauser 
119d905319SNikolas Klauser // UNSUPPORTED: c++03, c++11, c++14, c++17
129d905319SNikolas Klauser 
13fc3923faSArthur O'Dwyer // template<input_iterator I1, sentinel_for<I1> S1, input_iterator I2, sentinel_for<I2> S2>
14fc3923faSArthur O'Dwyer //   requires indirectly_swappable<I1, I2>
159d905319SNikolas Klauser //   constexpr ranges::swap_ranges_result<I1, I2>
169d905319SNikolas Klauser //     ranges::swap_ranges(I1 first1, S1 last1, I2 first2, S2 last2);
17fc3923faSArthur O'Dwyer // template<input_range R1, input_range R2>
18fc3923faSArthur O'Dwyer //   requires indirectly_swappable<iterator_t<R1>, iterator_t<R2>>
199d905319SNikolas Klauser //   constexpr ranges::swap_ranges_result<borrowed_iterator_t<R1>, borrowed_iterator_t<R2>>
209d905319SNikolas Klauser //     ranges::swap_ranges(R1&& r1, R2&& r2);
219d905319SNikolas Klauser 
229d905319SNikolas Klauser #include <algorithm>
239d905319SNikolas Klauser #include <array>
249d905319SNikolas Klauser #include <cassert>
259d905319SNikolas Klauser #include <ranges>
269d905319SNikolas Klauser 
279d905319SNikolas Klauser #include "test_iterators.h"
289d905319SNikolas Klauser 
test_different_lengths()299d905319SNikolas Klauser constexpr void test_different_lengths() {
309d905319SNikolas Klauser   using Expected = std::ranges::swap_ranges_result<int*, int*>;
319d905319SNikolas Klauser   int i[3] = {1, 2, 3};
329d905319SNikolas Klauser   int j[1] = {4};
339d905319SNikolas Klauser   std::same_as<Expected> auto r = std::ranges::swap_ranges(i, i + 3, j, j + 1);
349d905319SNikolas Klauser   assert(r.in1 == i + 1);
359d905319SNikolas Klauser   assert(r.in2 == j + 1);
369d905319SNikolas Klauser   assert(i[0] == 4);
379d905319SNikolas Klauser   assert(i[1] == 2);
389d905319SNikolas Klauser   assert(i[2] == 3);
399d905319SNikolas Klauser   assert(j[0] == 1);
409d905319SNikolas Klauser   std::same_as<Expected> auto r2 = std::ranges::swap_ranges(i, j);
419d905319SNikolas Klauser   assert(r2.in1 == i + 1);
429d905319SNikolas Klauser   assert(r2.in2 == j + 1);
439d905319SNikolas Klauser   assert(i[0] == 1);
449d905319SNikolas Klauser   assert(i[1] == 2);
459d905319SNikolas Klauser   assert(i[2] == 3);
469d905319SNikolas Klauser   assert(j[0] == 4);
479d905319SNikolas Klauser   std::same_as<Expected> auto r3 = std::ranges::swap_ranges(j, j + 1, i, i + 3);
489d905319SNikolas Klauser   assert(r3.in1 == j + 1);
499d905319SNikolas Klauser   assert(r3.in2 == i + 1);
509d905319SNikolas Klauser   assert(i[0] == 4);
519d905319SNikolas Klauser   assert(i[1] == 2);
529d905319SNikolas Klauser   assert(i[2] == 3);
539d905319SNikolas Klauser   assert(j[0] == 1);
549d905319SNikolas Klauser   std::same_as<Expected> auto r4 = std::ranges::swap_ranges(j, i);
559d905319SNikolas Klauser   assert(r4.in1 == j + 1);
569d905319SNikolas Klauser   assert(r4.in2 == i + 1);
579d905319SNikolas Klauser   assert(i[0] == 1);
589d905319SNikolas Klauser   assert(i[1] == 2);
599d905319SNikolas Klauser   assert(i[2] == 3);
609d905319SNikolas Klauser   assert(j[0] == 4);
619d905319SNikolas Klauser }
629d905319SNikolas Klauser 
test_range()639d905319SNikolas Klauser constexpr void test_range() {
649d905319SNikolas Klauser   std::array r1 = {1, 2, 3};
659d905319SNikolas Klauser   std::array r2 = {4, 5, 6};
669d905319SNikolas Klauser 
679d905319SNikolas Klauser 
68*d05bada5SDuo Wang   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);
699d905319SNikolas Klauser   assert(r.in1 == r1.end());
709d905319SNikolas Klauser   assert(r.in2 == r2.end());
719d905319SNikolas Klauser 
729d905319SNikolas Klauser   assert((r1 == std::array{4, 5, 6}));
739d905319SNikolas Klauser   assert((r2 == std::array{1, 2, 3}));
749d905319SNikolas Klauser }
759d905319SNikolas Klauser 
test_borrowed_input_range()769d905319SNikolas Klauser constexpr void test_borrowed_input_range() {
779d905319SNikolas Klauser   {
789d905319SNikolas Klauser     int r1[] = {1, 2, 3};
799d905319SNikolas Klauser     int r2[] = {4, 5, 6};
809d905319SNikolas Klauser     std::ranges::swap_ranges(std::views::all(r1), r2);
819d905319SNikolas Klauser     assert(r1[0] == 4);
829d905319SNikolas Klauser     assert(r1[1] == 5);
839d905319SNikolas Klauser     assert(r1[2] == 6);
849d905319SNikolas Klauser     assert(r2[0] == 1);
859d905319SNikolas Klauser     assert(r2[1] == 2);
869d905319SNikolas Klauser     assert(r2[2] == 3);
879d905319SNikolas Klauser   }
889d905319SNikolas Klauser   {
899d905319SNikolas Klauser     int r1[] = {1, 2, 3};
909d905319SNikolas Klauser     int r2[] = {4, 5, 6};
919d905319SNikolas Klauser     std::ranges::swap_ranges(r1, std::views::all(r2));
929d905319SNikolas Klauser     assert(r1[0] == 4);
939d905319SNikolas Klauser     assert(r1[1] == 5);
949d905319SNikolas Klauser     assert(r1[2] == 6);
959d905319SNikolas Klauser     assert(r2[0] == 1);
969d905319SNikolas Klauser     assert(r2[1] == 2);
979d905319SNikolas Klauser     assert(r2[2] == 3);
989d905319SNikolas Klauser   }
999d905319SNikolas Klauser   {
1009d905319SNikolas Klauser     int r1[] = {1, 2, 3};
1019d905319SNikolas Klauser     int r2[] = {4, 5, 6};
1029d905319SNikolas Klauser     std::ranges::swap_ranges(std::views::all(r1), std::views::all(r2));
1039d905319SNikolas Klauser     assert(r1[0] == 4);
1049d905319SNikolas Klauser     assert(r1[1] == 5);
1059d905319SNikolas Klauser     assert(r1[2] == 6);
1069d905319SNikolas Klauser     assert(r2[0] == 1);
1079d905319SNikolas Klauser     assert(r2[1] == 2);
1089d905319SNikolas Klauser     assert(r2[2] == 3);
1099d905319SNikolas Klauser   }
1109d905319SNikolas Klauser }
1119d905319SNikolas Klauser 
test_sentinel()1129d905319SNikolas Klauser constexpr void test_sentinel() {
1139d905319SNikolas Klauser   int i[3] = {1, 2, 3};
1149d905319SNikolas Klauser   int j[3] = {4, 5, 6};
1159d905319SNikolas Klauser   using It = cpp17_input_iterator<int*>;
1169d905319SNikolas Klauser   using Sent = sentinel_wrapper<It>;
1179d905319SNikolas Klauser   using Expected = std::ranges::swap_ranges_result<It, It>;
1189d905319SNikolas Klauser   std::same_as<Expected> auto r =
1199d905319SNikolas Klauser       std::ranges::swap_ranges(It(i), Sent(It(i + 3)), It(j), Sent(It(j + 3)));
1209d905319SNikolas Klauser   assert(base(r.in1) == i + 3);
1219d905319SNikolas Klauser   assert(base(r.in2) == j + 3);
1229d905319SNikolas Klauser   assert(i[0] == 4);
1239d905319SNikolas Klauser   assert(i[1] == 5);
1249d905319SNikolas Klauser   assert(i[2] == 6);
1259d905319SNikolas Klauser   assert(j[0] == 1);
1269d905319SNikolas Klauser   assert(j[1] == 2);
1279d905319SNikolas Klauser   assert(j[2] == 3);
1289d905319SNikolas Klauser }
1299d905319SNikolas Klauser 
1309d905319SNikolas Klauser template <class Iter1, class Iter2>
test_iterators()1319d905319SNikolas Klauser constexpr void test_iterators() {
1329d905319SNikolas Klauser   using Expected = std::ranges::swap_ranges_result<Iter1, Iter2>;
1339d905319SNikolas Klauser   int i[3] = {1, 2, 3};
1349d905319SNikolas Klauser   int j[3] = {4, 5, 6};
1359d905319SNikolas Klauser   std::same_as<Expected> auto r =
1369d905319SNikolas Klauser       std::ranges::swap_ranges(Iter1(i), sentinel_wrapper(Iter1(i + 3)), Iter2(j), sentinel_wrapper(Iter2(j + 3)));
1379d905319SNikolas Klauser   assert(base(r.in1) == i + 3);
1389d905319SNikolas Klauser   assert(base(r.in2) == j + 3);
1399d905319SNikolas Klauser   assert(i[0] == 4);
1409d905319SNikolas Klauser   assert(i[1] == 5);
1419d905319SNikolas Klauser   assert(i[2] == 6);
1429d905319SNikolas Klauser   assert(j[0] == 1);
1439d905319SNikolas Klauser   assert(j[1] == 2);
1449d905319SNikolas Klauser   assert(j[2] == 3);
1459d905319SNikolas Klauser }
1469d905319SNikolas Klauser 
test_rval_range()1479d905319SNikolas Klauser constexpr void test_rval_range() {
1489d905319SNikolas Klauser   {
149*d05bada5SDuo Wang     using Expected = std::ranges::swap_ranges_result<std::array<int, 3>::iterator, std::ranges::dangling>;
1509d905319SNikolas Klauser     std::array<int, 3> r = {1, 2, 3};
1519d905319SNikolas Klauser     std::same_as<Expected> auto a = std::ranges::swap_ranges(r, std::array{4, 5, 6});
1529d905319SNikolas Klauser     assert((r == std::array{4, 5, 6}));
1539d905319SNikolas Klauser     assert(a.in1 == r.begin() + 3);
1549d905319SNikolas Klauser   }
1559d905319SNikolas Klauser   {
1569d905319SNikolas Klauser     std::array<int, 3> r = {1, 2, 3};
157*d05bada5SDuo Wang     using Expected = std::ranges::swap_ranges_result<std::ranges::dangling, std::array<int, 3>::iterator>;
1589d905319SNikolas Klauser     std::same_as<Expected> auto b = std::ranges::swap_ranges(std::array{4, 5, 6}, r);
1599d905319SNikolas Klauser     assert((r == std::array{4, 5, 6}));
1609d905319SNikolas Klauser     assert(b.in2 == r.begin() + 3);
1619d905319SNikolas Klauser   }
1629d905319SNikolas Klauser }
1639d905319SNikolas Klauser 
164a81cc1fcSHui Xie template <class Out>
test_proxy_in_iterators()165a81cc1fcSHui Xie constexpr void test_proxy_in_iterators() {
166a81cc1fcSHui Xie   test_iterators<ProxyIterator<cpp20_input_iterator<int*>>, Out>();
167a81cc1fcSHui Xie   test_iterators<ProxyIterator<forward_iterator<int*>>, Out>();
168a81cc1fcSHui Xie   test_iterators<ProxyIterator<bidirectional_iterator<int*>>, Out>();
169a81cc1fcSHui Xie   test_iterators<ProxyIterator<random_access_iterator<int*>>, Out>();
170a81cc1fcSHui Xie   test_iterators<ProxyIterator<contiguous_iterator<int*>>, Out>();
171a81cc1fcSHui Xie }
172a81cc1fcSHui Xie 
test()1739d905319SNikolas Klauser constexpr bool test() {
1749d905319SNikolas Klauser   test_range();
1759d905319SNikolas Klauser 
1769d905319SNikolas Klauser   test_iterators<cpp20_input_iterator<int*>, cpp20_input_iterator<int*>>();
1779d905319SNikolas Klauser   test_iterators<cpp20_input_iterator<int*>, forward_iterator<int*>>();
1789d905319SNikolas Klauser   test_iterators<cpp20_input_iterator<int*>, bidirectional_iterator<int*>>();
1799d905319SNikolas Klauser   test_iterators<cpp20_input_iterator<int*>, random_access_iterator<int*>>();
1809d905319SNikolas Klauser   test_iterators<cpp20_input_iterator<int*>, int*>();
1819d905319SNikolas Klauser 
1829d905319SNikolas Klauser   test_iterators<forward_iterator<int*>, cpp20_input_iterator<int*>>();
1839d905319SNikolas Klauser   test_iterators<forward_iterator<int*>, forward_iterator<int*>>();
1849d905319SNikolas Klauser   test_iterators<forward_iterator<int*>, bidirectional_iterator<int*>>();
1859d905319SNikolas Klauser   test_iterators<forward_iterator<int*>, random_access_iterator<int*>>();
1869d905319SNikolas Klauser   test_iterators<forward_iterator<int*>, int*>();
1879d905319SNikolas Klauser 
1889d905319SNikolas Klauser   test_iterators<bidirectional_iterator<int*>, cpp20_input_iterator<int*>>();
1899d905319SNikolas Klauser   test_iterators<bidirectional_iterator<int*>, forward_iterator<int*>>();
1909d905319SNikolas Klauser   test_iterators<bidirectional_iterator<int*>, bidirectional_iterator<int*>>();
1919d905319SNikolas Klauser   test_iterators<bidirectional_iterator<int*>, random_access_iterator<int*>>();
1929d905319SNikolas Klauser   test_iterators<bidirectional_iterator<int*>, int*>();
1939d905319SNikolas Klauser 
1949d905319SNikolas Klauser   test_iterators<random_access_iterator<int*>, cpp20_input_iterator<int*>>();
1959d905319SNikolas Klauser   test_iterators<random_access_iterator<int*>, forward_iterator<int*>>();
1969d905319SNikolas Klauser   test_iterators<random_access_iterator<int*>, bidirectional_iterator<int*>>();
1979d905319SNikolas Klauser   test_iterators<random_access_iterator<int*>, random_access_iterator<int*>>();
1989d905319SNikolas Klauser   test_iterators<random_access_iterator<int*>, int*>();
1999d905319SNikolas Klauser 
2009d905319SNikolas Klauser   test_iterators<int*, cpp20_input_iterator<int*>>();
2019d905319SNikolas Klauser   test_iterators<int*, forward_iterator<int*>>();
2029d905319SNikolas Klauser   test_iterators<int*, bidirectional_iterator<int*>>();
2039d905319SNikolas Klauser   test_iterators<int*, random_access_iterator<int*>>();
2049d905319SNikolas Klauser   test_iterators<int*, int*>();
2059d905319SNikolas Klauser 
206a81cc1fcSHui Xie   test_proxy_in_iterators<ProxyIterator<cpp20_input_iterator<int*>>>();
207a81cc1fcSHui Xie   test_proxy_in_iterators<ProxyIterator<forward_iterator<int*>>>();
208a81cc1fcSHui Xie   test_proxy_in_iterators<ProxyIterator<bidirectional_iterator<int*>>>();
209a81cc1fcSHui Xie   test_proxy_in_iterators<ProxyIterator<random_access_iterator<int*>>>();
210a81cc1fcSHui Xie   test_proxy_in_iterators<ProxyIterator<contiguous_iterator<int*>>>();
211a81cc1fcSHui Xie 
2129d905319SNikolas Klauser   test_sentinel();
2139d905319SNikolas Klauser   test_different_lengths();
2149d905319SNikolas Klauser   test_borrowed_input_range();
2159d905319SNikolas Klauser   test_rval_range();
2169d905319SNikolas Klauser 
2179d905319SNikolas Klauser   return true;
2189d905319SNikolas Klauser }
2199d905319SNikolas Klauser 
2209d905319SNikolas Klauser static_assert(std::same_as<std::ranges::swap_ranges_result<int, char>, std::ranges::in_in_result<int, char>>);
2219d905319SNikolas Klauser 
main(int,char **)2229d905319SNikolas Klauser int main(int, char**) {
2239d905319SNikolas Klauser   test();
2249d905319SNikolas Klauser   static_assert(test());
2259d905319SNikolas Klauser 
2269d905319SNikolas Klauser   return 0;
2279d905319SNikolas Klauser }
228