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