xref: /llvm-project/libcxx/test/std/ranges/range.adaptors/range.zip/sentinel/eq.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, c++20
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 <cassert>
16 #include <compare>
17 #include <ranges>
18 #include <tuple>
19 
20 #include "../types.h"
21 #include "test_range.h"
22 
23 using Iterator = random_access_iterator<int*>;
24 using ConstIterator = random_access_iterator<const int*>;
25 
26 template <bool Const>
27 struct ComparableSentinel {
28 
29   using Iter = std::conditional_t<Const, ConstIterator, Iterator>;
30   Iter iter_;
31 
32   explicit ComparableSentinel() = default;
ComparableSentinelComparableSentinel33   constexpr explicit ComparableSentinel(const Iter& it) : iter_(it) {}
34 
operator ==(const Iterator & i,const ComparableSentinel & s)35   constexpr friend bool operator==(const Iterator& i, const ComparableSentinel& s) { return base(i) == base(s.iter_); }
36 
operator ==(const ConstIterator & i,const ComparableSentinel & s)37   constexpr friend bool operator==(const ConstIterator& i, const ComparableSentinel& s) {
38     return base(i) == base(s.iter_);
39   }
40 };
41 
42 struct ComparableView :  IntBufferView {
43   using IntBufferView::IntBufferView;
44 
beginComparableView45   constexpr auto begin() { return Iterator(buffer_); }
beginComparableView46   constexpr auto begin() const { return ConstIterator(buffer_); }
endComparableView47   constexpr auto end() { return ComparableSentinel<false>(Iterator(buffer_ + size_)); }
endComparableView48   constexpr auto end() const { return ComparableSentinel<true>(ConstIterator(buffer_ + size_)); }
49 };
50 
51 struct ConstIncompatibleView : std::ranges::view_base {
52   cpp17_input_iterator<int*> begin();
53   forward_iterator<const int*> begin() const;
54   sentinel_wrapper<cpp17_input_iterator<int*>> end();
55   sentinel_wrapper<forward_iterator<const int*>> end() const;
56 };
57 
test()58 constexpr bool test() {
59   int buffer1[4] = {1, 2, 3, 4};
60   int buffer2[5] = {1, 2, 3, 4, 5};
61   int buffer3[8] = {1, 2, 3, 4, 5, 6, 7, 8};
62   {
63     // simple-view: const and non-const have the same iterator/sentinel type
64     std::ranges::zip_view v{SimpleNonCommon(buffer1), SimpleNonCommon(buffer2), SimpleNonCommon(buffer3)};
65     static_assert(!std::ranges::common_range<decltype(v)>);
66     static_assert(simple_view<decltype(v)>);
67 
68     assert(v.begin() != v.end());
69     assert(v.begin() + 1 != v.end());
70     assert(v.begin() + 2 != v.end());
71     assert(v.begin() + 3 != v.end());
72     assert(v.begin() + 4 == v.end());
73   }
74 
75   {
76     // !simple-view: const and non-const have different iterator/sentinel types
77     std::ranges::zip_view v{NonSimpleNonCommon(buffer1), SimpleNonCommon(buffer2), SimpleNonCommon(buffer3)};
78     static_assert(!std::ranges::common_range<decltype(v)>);
79     static_assert(!simple_view<decltype(v)>);
80 
81     assert(v.begin() != v.end());
82     assert(v.begin() + 4 == v.end());
83 
84     // const_iterator (const int*) converted to iterator (int*)
85     assert(v.begin() + 4 == std::as_const(v).end());
86 
87     using Iter = std::ranges::iterator_t<decltype(v)>;
88     using ConstIter = std::ranges::iterator_t<const decltype(v)>;
89     static_assert(!std::is_same_v<Iter, ConstIter>);
90     using Sentinel = std::ranges::sentinel_t<decltype(v)>;
91     using ConstSentinel = std::ranges::sentinel_t<const decltype(v)>;
92     static_assert(!std::is_same_v<Sentinel, ConstSentinel>);
93 
94     static_assert(weakly_equality_comparable_with<Iter, Sentinel>);
95     static_assert(!weakly_equality_comparable_with<ConstIter, Sentinel>);
96     static_assert(weakly_equality_comparable_with<Iter, ConstSentinel>);
97     static_assert(weakly_equality_comparable_with<ConstIter, ConstSentinel>);
98   }
99 
100   {
101     // underlying const/non-const sentinel can be compared with both const/non-const iterator
102     std::ranges::zip_view v{ComparableView(buffer1), ComparableView(buffer2)};
103     static_assert(!std::ranges::common_range<decltype(v)>);
104     static_assert(!simple_view<decltype(v)>);
105 
106     assert(v.begin() != v.end());
107     assert(v.begin() + 4 == v.end());
108     assert(std::as_const(v).begin() + 4 == v.end());
109     assert(std::as_const(v).begin() + 4 == std::as_const(v).end());
110     assert(v.begin() + 4 == std::as_const(v).end());
111 
112     using Iter = std::ranges::iterator_t<decltype(v)>;
113     using ConstIter = std::ranges::iterator_t<const decltype(v)>;
114     static_assert(!std::is_same_v<Iter, ConstIter>);
115     using Sentinel = std::ranges::sentinel_t<decltype(v)>;
116     using ConstSentinel = std::ranges::sentinel_t<const decltype(v)>;
117     static_assert(!std::is_same_v<Sentinel, ConstSentinel>);
118 
119     static_assert(weakly_equality_comparable_with<Iter, Sentinel>);
120     static_assert(weakly_equality_comparable_with<ConstIter, Sentinel>);
121     static_assert(weakly_equality_comparable_with<Iter, ConstSentinel>);
122     static_assert(weakly_equality_comparable_with<ConstIter, ConstSentinel>);
123   }
124 
125   {
126     // underlying const/non-const sentinel cannot be compared with non-const/const iterator
127     std::ranges::zip_view v{ComparableView(buffer1), ConstIncompatibleView{}};
128     static_assert(!std::ranges::common_range<decltype(v)>);
129     static_assert(!simple_view<decltype(v)>);
130 
131     using Iter = std::ranges::iterator_t<decltype(v)>;
132     using ConstIter = std::ranges::iterator_t<const decltype(v)>;
133     static_assert(!std::is_same_v<Iter, ConstIter>);
134     using Sentinel = std::ranges::sentinel_t<decltype(v)>;
135     using ConstSentinel = std::ranges::sentinel_t<const decltype(v)>;
136     static_assert(!std::is_same_v<Sentinel, ConstSentinel>);
137 
138     static_assert(weakly_equality_comparable_with<Iter, Sentinel>);
139     static_assert(!weakly_equality_comparable_with<ConstIter, Sentinel>);
140     static_assert(!weakly_equality_comparable_with<Iter, ConstSentinel>);
141     static_assert(weakly_equality_comparable_with<ConstIter, ConstSentinel>);
142   }
143   return true;
144 }
145 
main(int,char **)146 int main(int, char**) {
147   test();
148   static_assert(test());
149 
150   return 0;
151 }
152