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
26constexpr 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
134int main(int, char**) {
135 test();
136 static_assert(test());
137
138 return 0;
139}
140

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