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// <iterator>
10
11// reverse_iterator
12
13// pointer operator->() const; // constexpr in C++17
14
15// Be sure to respect LWG 198:
16// http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#198
17// LWG 198 was superseded by LWG 2360
18// http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2360
19
20
21#include <iterator>
22#include <list>
23#include <cassert>
24
25#include "test_macros.h"
26
27#if TEST_STD_VER >= 20
28// C++20 bidirectional_iterator that does not satisfy the Cpp17BidirectionalIterator named requirement.
29template <class It>
30class cpp20_bidirectional_iterator_with_arrow {
31 It it_;
32
33public:
34 using iterator_category = std::input_iterator_tag;
35 using iterator_concept = std::bidirectional_iterator_tag;
36 using value_type = std::iterator_traits<It>::value_type;
37 using difference_type = std::iterator_traits<It>::difference_type;
38
39 cpp20_bidirectional_iterator_with_arrow() : it_() {}
40 explicit cpp20_bidirectional_iterator_with_arrow(It it) : it_(it) {}
41
42 decltype(auto) operator*() const { return *it_; }
43
44 auto operator->() const {
45 if constexpr (std::is_pointer_v<It>) {
46 return it_;
47 } else {
48 return it_.operator->();
49 }
50 }
51
52 cpp20_bidirectional_iterator_with_arrow& operator++() {
53 ++it_;
54 return *this;
55 }
56 cpp20_bidirectional_iterator_with_arrow& operator--() {
57 --it_;
58 return *this;
59 }
60 cpp20_bidirectional_iterator_with_arrow operator++(int) { return cpp20_bidirectional_iterator_with_arrow(it_++); }
61 cpp20_bidirectional_iterator_with_arrow operator--(int) { return cpp20_bidirectional_iterator_with_arrow(it_--); }
62
63 friend bool
64 operator==(const cpp20_bidirectional_iterator_with_arrow& x, const cpp20_bidirectional_iterator_with_arrow& y) {
65 return x.it_ == y.it_;
66 }
67 friend bool
68 operator!=(const cpp20_bidirectional_iterator_with_arrow& x, const cpp20_bidirectional_iterator_with_arrow& y) {
69 return x.it_ != y.it_;
70 }
71
72 friend It base(const cpp20_bidirectional_iterator_with_arrow& i) { return i.it_; }
73};
74#endif
75
76class A
77{
78 int data_;
79public:
80 A() : data_(1) {}
81 A(const A&) = default;
82 A& operator=(const A&) = default;
83 ~A() {data_ = -1;}
84
85 int get() const {return data_;}
86
87 friend bool operator==(const A& x, const A& y)
88 {return x.data_ == y.data_;}
89};
90
91template <class It>
92void
93test(It i, typename std::iterator_traits<It>::value_type x)
94{
95 std::reverse_iterator<It> r(i);
96 assert(r->get() == x.get());
97}
98
99class B
100{
101 int data_;
102public:
103 B(int d=1) : data_(d) {}
104 B(const B&) = default;
105 B& operator=(const B&) = default;
106 ~B() {data_ = -1;}
107
108 int get() const {return data_;}
109
110 friend bool operator==(const B& x, const B& y)
111 {return x.data_ == y.data_;}
112 const B *operator&() const { return nullptr; }
113 B *operator&() { return nullptr; }
114};
115
116class C
117{
118 int data_;
119public:
120 TEST_CONSTEXPR C() : data_(1) {}
121
122 TEST_CONSTEXPR int get() const {return data_;}
123
124 friend TEST_CONSTEXPR bool operator==(const C& x, const C& y)
125 {return x.data_ == y.data_;}
126};
127
128TEST_CONSTEXPR C gC;
129
130int main(int, char**)
131{
132 A a;
133 test(i: &a+1, x: A());
134
135 {
136 std::list<B> l;
137 l.push_back(x: B(0));
138 l.push_back(x: B(1));
139 l.push_back(x: B(2));
140
141 {
142 std::list<B>::const_iterator i = l.begin();
143 assert ( i->get() == 0 ); ++i;
144 assert ( i->get() == 1 ); ++i;
145 assert ( i->get() == 2 ); ++i;
146 assert ( i == l.end ());
147 }
148
149 {
150 std::list<B>::const_reverse_iterator ri = l.rbegin();
151 assert ( ri->get() == 2 ); ++ri;
152 assert ( ri->get() == 1 ); ++ri;
153 assert ( ri->get() == 0 ); ++ri;
154 assert ( ri == l.rend ());
155 }
156 }
157
158#if TEST_STD_VER > 14
159 {
160 typedef std::reverse_iterator<const C *> RI;
161 constexpr RI it1 = std::make_reverse_iterator(&gC+1);
162
163 static_assert(it1->get() == gC.get(), "");
164 }
165#endif
166#if TEST_STD_VER >= 20
167 {
168 // The underlying iterator models c++20 bidirectional_iterator,
169 // but does not satisfy c++17 BidirectionalIterator named requirement
170 B data[] = {1, 2, 3};
171 cpp20_bidirectional_iterator_with_arrow<B*> iter(data + 3);
172 auto ri = std::make_reverse_iterator(iter);
173 assert(ri->get() == 3);
174 }
175#endif
176 {
177 ((void)gC);
178 }
179
180 return 0;
181}
182

source code of libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.elem/arrow.pass.cpp