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
23using Iterator = random_access_iterator<int*>;
24using ConstIterator = random_access_iterator<const int*>;
25
26template <bool Const>
27struct ComparableSentinel {
28
29 using Iter = std::conditional_t<Const, ConstIterator, Iterator>;
30 Iter iter_;
31
32 explicit ComparableSentinel() = default;
33 constexpr explicit ComparableSentinel(const Iter& it) : iter_(it) {}
34
35 constexpr friend bool operator==(const Iterator& i, const ComparableSentinel& s) { return base(i) == base(s.iter_); }
36
37 constexpr friend bool operator==(const ConstIterator& i, const ComparableSentinel& s) {
38 return base(i) == base(s.iter_);
39 }
40};
41
42struct ComparableView : IntBufferView {
43 using IntBufferView::IntBufferView;
44
45 constexpr auto begin() { return Iterator(buffer_); }
46 constexpr auto begin() const { return ConstIterator(buffer_); }
47 constexpr auto end() { return ComparableSentinel<false>(Iterator(buffer_ + size_)); }
48 constexpr auto end() const { return ComparableSentinel<true>(ConstIterator(buffer_ + size_)); }
49};
50
51struct 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
58constexpr 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
146int main(int, char**) {
147 test();
148 static_assert(test());
149
150 return 0;
151}
152

source code of libcxx/test/std/ranges/range.adaptors/range.zip/sentinel/eq.pass.cpp