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 // UNSUPPORTED: libcpp-has-no-incomplete-ranges
11
12 // template<bool OtherConst>
13 // requires sentinel_for<sentinel_t<Base>, iterator_t<maybe-const<OtherConst, V>>>
14 // friend constexpr bool operator==(const iterator<OtherConst>& x, const sentinel& y);
15
16 #include <cassert>
17 #include <concepts>
18 #include <functional>
19 #include <ranges>
20
21 #include "../types.h"
22
23 template <class Iter, class Sent>
24 concept EqualityComparable = std::invocable<std::equal_to<>, const Iter&, const Sent&> ;
25
26 using Iterator = random_access_iterator<BufferView<int*>*>;
27 using ConstIterator = random_access_iterator<const BufferView<int*>*>;
28
29 template <bool Const>
30 struct ConstComparableSentinel {
31
32 using Iter = std::conditional_t<Const, ConstIterator, Iterator>;
33 Iter iter_;
34
35 explicit ConstComparableSentinel() = default;
ConstComparableSentinelConstComparableSentinel36 constexpr explicit ConstComparableSentinel(const Iter& it) : iter_(it) {}
37
operator ==(const Iterator & i,const ConstComparableSentinel & s)38 constexpr friend bool operator==(const Iterator& i, const ConstComparableSentinel& s) {
39 return base(i) == base(s.iter_);
40 }
41
operator ==(const ConstIterator & i,const ConstComparableSentinel & s)42 constexpr friend bool operator==(const ConstIterator& i, const ConstComparableSentinel& s) {
43 return base(i) == base(s.iter_);
44 }
45 };
46
47 struct ConstComparableView : BufferView<BufferView<int*>*> {
48 using BufferView<BufferView<int*>*>::BufferView;
49
beginConstComparableView50 constexpr auto begin() { return Iterator(data_); }
beginConstComparableView51 constexpr auto begin() const { return ConstIterator(data_); }
endConstComparableView52 constexpr auto end() { return ConstComparableSentinel<false>(Iterator(data_ + size_)); }
endConstComparableView53 constexpr auto end() const { return ConstComparableSentinel<true>(ConstIterator(data_ + size_)); }
54 };
55
56 static_assert(EqualityComparable<std::ranges::iterator_t<ConstComparableView>,
57 std::ranges::sentinel_t<const ConstComparableView>>);
58 static_assert(EqualityComparable<std::ranges::iterator_t<const ConstComparableView>,
59 std::ranges::sentinel_t<ConstComparableView>>);
60
test()61 constexpr bool test() {
62 int buffer[4][4] = {{1111, 2222, 3333, 4444}, {555, 666, 777, 888}, {99, 1010, 1111, 1212}, {13, 14, 15, 16}};
63
64 {
65 ChildView children[4] = {ChildView(buffer[0]), ChildView(buffer[1]), ChildView(buffer[2]), ChildView(buffer[3])};
66 auto jv = std::ranges::join_view(ParentView(children));
67 assert(jv.end() == std::ranges::next(jv.begin(), 16));
68 static_assert(!EqualityComparable<decltype(std::as_const(jv).begin()), decltype(jv.end())>);
69 static_assert(!EqualityComparable<decltype(jv.begin()), decltype(std::as_const(jv).end())>);
70 }
71
72 {
73 CopyableChild children[4] = {CopyableChild(buffer[0]), CopyableChild(buffer[1]), CopyableChild(buffer[2]),
74 CopyableChild(buffer[3])};
75 const auto jv = std::ranges::join_view(ParentView(children));
76 assert(jv.end() == std::ranges::next(jv.begin(), 16));
77 }
78
79 // test iterator<Const> == sentinel<!Const>
80 {
81 BufferView<int*> inners[] = {buffer[0], buffer[1]};
82 ConstComparableView outer(inners);
83 auto jv = std::ranges::join_view(outer);
84 assert(jv.end() == std::ranges::next(jv.begin(), 8));
85 assert(std::as_const(jv).end() == std::ranges::next(jv.begin(), 8));
86 assert(jv.end() == std::ranges::next(std::as_const(jv).begin(), 8));
87 }
88
89 return true;
90 }
91
main(int,char **)92 int main(int, char**) {
93 test();
94 static_assert(test());
95
96 return 0;
97 }
98