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// template<ForwardIterator Iter1, ForwardIterator Iter2>
12// requires HasSwap<Iter1::reference, Iter2::reference>
13// Iter2
14// swap_ranges(Iter1 first1, Iter1 last1, Iter2 first2);
15
16#include <algorithm>
17#include <array>
18#include <cassert>
19#include <memory>
20#include <type_traits>
21#include <utility>
22#include <vector>
23
24#include "test_macros.h"
25#include "test_iterators.h"
26#include "type_algorithms.h"
27
28struct TestPtr {
29 template <class Iter>
30 TEST_CONSTEXPR_CXX20 void operator()() {
31 types::for_each(types::forward_iterator_list<int*>(), TestImpl<Iter>());
32 }
33
34 template <class Iter1>
35 struct TestImpl {
36 template <class Iter2>
37 TEST_CONSTEXPR_CXX20 void operator()() {
38 { // Basic test case: swapping three elements between two arrays
39 int a[] = {1, 2, 3};
40 int b[] = {4, 5, 6};
41 Iter2 r = std::swap_ranges(Iter1(a), Iter1(a + 3), Iter2(b));
42 assert(base(r) == b + 3);
43 assert(a[0] == 4 && a[1] == 5 && a[2] == 6);
44 assert(b[0] == 1 && b[1] == 2 && b[2] == 3);
45 }
46 { // Large-scale test: swapping 100 elements between two different containers
47 const int N = 100;
48 std::array<int, N> a;
49 std::vector<int> b(N + 2, 42);
50 b.front() = 1;
51 b.back() = -1;
52 for (int i = 0; i < N; ++i)
53 a[i] = i * i + 1;
54 Iter2 r = std::swap_ranges(Iter1(a.data()), Iter1(a.data() + N), Iter2(b.data() + 1));
55 assert(base(r) == b.data() + N + 1);
56 assert(b.front() == 1); // Ensure that the unswapped portion remains unchanged
57 assert(b.back() == -1);
58 for (int i = 0; i < N; ++i) {
59 assert(a[i] == 42);
60 assert(b[i + 1] == i * i + 1);
61 }
62 }
63 }
64 };
65};
66
67#if TEST_STD_VER >= 11
68struct TestUniquePtr {
69 template <class Iter>
70 TEST_CONSTEXPR_CXX23 void operator()() {
71 types::for_each(types::forward_iterator_list<std::unique_ptr<int>*>(), TestImpl<Iter>());
72 }
73
74 template <class Iter1>
75 struct TestImpl {
76 template <class Iter2>
77 TEST_CONSTEXPR_CXX23 void operator()() {
78 std::unique_ptr<int> a[3];
79 for (int k = 0; k < 3; ++k)
80 a[k].reset(new int(k + 1));
81 std::unique_ptr<int> b[3];
82 for (int k = 0; k < 3; ++k)
83 b[k].reset(new int(k + 4));
84 Iter2 r = std::swap_ranges(Iter1(a), Iter1(a + 3), Iter2(b));
85 assert(base(r) == b + 3);
86 assert(*a[0] == 4 && *a[1] == 5 && *a[2] == 6);
87 assert(*b[0] == 1 && *b[1] == 2 && *b[2] == 3);
88 }
89 };
90};
91#endif
92
93template <template <class> class Iter1, template <class> class Iter2>
94TEST_CONSTEXPR_CXX20 bool test_simple_cases() {
95 {
96 int a[2] = {1, 2};
97 int b[2] = {4, 5};
98 std::swap_ranges(Iter1<int*>(a), Iter1<int*>(a + 2), Iter2<int*>(b));
99 assert(a[0] == 4 && a[1] == 5);
100 assert(b[0] == 1 && b[1] == 2);
101 }
102 {
103 std::array<int, 3> a = {1, 2, 3}, a0 = a;
104 std::array<int, 3> b = {4, 5, 6}, b0 = b;
105 using It1 = Iter1<std::array<int, 3>::iterator>;
106 using It2 = Iter2<std::array<int, 3>::iterator>;
107 std::swap_ranges(It1(a.begin()), It1(a.end()), It2(b.begin()));
108 assert(a == b0);
109 assert(b == a0);
110 }
111 {
112 std::array<std::array<int, 2>, 2> a = {._M_elems: {{0, 1}, {2, 3}}}, a0 = a;
113 std::array<std::array<int, 2>, 2> b = {._M_elems: {{9, 8}, {7, 6}}}, b0 = b;
114 using It1 = Iter1<std::array<std::array<int, 2>, 2>::iterator>;
115 using It2 = Iter2<std::array<std::array<int, 2>, 2>::iterator>;
116 std::swap_ranges(It1(a.begin()), It1(a.end()), It2(b.begin()));
117 assert(a == b0);
118 assert(b == a0);
119 }
120 {
121 std::array<std::array<int, 3>, 3> a = {._M_elems: {{0, 1, 2}, {3, 4, 5}, {6, 7, 8}}}, a0 = a;
122 std::array<std::array<int, 3>, 3> b = {._M_elems: {{9, 8, 7}, {6, 5, 4}, {3, 2, 1}}}, b0 = b;
123 using It1 = Iter1<std::array<std::array<int, 3>, 3>::iterator>;
124 using It2 = Iter2<std::array<std::array<int, 3>, 3>::iterator>;
125 std::swap_ranges(It1(a.begin()), It1(a.end()), It2(b.begin()));
126 assert(a == b0);
127 assert(b == a0);
128 }
129
130 return true;
131}
132
133template <std::size_t N>
134TEST_CONSTEXPR_CXX20 void test_vector_bool() {
135 std::vector<bool> f(N, false), t(N, true);
136 { // Test swap_ranges() with aligned bytes
137 std::vector<bool> f1 = f, t1 = t;
138 std::swap_ranges(f1.begin(), f1.end(), t1.begin());
139 assert(f1 == t);
140 assert(t1 == f);
141 }
142 { // Test swap_ranges() with unaligned bytes
143 std::vector<bool> f1(N, false), t1(N + 8, true);
144 std::swap_ranges(f1.begin(), f1.end(), t1.begin() + 4);
145 assert(std::equal(f1.begin(), f1.end(), t.begin()));
146 assert(std::equal(t1.begin() + 4, t1.end() - 4, f.begin()));
147 }
148}
149
150TEST_CONSTEXPR_CXX20 bool test() {
151 test_simple_cases<forward_iterator, forward_iterator>();
152 test_simple_cases<forward_iterator, bidirectional_iterator>();
153 test_simple_cases<forward_iterator, random_access_iterator>();
154 test_simple_cases<bidirectional_iterator, forward_iterator>();
155 test_simple_cases<bidirectional_iterator, bidirectional_iterator>();
156 test_simple_cases<bidirectional_iterator, random_access_iterator>();
157 test_simple_cases<random_access_iterator, random_access_iterator>();
158#if TEST_STD_VER >= 20
159 test_simple_cases<std::type_identity_t, std::type_identity_t>();
160#endif
161
162 types::for_each(types::forward_iterator_list<int*>(), TestPtr());
163
164#if TEST_STD_VER >= 11
165 // We can't test unique_ptr in constant evaluation before C++23 as it's constexpr only since C++23.
166 if (TEST_STD_AT_LEAST_23_OR_RUNTIME_EVALUATED)
167 types::for_each(types::forward_iterator_list<std::unique_ptr<int>*>(), TestUniquePtr());
168#endif
169
170 { // Test vector<bool>::iterator optimization
171 test_vector_bool<8>();
172 test_vector_bool<19>();
173 test_vector_bool<32>();
174 test_vector_bool<49>();
175 test_vector_bool<64>();
176 test_vector_bool<199>();
177 test_vector_bool<256>();
178 }
179
180 return true;
181}
182
183int main(int, char**) {
184 test();
185#if TEST_STD_VER >= 20
186 static_assert(test());
187#endif
188
189 return 0;
190}
191

source code of libcxx/test/std/algorithms/alg.modifying.operations/alg.swap/swap_ranges.pass.cpp