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// friend constexpr bool operator==(const iterator& x, const iterator& y)
12// requires equality_comparable<iterator_t<Base>>;
13// friend constexpr bool operator<(const iterator& x, const iterator& y)
14// requires random_access_range<Base>;
15// friend constexpr bool operator>(const iterator& x, const iterator& y)
16// requires random_access_range<Base>;
17// friend constexpr bool operator<=(const iterator& x, const iterator& y)
18// requires random_access_range<Base>;
19// friend constexpr bool operator>=(const iterator& x, const iterator& y)
20// requires random_access_range<Base>;
21// friend constexpr auto operator<=>(const iterator& x, const iterator& y)
22// requires random_access_range<Base> && three_way_comparable<iterator_t<Base>>;
23
24#include <compare>
25#include <functional>
26#include <ranges>
27#include <tuple>
28
29#include "test_iterators.h"
30#include "test_range.h"
31
32constexpr void compareOperatorTest(const auto& iter1, const auto& iter2) {
33 assert(!(iter1 < iter1));
34 assert(iter1 < iter2);
35 assert(!(iter2 < iter1));
36
37 assert(iter1 <= iter1);
38 assert(iter1 <= iter2);
39 assert(!(iter2 <= iter1));
40
41 assert(!(iter1 > iter1));
42 assert(!(iter1 > iter2));
43 assert(iter2 > iter1);
44
45 assert(iter1 >= iter1);
46 assert(!(iter1 >= iter2));
47 assert(iter2 >= iter1);
48
49 assert(iter1 == iter1);
50 assert(!(iter1 == iter2));
51 assert(iter2 == iter2);
52
53 assert(!(iter1 != iter1));
54 assert(iter1 != iter2);
55 assert(!(iter2 != iter2));
56}
57
58constexpr void inequalityOperatorsDoNotExistTest(const auto& iter1, const auto& iter2) {
59 using Iter1 = decltype(iter1);
60 using Iter2 = decltype(iter2);
61 static_assert(!std::is_invocable_v<std::less<>, Iter1, Iter2>);
62 static_assert(!std::is_invocable_v<std::less_equal<>, Iter1, Iter2>);
63 static_assert(!std::is_invocable_v<std::greater<>, Iter1, Iter2>);
64 static_assert(!std::is_invocable_v<std::greater_equal<>, Iter1, Iter2>);
65}
66
67constexpr bool test() {
68 std::tuple<int> ts[] = {{1}, {2}, {3}};
69
70 {
71 // Test a new-school iterator with operator<=>; the iterator should also have operator<=>.
72 using It = three_way_contiguous_iterator<std::tuple<int>*>;
73 using Subrange = std::ranges::subrange<It>;
74 static_assert(std::three_way_comparable<It>);
75 using R = std::ranges::elements_view<Subrange, 0>;
76 static_assert(std::three_way_comparable<std::ranges::iterator_t<R>>);
77
78 auto ev = Subrange{It{&ts[0]}, It{&ts[0] + 3}} | std::views::elements<0>;
79 auto iter1 = ev.begin();
80 auto iter2 = iter1 + 1;
81
82 compareOperatorTest(iter1, iter2);
83
84 assert((iter1 <=> iter2) == std::strong_ordering::less);
85 assert((iter1 <=> iter1) == std::strong_ordering::equal);
86 assert((iter2 <=> iter1) == std::strong_ordering::greater);
87 }
88
89 {
90 // Test an old-school iterator with no operator<=>; the elements view iterator shouldn't have
91 // operator<=> either.
92 using It = random_access_iterator<std::tuple<int>*>;
93 using Subrange = std::ranges::subrange<It>;
94 static_assert(!std::three_way_comparable<It>);
95 using R = std::ranges::elements_view<Subrange, 0>;
96 static_assert(!std::three_way_comparable<std::ranges::iterator_t<R>>);
97
98 auto ev = Subrange{It{&ts[0]}, It{&ts[0] + 3}} | std::views::elements<0>;
99 auto iter1 = ev.begin();
100 auto iter2 = iter1 + 1;
101
102 compareOperatorTest(iter1, iter2);
103 }
104
105 {
106 // non random_access_range
107 using It = bidirectional_iterator<std::tuple<int>*>;
108 using Subrange = std::ranges::subrange<It>;
109 static_assert(!std::ranges::random_access_range<Subrange>);
110 using R = std::ranges::elements_view<Subrange, 0>;
111 static_assert(!std::three_way_comparable<std::ranges::iterator_t<R>>);
112
113 auto ev = Subrange{It{&ts[0]}, It{&ts[0] + 1}} | std::views::elements<0>;
114
115 auto it1 = ev.begin();
116 auto it2 = ev.end();
117
118 assert(it1 == it1);
119 assert(!(it1 != it1));
120 assert(it2 == it2);
121 assert(!(it2 != it2));
122
123 assert(it1 != it2);
124
125 ++it1;
126 assert(it1 == it2);
127
128 inequalityOperatorsDoNotExistTest(it1, it2);
129 }
130
131 {
132 // underlying iterator does not support ==
133 using Iter = cpp20_input_iterator<std::tuple<int>*>;
134 using Sent = sentinel_wrapper<Iter>;
135 using Subrange = std::ranges::subrange<Iter, Sent>;
136 using R = std::ranges::elements_view<Subrange, 0>;
137 static_assert(!std::three_way_comparable<std::ranges::iterator_t<R>>);
138
139 auto ev = Subrange{Iter{&ts[0]}, Sent{Iter{&ts[0] + 1}}} | std::views::elements<0>;
140 auto it = ev.begin();
141
142 using ElemIter = decltype(it);
143 static_assert(!weakly_equality_comparable_with<ElemIter, ElemIter>);
144 inequalityOperatorsDoNotExistTest(it, it);
145 }
146
147 return true;
148}
149
150int main(int, char**) {
151 test();
152 static_assert(test());
153
154 return 0;
155}
156

source code of libcxx/test/std/ranges/range.adaptors/range.elements/iterator/compare.pass.cpp