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// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
10
11// friend constexpr void iter_swap(const iterator& l, const iterator& r) noexcept(see below)
12// requires (indirectly_swappable<iterator_t<maybe-const<Const, Views>>> && ...);
13
14#include <array>
15#include <cassert>
16#include <ranges>
17
18#include "../types.h"
19
20struct ThrowingMove {
21 ThrowingMove() = default;
22 ThrowingMove(ThrowingMove&&) {}
23 ThrowingMove& operator=(ThrowingMove&&){return *this;}
24};
25
26constexpr bool test() {
27 {
28 std::array a1{1, 2, 3, 4};
29 std::array a2{0.1, 0.2, 0.3};
30 std::ranges::zip_view v(a1, a2);
31 auto iter1 = v.begin();
32 auto iter2 = ++v.begin();
33
34 std::ranges::iter_swap(iter1, iter2);
35
36 assert(a1[0] == 2);
37 assert(a1[1] == 1);
38 assert(a2[0] == 0.2);
39 assert(a2[1] == 0.1);
40
41 auto [x1, y1] = *iter1;
42 assert(&x1 == &a1[0]);
43 assert(&y1 == &a2[0]);
44
45 auto [x2, y2] = *iter2;
46 assert(&x2 == &a1[1]);
47 assert(&y2 == &a2[1]);
48
49 static_assert(noexcept(std::ranges::iter_swap(iter1, iter2)));
50 }
51
52 {
53 // underlying iter_swap may throw
54 std::array<ThrowingMove, 2> iterSwapMayThrow{};
55 std::ranges::zip_view v(iterSwapMayThrow);
56 auto iter1 = v.begin();
57 auto iter2 = ++v.begin();
58 static_assert(!noexcept(std::ranges::iter_swap(iter1, iter2)));
59 }
60
61 {
62 // underlying iterators' iter_move are called through ranges::iter_swap
63 adltest::IterMoveSwapRange r1, r2;
64 assert(r1.iter_swap_called_times == 0);
65 assert(r2.iter_swap_called_times == 0);
66
67 std::ranges::zip_view v{r1, r2};
68 auto it1 = v.begin();
69 auto it2 = std::ranges::next(it1, 3);
70
71 std::ranges::iter_swap(it1, it2);
72 assert(r1.iter_swap_called_times == 2);
73 assert(r2.iter_swap_called_times == 2);
74
75 std::ranges::iter_swap(it1, it2);
76 assert(r1.iter_swap_called_times == 4);
77 assert(r2.iter_swap_called_times == 4);
78 }
79 return true;
80}
81
82int main(int, char**) {
83 test();
84 static_assert(test());
85
86 return 0;
87}
88

source code of libcxx/test/std/ranges/range.adaptors/range.zip/iterator/iter_swap.pass.cpp