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 // friend constexpr iter_rvalue_reference_t<Iterator>
16 // iter_move(const reverse_iterator& i) noexcept(see below);
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
test()26 constexpr bool test() {
27 // Can use `iter_move` with a regular array.
28 {
29 constexpr int N = 3;
30 int a[N] = {0, 1, 2};
31
32 std::reverse_iterator<int*> ri(a + N);
33 static_assert(std::same_as<decltype(iter_move(ri)), int&&>);
34 assert(iter_move(ri) == 2);
35
36 ++ri;
37 assert(iter_move(ri) == 1);
38 }
39
40 // Check that the `iter_move` customization point is being used.
41 {
42 constexpr int N = 3;
43 int a[N] = {0, 1, 2};
44
45 int iter_move_invocations = 0;
46 adl::Iterator i = adl::Iterator::TrackMoves(a + N, iter_move_invocations);
47 std::reverse_iterator<adl::Iterator> ri(i);
48 int x = iter_move(ri);
49 assert(x == 2);
50 assert(iter_move_invocations == 1);
51 }
52
53 // Check the `noexcept` specification.
54 {
55 {
56 struct ThrowingCopyNoexceptDecrement {
57 using value_type = int;
58 using difference_type = std::ptrdiff_t;
59
60 ThrowingCopyNoexceptDecrement();
61 ThrowingCopyNoexceptDecrement(const ThrowingCopyNoexceptDecrement&);
62
63 int& operator*() const noexcept { static int x; return x; }
64
65 ThrowingCopyNoexceptDecrement& operator++();
66 ThrowingCopyNoexceptDecrement operator++(int);
67 ThrowingCopyNoexceptDecrement& operator--() noexcept;
68 ThrowingCopyNoexceptDecrement operator--(int) noexcept;
69
70 bool operator==(const ThrowingCopyNoexceptDecrement&) const = default;
71 };
72 static_assert(std::bidirectional_iterator<ThrowingCopyNoexceptDecrement>);
73
74 static_assert(!std::is_nothrow_copy_constructible_v<ThrowingCopyNoexceptDecrement>);
75 ASSERT_NOEXCEPT(std::ranges::iter_move(--std::declval<ThrowingCopyNoexceptDecrement&>()));
76 using RI = std::reverse_iterator<ThrowingCopyNoexceptDecrement>;
77 ASSERT_NOT_NOEXCEPT(iter_move(std::declval<RI>()));
78 }
79
80 {
81 struct NoexceptCopyThrowingDecrement {
82 using value_type = int;
83 using difference_type = std::ptrdiff_t;
84
85 NoexceptCopyThrowingDecrement();
86 NoexceptCopyThrowingDecrement(const NoexceptCopyThrowingDecrement&) noexcept;
87
88 int& operator*() const { static int x; return x; }
89
90 NoexceptCopyThrowingDecrement& operator++();
91 NoexceptCopyThrowingDecrement operator++(int);
92 NoexceptCopyThrowingDecrement& operator--();
93 NoexceptCopyThrowingDecrement operator--(int);
94
95 bool operator==(const NoexceptCopyThrowingDecrement&) const = default;
96 };
97 static_assert(std::bidirectional_iterator<NoexceptCopyThrowingDecrement>);
98
99 static_assert( std::is_nothrow_copy_constructible_v<NoexceptCopyThrowingDecrement>);
100 ASSERT_NOT_NOEXCEPT(std::ranges::iter_move(--std::declval<NoexceptCopyThrowingDecrement&>()));
101 using RI = std::reverse_iterator<NoexceptCopyThrowingDecrement>;
102 ASSERT_NOT_NOEXCEPT(iter_move(std::declval<RI>()));
103 }
104
105 {
106 struct NoexceptCopyAndDecrement {
107 using value_type = int;
108 using difference_type = std::ptrdiff_t;
109
110 NoexceptCopyAndDecrement();
111 NoexceptCopyAndDecrement(const NoexceptCopyAndDecrement&) noexcept;
112
113 int& operator*() const noexcept { static int x; return x; }
114
115 NoexceptCopyAndDecrement& operator++();
116 NoexceptCopyAndDecrement operator++(int);
117 NoexceptCopyAndDecrement& operator--() noexcept;
118 NoexceptCopyAndDecrement operator--(int) noexcept;
119
120 bool operator==(const NoexceptCopyAndDecrement&) const = default;
121 };
122 static_assert(std::bidirectional_iterator<NoexceptCopyAndDecrement>);
123
124 static_assert( std::is_nothrow_copy_constructible_v<NoexceptCopyAndDecrement>);
125 ASSERT_NOEXCEPT(std::ranges::iter_move(--std::declval<NoexceptCopyAndDecrement&>()));
126 using RI = std::reverse_iterator<NoexceptCopyAndDecrement>;
127 ASSERT_NOEXCEPT(iter_move(std::declval<RI>()));
128 }
129 }
130
131 return true;
132 }
133
main(int,char **)134 int main(int, char**) {
135 test();
136 static_assert(test());
137
138 return 0;
139 }
140