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 // template<indirectly_swappable<I> I2>
12 // friend constexpr void
13 // iter_swap(const counted_iterator& x, const counted_iterator<I2>& y)
14 // noexcept(noexcept(ranges::iter_swap(x.current, y.current)));
15
16 #include <iterator>
17
18 #include "test_macros.h"
19 #include "test_iterators.h"
20
21 template<bool IsNoexcept>
22 class HasNoexceptIterSwap
23 {
24 int *it_;
25
26 public:
27 typedef std::input_iterator_tag iterator_category;
28 typedef int value_type;
29 typedef typename std::iterator_traits<int *>::difference_type difference_type;
30 typedef int * pointer;
31 typedef int & reference;
32
base() const33 constexpr int *base() const {return it_;}
34
35 HasNoexceptIterSwap() = default;
HasNoexceptIterSwap(int * it)36 explicit constexpr HasNoexceptIterSwap(int *it) : it_(it) {}
37
operator *() const38 constexpr reference operator*() const {return *it_;}
39
operator ++()40 constexpr HasNoexceptIterSwap& operator++() {++it_; return *this;}
operator ++(int)41 constexpr HasNoexceptIterSwap operator++(int)
42 {HasNoexceptIterSwap tmp(*this); ++(*this); return tmp;}
43
iter_swap(const HasNoexceptIterSwap &,const HasNoexceptIterSwap &)44 friend void iter_swap(
45 const HasNoexceptIterSwap&, const HasNoexceptIterSwap&) noexcept(IsNoexcept) {}
46 };
47
test()48 constexpr bool test() {
49 int buffer[8] = {1, 2, 3, 4, 5, 6, 7, 8};
50
51 {
52 auto iter1 = cpp17_input_iterator<int*>(buffer);
53 auto commonIter1 = std::counted_iterator<decltype(iter1)>(iter1, 8);
54 auto commonIter2 = std::counted_iterator<decltype(iter1)>(iter1, 8);
55 for (auto i = 0; i < 4; ++i) ++commonIter2;
56 assert(*commonIter2 == 5);
57 std::ranges::iter_swap(commonIter1, commonIter2);
58 assert(*commonIter1 == 5);
59 assert(*commonIter2 == 1);
60 std::ranges::iter_swap(commonIter2, commonIter1);
61 }
62 {
63 auto iter1 = forward_iterator<int*>(buffer);
64 auto commonIter1 = std::counted_iterator<decltype(iter1)>(iter1, 8);
65 auto commonIter2 = std::counted_iterator<decltype(iter1)>(iter1, 8);
66 for (auto i = 0; i < 4; ++i) ++commonIter2;
67 assert(*commonIter2 == 5);
68 std::ranges::iter_swap(commonIter1, commonIter2);
69 assert(*commonIter1 == 5);
70 assert(*commonIter2 == 1);
71 std::ranges::iter_swap(commonIter2, commonIter1);
72 }
73 {
74 auto iter1 = random_access_iterator<int*>(buffer);
75 auto commonIter1 = std::counted_iterator<decltype(iter1)>(iter1, 8);
76 auto commonIter2 = std::counted_iterator<decltype(iter1)>(iter1, 8);
77 for (auto i = 0; i < 4; ++i) ++commonIter2;
78 assert(*commonIter2 == 5);
79 std::ranges::iter_swap(commonIter1, commonIter2);
80 assert(*commonIter1 == 5);
81 assert(*commonIter2 == 1);
82 std::ranges::iter_swap(commonIter2, commonIter1);
83 }
84
85 // Test noexceptness.
86 {
87 static_assert( noexcept(std::ranges::iter_swap(
88 std::declval<std::counted_iterator<HasNoexceptIterSwap<true>>&>(),
89 std::declval<std::counted_iterator<HasNoexceptIterSwap<true>>&>()
90 )));
91 static_assert(!noexcept(std::ranges::iter_swap(
92 std::declval<std::counted_iterator<HasNoexceptIterSwap<false>>&>(),
93 std::declval<std::counted_iterator<HasNoexceptIterSwap<false>>&>()
94 )));
95 }
96
97 return true;
98 }
99
main(int,char **)100 int main(int, char**) {
101 test();
102 static_assert(test());
103
104 return 0;
105 }
106