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