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; 36 constexpr explicit ConstComparableSentinel(const Iter& it) : iter_(it) {} 37 38 constexpr friend bool operator==(const Iterator& i, const ConstComparableSentinel& s) { 39 return base(i) == base(s.iter_); 40 } 41 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 50 constexpr auto begin() { return Iterator(data_); } 51 constexpr auto begin() const { return ConstIterator(data_); } 52 constexpr auto end() { return ConstComparableSentinel<false>(Iterator(data_ + size_)); } 53 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 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 92 int main(int, char**) { 93 test(); 94 static_assert(test()); 95 96 return 0; 97 } 98