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
10
11// <iterator>
12//
13// template<indirectly_swappable<Iterator> Iterator2>
14// friend constexpr void
15// iter_swap(const move_iterator& x, const move_iterator<Iterator2>& y)
16// noexcept(noexcept(ranges::iter_swap(x.current, y.current))); // Since C++20
17
18#include <iterator>
19
20#include <cassert>
21#include <type_traits>
22#include <utility>
23#include "test_iterators.h"
24#include "test_macros.h"
25
26template <bool IsNoexcept>
27struct MaybeNoexceptSwap {
28 using value_type = int;
29 using difference_type = std::ptrdiff_t;
30
31 constexpr friend void iter_swap(MaybeNoexceptSwap, MaybeNoexceptSwap) noexcept(IsNoexcept) {
32 }
33
34 int& operator*() const { static int x; return x; }
35
36 MaybeNoexceptSwap& operator++();
37 MaybeNoexceptSwap operator++(int);
38};
39using ThrowingBase = MaybeNoexceptSwap<false>;
40using NoexceptBase = MaybeNoexceptSwap<true>;
41static_assert(std::input_iterator<ThrowingBase>);
42ASSERT_NOT_NOEXCEPT(std::ranges::iter_swap(std::declval<ThrowingBase>(), std::declval<ThrowingBase>()));
43ASSERT_NOEXCEPT(std::ranges::iter_swap(std::declval<NoexceptBase>(), std::declval<NoexceptBase>()));
44
45constexpr bool test() {
46 // Can use `iter_swap` with a regular array.
47 {
48 int a[] = {0, 1, 2};
49
50 std::move_iterator b(a);
51 std::move_iterator e(a + 2);
52 assert(a[0] == 0);
53 assert(a[2] == 2);
54
55 static_assert(std::same_as<decltype(iter_swap(b, e)), void>);
56 iter_swap(a: b, b: e);
57 assert(a[0] == 2);
58 assert(a[2] == 0);
59 }
60
61 // Check that the `iter_swap` customization point is being used.
62 {
63 int iter_swap_invocations = 0;
64 adl::Iterator base1 = adl::Iterator::TrackSwaps(iter_swap_invocations);
65 adl::Iterator base2 = adl::Iterator::TrackSwaps(iter_swap_invocations);
66 std::move_iterator<adl::Iterator> i1(base1), i2(base2);
67 iter_swap(i1, i2);
68 assert(iter_swap_invocations == 1);
69
70 iter_swap(i2, i1);
71 assert(iter_swap_invocations == 2);
72 }
73
74 // Check the `noexcept` specification.
75 {
76 using ThrowingIter = std::move_iterator<ThrowingBase>;
77 ASSERT_NOT_NOEXCEPT(iter_swap(a: std::declval<ThrowingIter>(), b: std::declval<ThrowingIter>()));
78 using NoexceptIter = std::move_iterator<NoexceptBase>;
79 ASSERT_NOEXCEPT(iter_swap(a: std::declval<NoexceptIter>(), b: std::declval<NoexceptIter>()));
80 }
81
82 return true;
83}
84
85int main(int, char**) {
86 test();
87 static_assert(test());
88
89 return 0;
90}
91

source code of libcxx/test/std/iterators/predef.iterators/move.iterators/move.iter.ops/move.iter.nonmember/iter_swap.pass.cpp