xref: /llvm-project/libcxx/test/std/ranges/range.adaptors/range.elements/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 //  template<bool OtherConst>
12 //    requires sentinel_for<sentinel_t<Base>, iterator_t<maybe-const<OtherConst, V>>>
13 //  friend constexpr bool operator==(const iterator<OtherConst>& x, const sentinel& y);
14 
15 #include <array>
16 #include <cassert>
17 #include <ranges>
18 
19 #include "../types.h"
20 #include "test_range.h"
21 
22 template <bool Const>
23 struct Iter {
24   std::tuple<int>* it_;
25 
26   using value_type       = std::tuple<int>;
27   using difference_type  = std::intptr_t;
28   using iterator_concept = std::input_iterator_tag;
29 
operator *Iter30   constexpr decltype(auto) operator*() const { return *it_; }
operator ++Iter31   constexpr Iter& operator++() {
32     ++it_;
33     return *this;
34   }
operator ++Iter35   constexpr void operator++(int) { ++it_; }
36 };
37 
38 template <bool Const>
39 struct Sent {
40   std::tuple<int>* end_;
41 
operator ==Sent42   constexpr bool operator==(const Iter<Const>& i) const { return i.it_ == end_; }
43 };
44 
45 template <bool Const>
46 struct CrossComparableSent {
47   std::tuple<int>* end_;
48 
49   template <bool C>
operator ==CrossComparableSent50   constexpr bool operator==(const Iter<C>& i) const {
51     return i.it_ == end_;
52   }
53 };
54 
55 template <template <bool> typename St>
56 struct Range : TupleBufferView {
57   using TupleBufferView::TupleBufferView;
beginRange58   constexpr Iter<false> begin() { return Iter<false>{buffer_}; }
beginRange59   constexpr Iter<true> begin() const { return Iter<true>{buffer_}; }
endRange60   constexpr St<false> end() { return St<false>{buffer_ + size_}; }
endRange61   constexpr St<true> end() const { return St<true>{buffer_ + size_}; }
62 };
63 
64 using R                = Range<Sent>;
65 using CrossComparableR = Range<CrossComparableSent>;
66 
67 using std::ranges::elements_view;
68 using std::ranges::iterator_t;
69 using std::ranges::sentinel_t;
70 
71 static_assert(weakly_equality_comparable_with<iterator_t<elements_view<R, 0>>, //
72                                               sentinel_t<elements_view<R, 0>>>);
73 
74 static_assert(!weakly_equality_comparable_with<iterator_t<const elements_view<R, 0>>, //
75                                                sentinel_t<elements_view<R, 0>>>);
76 
77 static_assert(!weakly_equality_comparable_with<iterator_t<elements_view<R, 0>>, //
78                                                sentinel_t<const elements_view<R, 0>>>);
79 
80 static_assert(weakly_equality_comparable_with<iterator_t<const elements_view<R, 0>>, //
81                                               sentinel_t<const elements_view<R, 0>>>);
82 
83 static_assert(weakly_equality_comparable_with<iterator_t<elements_view<CrossComparableR, 0>>, //
84                                               sentinel_t<elements_view<CrossComparableR, 0>>>);
85 
86 static_assert(weakly_equality_comparable_with<iterator_t<const elements_view<CrossComparableR, 0>>, //
87                                               sentinel_t<elements_view<CrossComparableR, 0>>>);
88 
89 static_assert(weakly_equality_comparable_with<iterator_t<elements_view<CrossComparableR, 0>>, //
90                                               sentinel_t<const elements_view<CrossComparableR, 0>>>);
91 
92 static_assert(weakly_equality_comparable_with<iterator_t<const elements_view<CrossComparableR, 0>>, //
93                                               sentinel_t<const elements_view<CrossComparableR, 0>>>);
94 
95 template <class R, bool ConstIter, bool ConstSent>
testOne()96 constexpr void testOne() {
97   auto getBegin = [](auto&& rng) {
98     if constexpr (ConstIter) {
99       return std::as_const(rng).begin();
100     } else {
101       return rng.begin();
102     }
103   };
104 
105   auto getEnd = [](auto&& rng) {
106     if constexpr (ConstSent) {
107       return std::as_const(rng).end();
108     } else {
109       return rng.end();
110     }
111   };
112 
113   // iter == sentinel.base
114   {
115     std::tuple<int> buffer[] = {{1}};
116     R v{buffer};
117     std::ranges::elements_view<R, 0> ev(v);
118     auto iter = getBegin(ev);
119     auto st   = getEnd(ev);
120     ++iter;
121     assert(iter == st);
122   }
123 
124   // iter != sentinel.base
125   {
126     std::tuple<int> buffer[] = {{1}};
127     R v{buffer};
128     std::ranges::elements_view<R, 0> ev(v);
129     auto iter = getBegin(ev);
130     auto st   = getEnd(ev);
131     assert(iter != st);
132   }
133 
134   // empty range
135   {
136     std::array<std::tuple<int>, 0> arr;
137     R v{arr};
138     std::ranges::elements_view<R, 0> ev(v);
139     auto iter = getBegin(ev);
140     auto sent = getEnd(ev);
141     assert(iter == sent);
142   }
143 }
144 
test()145 constexpr bool test() {
146   testOne<R, false, false>();
147   testOne<R, true, true>();
148   testOne<CrossComparableR, false, false>();
149   testOne<CrossComparableR, true, true>();
150   testOne<CrossComparableR, true, false>();
151   testOne<CrossComparableR, false, true>();
152 
153   return true;
154 }
155 
main(int,char **)156 int main(int, char**) {
157   test();
158   static_assert(test());
159 
160   return 0;
161 }
162