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// REQUIRES: std-at-least-c++23
10
11// <ranges>
12
13// friend constexpr bool operator==(const iterator& x, const iterator& y)
14// requires ref-is-glvalue && forward_range<Base> &&
15// equality_comparable<InnerIter>;
16
17#include <ranges>
18
19#include <array>
20#include <cassert>
21#include <utility>
22
23#include "../types.h"
24#include "test_comparisons.h"
25
26template <class I1, class I2 = I1>
27concept CanEq = requires(const I1& i1, const I2& i2) {
28 { i1 == i2 } -> std::same_as<bool>;
29 { i2 == i1 } -> std::same_as<bool>;
30 { i1 != i2 } -> std::same_as<bool>;
31 { i2 != i1 } -> std::same_as<bool>;
32};
33
34constexpr bool test() {
35 { // `V` and `Pattern` are not empty. Test return types too.
36 using V = std::array<std::array<int, 2>, 3>;
37 using Pattern = std::array<long, 1>;
38 using JWV = std::ranges::join_with_view<std::ranges::owning_view<V>, std::ranges::owning_view<Pattern>>;
39
40 using Iter = std::ranges::iterator_t<JWV>;
41 using CIter = std::ranges::iterator_t<const JWV>;
42 static_assert(!std::same_as<Iter, CIter>);
43 static_assert(CanEq<Iter>);
44 static_assert(CanEq<CIter>);
45 static_assert(CanEq<Iter, CIter>);
46
47 JWV jwv(V{._M_elems: {{9, 8}, {7, 6}, {5, 4}}}, Pattern{0L});
48
49 Iter it1 = jwv.begin();
50 assert(*it1 == 9);
51 assert(testEquality(it1, it1, true));
52
53 Iter it2 = std::ranges::prev(jwv.end());
54 assert(*it2 == 4);
55 assert(testEquality(it2, it2, true));
56 assert(testEquality(it1, it2, false));
57
58 CIter cit1 = std::as_const(jwv).begin();
59 assert(*cit1 == 9);
60 assert(testEquality(cit1, cit1, true));
61 assert(testEquality(it1, cit1, true));
62 assert(testEquality(it2, cit1, false));
63
64 CIter cit2 = std::ranges::prev(std::as_const(jwv).end());
65 assert(*cit2 == 4);
66 assert(testEquality(cit2, cit2, true));
67 assert(testEquality(cit1, cit2, false));
68 assert(testEquality(it1, cit2, false));
69 assert(testEquality(it2, cit2, true));
70
71 // `it1.inner_it_` and `it2.inner_it_` are equal, but `it1.outer_it_` and `it2.outer_it_` are not.
72 std::ranges::advance(it1, 2);
73 assert(*it1 == 0);
74 std::ranges::advance(it2, -2);
75 assert(*it2 == 0);
76 assert(testEquality(it1, it2, false));
77
78 // `cit1.inner_it_` and `cit2.inner_it_` are equal, but `cit1.outer_it_` and `cit2.outer_it_` are not.
79 std::ranges::advance(cit1, 2);
80 assert(*cit1 == 0);
81 assert(testEquality(it1, cit1, true));
82 std::ranges::advance(cit2, -2);
83 assert(*cit2 == 0);
84 assert(testEquality(it2, cit2, true));
85 assert(testEquality(cit1, cit2, false));
86
87 // `it1.inner_it_` and `it2.inner_it_` are equal, `it1.outer_it_` and `it2.outer_it_` are equal too.
88 // `it1.inner_it_index()` and `it2.inner_it_index()` are equal to 1.
89 ++it1;
90 assert(*it1 == 7);
91 std::ranges::advance(it2, -2);
92 assert(*it2 == 7);
93 assert(testEquality(it1, it2, true));
94
95 // `cit1.inner_it_` and `cit2.inner_it_` are equal, `cit1.outer_it_` and `cit2.outer_it_` are equal too.
96 // `cit1.inner_it_index()` and `cit2.inner_it_index()` are equal to 1.
97 ++cit1;
98 assert(*cit1 == 7);
99 assert(testEquality(it1, cit1, true));
100 std::ranges::advance(cit2, -2);
101 assert(*cit2 == 7);
102 assert(testEquality(it2, cit2, true));
103 assert(testEquality(cit1, cit2, true));
104
105 // `it1.inner_it_` and `it2.inner_it_` are equal, `it1.outer_it_` and `it2.outer_it_` are equal too.
106 // `it1.inner_it_index()` and `it2.inner_it_index()` are equal to 0.
107 --it1;
108 assert(*it1 == 0);
109 --it2;
110 assert(*it2 == 0);
111 assert(testEquality(it1, it2, true));
112
113 // `cit1.inner_it_` and `cit2.inner_it_` are equal, `cit1.outer_it_` and `cit2.outer_it_` are equal too.
114 // `cit1.inner_it_index()` and `cit2.inner_it_index()` are equal to 0.
115 --cit1;
116 assert(*cit1 == 0);
117 assert(testEquality(it1, cit1, true));
118 --cit2;
119 assert(*cit2 == 0);
120 assert(testEquality(it2, cit2, true));
121 assert(testEquality(cit2, cit2, true));
122 }
123
124 { // `InnerIter` models input iterator and equality comparable. `Pattern` is empty.
125 using Inner = BasicVectorView<int, ViewProperties{.common = false}, EqComparableInputIter>;
126 using V = std::vector<Inner>;
127 using Pattern = std::ranges::empty_view<int>;
128 using JWV = std::ranges::join_with_view<std::ranges::owning_view<V>, std::ranges::owning_view<Pattern>>;
129
130 using Iter = std::ranges::iterator_t<JWV>;
131 using CIter = std::ranges::iterator_t<const JWV>;
132 static_assert(!std::same_as<Iter, CIter>);
133 static_assert(CanEq<Iter>);
134 static_assert(CanEq<CIter>);
135 static_assert(!CanEq<CIter, Iter>);
136
137 JWV jwv(V{Inner{1, 2}, Inner{5, 6}, Inner{9, 0}}, Pattern{});
138
139 {
140 Iter it1 = jwv.begin();
141 assert(*it1 == 1);
142 Iter it2 = std::ranges::next(jwv.begin(), 2);
143 assert(*it2 == 5);
144 assert(testEquality(it1, it2, false));
145 ++it1;
146 ++it1;
147 assert(testEquality(it1, it2, true));
148 ++it1;
149 assert(testEquality(it1, it2, false));
150 }
151
152 {
153 CIter cit1 = std::as_const(jwv).begin();
154 assert(*cit1 == 1);
155 CIter cit2 = std::ranges::next(std::as_const(jwv).begin(), 2);
156 assert(*cit2 == 5);
157 assert(testEquality(cit1, cit2, false));
158 ++cit1;
159 ++cit1;
160 assert(testEquality(cit1, cit2, true));
161 ++cit1;
162 assert(testEquality(cit1, cit2, false));
163 }
164 }
165
166 { // `Pattern` is not empty. Some elements of `V` are.
167 using Inner = BasicVectorView<int, ViewProperties{.common = false}, EqComparableInputIter>;
168 using V = BasicVectorView<Inner, ViewProperties{}, forward_iterator>;
169 using Pattern = BasicVectorView<int, ViewProperties{.common = false}, forward_iterator>;
170 using JWV = std::ranges::join_with_view<V, Pattern>;
171
172 using Iter = std::ranges::iterator_t<JWV>;
173 using CIter = std::ranges::iterator_t<const JWV>;
174 static_assert(!std::same_as<Iter, CIter>);
175 static_assert(CanEq<Iter>);
176 static_assert(CanEq<CIter>);
177 static_assert(!CanEq<CIter, Iter>);
178
179 JWV jwv(V{Inner{1}, Inner{}, Inner{27}}, Pattern{0});
180
181 {
182 Iter it1 = jwv.begin();
183 assert(*it1 == 1);
184 ++it1;
185 assert(*it1 == 0);
186 Iter it2 = jwv.begin();
187 assert(testEquality(it1, it2, false));
188 ++it2;
189 assert(testEquality(it1, it2, true));
190
191 ++it2;
192 assert(*it1 == *it2);
193 assert(testEquality(it1, it2, false));
194
195 std::ranges::advance(it1, 2);
196 ++it2;
197 assert(*it1 == *it2);
198 assert(testEquality(it1, it2, true));
199 }
200
201 {
202 CIter cit1 = std::as_const(jwv).begin();
203 assert(*cit1 == 1);
204 ++cit1;
205 assert(*cit1 == 0);
206 CIter cit2 = std::as_const(jwv).begin();
207 assert(testEquality(cit1, cit2, false));
208 ++cit2;
209 assert(testEquality(cit1, cit2, true));
210
211 ++cit2;
212 assert(*cit1 == *cit2);
213 assert(testEquality(cit1, cit2, false));
214
215 std::ranges::advance(cit1, 2);
216 ++cit2;
217 assert(*cit1 == *cit2);
218 assert(testEquality(cit1, cit2, true));
219 }
220 }
221
222 { // `ref-is-glvalue` is false
223 using Inner = std::vector<int>;
224 using V = RvalueVector<Inner>;
225 using Pattern = std::ranges::empty_view<int>;
226 using JWV = std::ranges::join_with_view<std::ranges::owning_view<V>, std::ranges::owning_view<Pattern>>;
227 using Iter = std::ranges::iterator_t<JWV>;
228 static_assert(!CanEq<Iter>);
229 }
230
231 { // `Base` does not model forward range
232 using Inner = std::vector<int>;
233 using V = BasicVectorView<Inner, ViewProperties{}, DefaultCtorInputIter>;
234 using Pattern = std::ranges::empty_view<int>;
235 using JWV = std::ranges::join_with_view<std::ranges::owning_view<V>, std::ranges::owning_view<Pattern>>;
236 using Iter = std::ranges::iterator_t<JWV>;
237 static_assert(!CanEq<Iter>);
238 }
239
240 { // `InnerIter` does not model equality comparable
241 using Inner = BasicVectorView<int, ViewProperties{.common = false}, cpp20_input_iterator>;
242 using V = std::vector<Inner>;
243 using Pattern = std::ranges::empty_view<int>;
244 using JWV = std::ranges::join_with_view<std::ranges::owning_view<V>, std::ranges::owning_view<Pattern>>;
245 using Iter = std::ranges::iterator_t<JWV>;
246 using CIter = std::ranges::iterator_t<const JWV>;
247 static_assert(!CanEq<Iter>);
248 static_assert(!CanEq<CIter>);
249 }
250
251 return true;
252}
253
254int main(int, char**) {
255 test();
256 static_assert(test());
257
258 return 0;
259}
260

source code of libcxx/test/std/ranges/range.adaptors/range.join.with/range.join.with.iterator/eq.pass.cpp