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// reverse_iterator
14//
15// template<indirectly_swappable<Iterator> Iterator2>
16// friend constexpr void
17// iter_swap(const reverse_iterator& x,
18// const reverse_iterator<Iterator2>& y) noexcept(see below);
19
20#include <iterator>
21
22#include <cassert>
23#include <type_traits>
24#include <utility>
25#include "test_iterators.h"
26#include "test_macros.h"
27
28constexpr bool test() {
29 // Can use `iter_swap` with a regular array.
30 {
31 constexpr int N = 3;
32 int a[N] = {0, 1, 2};
33
34 std::reverse_iterator<int*> rb(a + N);
35 std::reverse_iterator<int*> re(a + 1);
36 assert(a[0] == 0);
37 assert(a[2] == 2);
38
39 static_assert(std::same_as<decltype(iter_swap(rb, re)), void>);
40 iter_swap(a: rb, b: re);
41 assert(a[0] == 2);
42 assert(a[2] == 0);
43 }
44
45 // Check that the `iter_swap` customization point is being used.
46 {
47 int iter_swap_invocations = 0;
48 int a[] = {0, 1, 2};
49 adl::Iterator base1 = adl::Iterator::TrackSwaps(a + 1, iter_swap_invocations);
50 adl::Iterator base2 = adl::Iterator::TrackSwaps(a + 2, iter_swap_invocations);
51 std::reverse_iterator<adl::Iterator> ri1(base1), ri2(base2);
52 iter_swap(ri1, ri2);
53 assert(iter_swap_invocations == 1);
54
55 iter_swap(ri2, ri1);
56 assert(iter_swap_invocations == 2);
57 }
58
59 // Check the `noexcept` specification.
60 {
61 {
62 struct ThrowingCopyNoexceptDecrement {
63 using value_type = int;
64 using difference_type = std::ptrdiff_t;
65
66 ThrowingCopyNoexceptDecrement();
67 ThrowingCopyNoexceptDecrement(const ThrowingCopyNoexceptDecrement&);
68
69 int& operator*() const noexcept { static int x; return x; }
70
71 ThrowingCopyNoexceptDecrement& operator++();
72 ThrowingCopyNoexceptDecrement operator++(int);
73 ThrowingCopyNoexceptDecrement& operator--() noexcept;
74 ThrowingCopyNoexceptDecrement operator--(int) noexcept;
75
76 bool operator==(const ThrowingCopyNoexceptDecrement&) const = default;
77 };
78 static_assert(std::bidirectional_iterator<ThrowingCopyNoexceptDecrement>);
79
80 static_assert(!std::is_nothrow_copy_constructible_v<ThrowingCopyNoexceptDecrement>);
81 static_assert( std::is_nothrow_copy_constructible_v<int*>);
82 ASSERT_NOEXCEPT(std::ranges::iter_swap(--std::declval<ThrowingCopyNoexceptDecrement&>(), --std::declval<int*&>()));
83 using RI1 = std::reverse_iterator<ThrowingCopyNoexceptDecrement>;
84 using RI2 = std::reverse_iterator<int*>;
85 ASSERT_NOT_NOEXCEPT(iter_swap(a: std::declval<RI1>(), b: std::declval<RI2>()));
86 ASSERT_NOT_NOEXCEPT(iter_swap(a: std::declval<RI2>(), b: std::declval<RI1>()));
87 }
88
89 {
90 struct NoexceptCopyThrowingDecrement {
91 using value_type = int;
92 using difference_type = std::ptrdiff_t;
93
94 NoexceptCopyThrowingDecrement();
95 NoexceptCopyThrowingDecrement(const NoexceptCopyThrowingDecrement&) noexcept;
96
97 int& operator*() const { static int x; return x; }
98
99 NoexceptCopyThrowingDecrement& operator++();
100 NoexceptCopyThrowingDecrement operator++(int);
101 NoexceptCopyThrowingDecrement& operator--();
102 NoexceptCopyThrowingDecrement operator--(int);
103
104 bool operator==(const NoexceptCopyThrowingDecrement&) const = default;
105 };
106 static_assert(std::bidirectional_iterator<NoexceptCopyThrowingDecrement>);
107
108 static_assert( std::is_nothrow_copy_constructible_v<NoexceptCopyThrowingDecrement>);
109 static_assert( std::is_nothrow_copy_constructible_v<int*>);
110 ASSERT_NOT_NOEXCEPT(std::ranges::iter_swap(--std::declval<NoexceptCopyThrowingDecrement&>(), --std::declval<int*&>()));
111 using RI1 = std::reverse_iterator<NoexceptCopyThrowingDecrement>;
112 using RI2 = std::reverse_iterator<int*>;
113 ASSERT_NOT_NOEXCEPT(iter_swap(a: std::declval<RI1>(), b: std::declval<RI2>()));
114 ASSERT_NOT_NOEXCEPT(iter_swap(a: std::declval<RI2>(), b: std::declval<RI1>()));
115 }
116
117 {
118 struct NoexceptCopyAndDecrement {
119 using value_type = int;
120 using difference_type = std::ptrdiff_t;
121
122 NoexceptCopyAndDecrement();
123 NoexceptCopyAndDecrement(const NoexceptCopyAndDecrement&) noexcept;
124
125 int& operator*() const noexcept { static int x; return x; }
126
127 NoexceptCopyAndDecrement& operator++();
128 NoexceptCopyAndDecrement operator++(int);
129 NoexceptCopyAndDecrement& operator--() noexcept;
130 NoexceptCopyAndDecrement operator--(int) noexcept;
131
132 bool operator==(const NoexceptCopyAndDecrement&) const = default;
133 };
134 static_assert(std::bidirectional_iterator<NoexceptCopyAndDecrement>);
135
136 static_assert( std::is_nothrow_copy_constructible_v<NoexceptCopyAndDecrement>);
137 static_assert( std::is_nothrow_copy_constructible_v<int*>);
138 ASSERT_NOEXCEPT(std::ranges::iter_swap(--std::declval<NoexceptCopyAndDecrement&>(), --std::declval<int*&>()));
139 using RI1 = std::reverse_iterator<NoexceptCopyAndDecrement>;
140 using RI2 = std::reverse_iterator<int*>;
141 ASSERT_NOEXCEPT(iter_swap(a: std::declval<RI1>(), b: std::declval<RI2>()));
142 ASSERT_NOEXCEPT(iter_swap(a: std::declval<RI2>(), b: std::declval<RI1>()));
143 }
144 }
145
146 return true;
147}
148
149int main(int, char**) {
150 test();
151 static_assert(test());
152
153 return 0;
154}
155

Provided by KDAB

Privacy Policy
Improve your Profiling and Debugging skills
Find out more

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