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
22template <bool Const>
23struct 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
30 constexpr decltype(auto) operator*() const { return *it_; }
31 constexpr Iter& operator++() {
32 ++it_;
33 return *this;
34 }
35 constexpr void operator++(int) { ++it_; }
36};
37
38template <bool Const>
39struct Sent {
40 std::tuple<int>* end_;
41
42 constexpr bool operator==(const Iter<Const>& i) const { return i.it_ == end_; }
43};
44
45template <bool Const>
46struct CrossComparableSent {
47 std::tuple<int>* end_;
48
49 template <bool C>
50 constexpr bool operator==(const Iter<C>& i) const {
51 return i.it_ == end_;
52 }
53};
54
55template <template <bool> typename St>
56struct Range : TupleBufferView {
57 using TupleBufferView::TupleBufferView;
58 constexpr Iter<false> begin() { return Iter<false>{buffer_}; }
59 constexpr Iter<true> begin() const { return Iter<true>{buffer_}; }
60 constexpr St<false> end() { return St<false>{buffer_ + size_}; }
61 constexpr St<true> end() const { return St<true>{buffer_ + size_}; }
62};
63
64using R = Range<Sent>;
65using CrossComparableR = Range<CrossComparableSent>;
66
67using std::ranges::elements_view;
68using std::ranges::iterator_t;
69using std::ranges::sentinel_t;
70
71static_assert(weakly_equality_comparable_with<iterator_t<elements_view<R, 0>>, //
72 sentinel_t<elements_view<R, 0>>>);
73
74static_assert(!weakly_equality_comparable_with<iterator_t<const elements_view<R, 0>>, //
75 sentinel_t<elements_view<R, 0>>>);
76
77static_assert(!weakly_equality_comparable_with<iterator_t<elements_view<R, 0>>, //
78 sentinel_t<const elements_view<R, 0>>>);
79
80static_assert(weakly_equality_comparable_with<iterator_t<const elements_view<R, 0>>, //
81 sentinel_t<const elements_view<R, 0>>>);
82
83static_assert(weakly_equality_comparable_with<iterator_t<elements_view<CrossComparableR, 0>>, //
84 sentinel_t<elements_view<CrossComparableR, 0>>>);
85
86static_assert(weakly_equality_comparable_with<iterator_t<const elements_view<CrossComparableR, 0>>, //
87 sentinel_t<elements_view<CrossComparableR, 0>>>);
88
89static_assert(weakly_equality_comparable_with<iterator_t<elements_view<CrossComparableR, 0>>, //
90 sentinel_t<const elements_view<CrossComparableR, 0>>>);
91
92static_assert(weakly_equality_comparable_with<iterator_t<const elements_view<CrossComparableR, 0>>, //
93 sentinel_t<const elements_view<CrossComparableR, 0>>>);
94
95template <class R, bool ConstIter, bool ConstSent>
96constexpr 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
145constexpr 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
156int main(int, char**) {
157 test();
158 static_assert(test());
159
160 return 0;
161}
162

source code of libcxx/test/std/ranges/range.adaptors/range.elements/sentinel/equality.pass.cpp