xref: /llvm-project/libcxx/test/std/ranges/range.adaptors/range.elements/iterator/compare.pass.cpp (revision 808d794a45e169601ff16f72beae2f7bd79342a2)
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 
compareOperatorTest(const auto & iter1,const auto & iter2)32 constexpr 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 
inequalityOperatorsDoNotExistTest(const auto & iter1,const auto & iter2)58 constexpr 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 
test()67 constexpr 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 
main(int,char **)150 int main(int, char**) {
151   test();
152   static_assert(test());
153 
154   return 0;
155 }
156