xref: /llvm-project/libcxx/test/std/ranges/range.adaptors/range.take.while/sentinel/equality.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_t<Base>& x, const sentinel& y);
12 //
13 //  template<bool OtherConst = !Const>
14 //    requires sentinel_for<sentinel_t<Base>, iterator_t<maybe-const<OtherConst, V>>>
15 //  friend constexpr bool operator==(const iterator_t<maybe-const<OtherConst, V>>& x,
16 //                                   const sentinel& y);
17 
18 #include <array>
19 #include <cassert>
20 #include <ranges>
21 
22 #include "../types.h"
23 
24 template <bool Const>
25 struct Iter {
26   int* it_;
27 
28   using value_type       = int;
29   using difference_type  = std::intptr_t;
30   using iterator_concept = std::input_iterator_tag;
31 
operator *Iter32   constexpr decltype(auto) operator*() const { return *it_; }
operator ++Iter33   constexpr Iter& operator++() {
34     ++it_;
35     return *this;
36   }
operator ++Iter37   constexpr void operator++(int) { ++it_; }
38 };
39 
40 template <bool Const>
41 struct Sent {
42   int* end_;
43 
operator ==Sent44   constexpr bool operator==(const Iter<Const>& i) const { return i.it_ == end_; }
45 };
46 
47 template <bool Const>
48 struct CrossComparableSent {
49   int* end_;
50 
51   template <bool C>
operator ==CrossComparableSent52   constexpr bool operator==(const Iter<C>& i) const {
53     return i.it_ == end_;
54   }
55 };
56 
57 template <template <bool> typename St>
58 struct Range : IntBufferViewBase {
59   using IntBufferViewBase::IntBufferViewBase;
beginRange60   constexpr Iter<false> begin() { return Iter<false>{buffer_}; }
beginRange61   constexpr Iter<true> begin() const { return Iter<true>{buffer_}; }
endRange62   constexpr St<false> end() { return St<false>{buffer_ + size_}; }
endRange63   constexpr St<true> end() const { return St<true>{buffer_ + size_}; }
64 };
65 
66 using R                = Range<Sent>;
67 using CrossComparableR = Range<CrossComparableSent>;
68 
69 struct LessThan3 {
operator ()LessThan370   constexpr bool operator()(int i) const { return i < 3; }
71 };
72 
73 using std::ranges::iterator_t;
74 using std::ranges::sentinel_t;
75 using std::ranges::take_while_view;
76 
77 static_assert(weakly_equality_comparable_with<iterator_t<take_while_view<R, LessThan3>>, //
78                                               sentinel_t<take_while_view<R, LessThan3>>>);
79 
80 static_assert(!weakly_equality_comparable_with<iterator_t<const take_while_view<R, LessThan3>>, //
81                                                sentinel_t<take_while_view<R, LessThan3>>>);
82 
83 static_assert(!weakly_equality_comparable_with<iterator_t<take_while_view<R, LessThan3>>, //
84                                                sentinel_t<const take_while_view<R, LessThan3>>>);
85 
86 static_assert(weakly_equality_comparable_with<iterator_t<const take_while_view<R, LessThan3>>, //
87                                               sentinel_t<const take_while_view<R, LessThan3>>>);
88 
89 static_assert(weakly_equality_comparable_with<iterator_t<take_while_view<CrossComparableR, LessThan3>>, //
90                                               sentinel_t<take_while_view<CrossComparableR, LessThan3>>>);
91 
92 static_assert(weakly_equality_comparable_with<iterator_t<const take_while_view<CrossComparableR, LessThan3>>, //
93                                               sentinel_t<take_while_view<CrossComparableR, LessThan3>>>);
94 
95 static_assert(weakly_equality_comparable_with<iterator_t<take_while_view<CrossComparableR, LessThan3>>, //
96                                               sentinel_t<const take_while_view<CrossComparableR, LessThan3>>>);
97 
98 static_assert(weakly_equality_comparable_with<iterator_t<const take_while_view<CrossComparableR, LessThan3>>, //
99                                               sentinel_t<const take_while_view<CrossComparableR, LessThan3>>>);
100 
101 template <class R, bool ConstIter, bool ConstSent>
testOne()102 constexpr void testOne() {
103   auto getBegin = [](auto&& rng) {
104     if constexpr (ConstIter) {
105       return std::as_const(rng).begin();
106     } else {
107       return rng.begin();
108     }
109   };
110 
111   auto getEnd = [](auto&& rng) {
112     if constexpr (ConstSent) {
113       return std::as_const(rng).end();
114     } else {
115       return rng.end();
116     }
117   };
118 
119   // iter == sentinel.base
120   {
121     int buffer[] = {1};
122     R v{buffer};
123     std::ranges::take_while_view twv(v, LessThan3{});
124     auto iter = getBegin(twv);
125     auto st   = getEnd(twv);
126     ++iter;
127     assert(iter == st);
128   }
129 
130   // iter != sentinel.base && pred(*iter)
131   {
132     int buffer[] = {1, 3, 4};
133     R v{buffer};
134     std::ranges::take_while_view twv(v, LessThan3{});
135     auto iter = getBegin(twv);
136     auto st   = getEnd(twv);
137     assert(iter != st);
138     ++iter;
139     assert(iter == st);
140   }
141 
142   // iter != sentinel.base && !pred(*iter)
143   {
144     int buffer[] = {1, 2, 3, 4, 3, 2, 1};
145     R v{buffer};
146     std::ranges::take_while_view twv(v, LessThan3{});
147     auto iter = getBegin(twv);
148     auto sent = getEnd(twv);
149     assert(iter != sent);
150   }
151 
152   // empty range
153   {
154     std::array<int, 0> arr;
155     R v{arr};
156     std::ranges::take_while_view twv(v, LessThan3{});
157     auto iter = getBegin(twv);
158     auto sent = getEnd(twv);
159     assert(iter == sent);
160   }
161 }
162 
test()163 constexpr bool test() {
164   testOne<R, false, false>();
165   testOne<R, true, true>();
166   testOne<CrossComparableR, false, false>();
167   testOne<CrossComparableR, true, true>();
168 
169   // LWG 3449 `take_view` and `take_while_view`'s `sentinel<false>` not comparable with their const iterator
170   testOne<CrossComparableR, true, false>();
171   testOne<CrossComparableR, false, true>();
172 
173   // test std::invoke is used
174   {
175     struct Data {
176       bool b;
177     };
178 
179     Data buffer[] = {{true}, {true}, {false}};
180     std::ranges::take_while_view twv(buffer, &Data::b);
181     auto it = twv.begin();
182     auto st = twv.end();
183     assert(it != st);
184 
185     ++it;
186     assert(it != st);
187 
188     ++it;
189     assert(it == st);
190   }
191 
192   return true;
193 }
194 
main(int,char **)195 int main(int, char**) {
196   test();
197   static_assert(test());
198 
199   return 0;
200 }
201