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, c++20 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 <compare> 18 #include <ranges> 19 #include <tuple> 20 21 #include "../types.h" 22 23 using Iterator = random_access_iterator<int*>; 24 using ConstIterator = random_access_iterator<const int*>; 25 26 template <bool Const> 27 struct ComparableSentinel { 28 29 using Iter = std::conditional_t<Const, ConstIterator, Iterator>; 30 Iter iter_; 31 32 explicit ComparableSentinel() = default; 33 constexpr explicit ComparableSentinel(const Iter& it) : iter_(it) {} 34 35 constexpr friend bool operator==(const Iterator& i, const ComparableSentinel& s) { return base(i) == base(s.iter_); } 36 37 constexpr friend bool operator==(const ConstIterator& i, const ComparableSentinel& s) { 38 return base(i) == base(s.iter_); 39 } 40 }; 41 42 struct ComparableView : IntBufferView { 43 using IntBufferView::IntBufferView; 44 45 constexpr auto begin() { return Iterator(buffer_); } 46 constexpr auto begin() const { return ConstIterator(buffer_); } 47 constexpr auto end() { return ComparableSentinel<false>(Iterator(buffer_ + size_)); } 48 constexpr auto end() const { return ComparableSentinel<true>(ConstIterator(buffer_ + size_)); } 49 }; 50 51 struct ConstIncompatibleView : std::ranges::view_base { 52 cpp17_input_iterator<int*> begin(); 53 forward_iterator<const int*> begin() const; 54 sentinel_wrapper<cpp17_input_iterator<int*>> end(); 55 sentinel_wrapper<forward_iterator<const int*>> end() const; 56 }; 57 58 // clang-format off 59 template <class Iter, class Sent> 60 concept EqualComparable = std::invocable<std::equal_to<>, const Iter&, const Sent&>; 61 // clang-format on 62 63 constexpr bool test() { 64 int buffer1[4] = {1, 2, 3, 4}; 65 int buffer2[5] = {1, 2, 3, 4, 5}; 66 int buffer3[8] = {1, 2, 3, 4, 5, 6, 7, 8}; 67 { 68 // simple-view: const and non-const have the same iterator/sentinel type 69 std::ranges::zip_view v{SimpleNonCommon(buffer1), SimpleNonCommon(buffer2), SimpleNonCommon(buffer3)}; 70 static_assert(!std::ranges::common_range<decltype(v)>); 71 LIBCPP_STATIC_ASSERT(std::ranges::__simple_view<decltype(v)>); 72 73 assert(v.begin() != v.end()); 74 assert(v.begin() + 1 != v.end()); 75 assert(v.begin() + 2 != v.end()); 76 assert(v.begin() + 3 != v.end()); 77 assert(v.begin() + 4 == v.end()); 78 } 79 80 { 81 // !simple-view: const and non-const have different iterator/sentinel types 82 std::ranges::zip_view v{NonSimpleNonCommon(buffer1), SimpleNonCommon(buffer2), SimpleNonCommon(buffer3)}; 83 static_assert(!std::ranges::common_range<decltype(v)>); 84 LIBCPP_STATIC_ASSERT(!std::ranges::__simple_view<decltype(v)>); 85 86 assert(v.begin() != v.end()); 87 assert(v.begin() + 4 == v.end()); 88 89 // const_iterator (const int*) converted to iterator (int*) 90 assert(v.begin() + 4 == std::as_const(v).end()); 91 92 using Iter = std::ranges::iterator_t<decltype(v)>; 93 using ConstIter = std::ranges::iterator_t<const decltype(v)>; 94 static_assert(!std::is_same_v<Iter, ConstIter>); 95 using Sentinel = std::ranges::sentinel_t<decltype(v)>; 96 using ConstSentinel = std::ranges::sentinel_t<const decltype(v)>; 97 static_assert(!std::is_same_v<Sentinel, ConstSentinel>); 98 99 static_assert(EqualComparable<Iter, Sentinel>); 100 static_assert(!EqualComparable<ConstIter, Sentinel>); 101 static_assert(EqualComparable<Iter, ConstSentinel>); 102 static_assert(EqualComparable<ConstIter, ConstSentinel>); 103 } 104 105 { 106 // underlying const/non-const sentinel can be compared with both const/non-const iterator 107 std::ranges::zip_view v{ComparableView(buffer1), ComparableView(buffer2)}; 108 static_assert(!std::ranges::common_range<decltype(v)>); 109 LIBCPP_STATIC_ASSERT(!std::ranges::__simple_view<decltype(v)>); 110 111 assert(v.begin() != v.end()); 112 assert(v.begin() + 4 == v.end()); 113 assert(std::as_const(v).begin() + 4 == v.end()); 114 assert(std::as_const(v).begin() + 4 == std::as_const(v).end()); 115 assert(v.begin() + 4 == std::as_const(v).end()); 116 117 using Iter = std::ranges::iterator_t<decltype(v)>; 118 using ConstIter = std::ranges::iterator_t<const decltype(v)>; 119 static_assert(!std::is_same_v<Iter, ConstIter>); 120 using Sentinel = std::ranges::sentinel_t<decltype(v)>; 121 using ConstSentinel = std::ranges::sentinel_t<const decltype(v)>; 122 static_assert(!std::is_same_v<Sentinel, ConstSentinel>); 123 124 static_assert(EqualComparable<Iter, Sentinel>); 125 static_assert(EqualComparable<ConstIter, Sentinel>); 126 static_assert(EqualComparable<Iter, ConstSentinel>); 127 static_assert(EqualComparable<ConstIter, ConstSentinel>); 128 } 129 130 { 131 // underlying const/non-const sentinel cannot be compared with non-const/const iterator 132 std::ranges::zip_view v{ComparableView(buffer1), ConstIncompatibleView{}}; 133 static_assert(!std::ranges::common_range<decltype(v)>); 134 LIBCPP_STATIC_ASSERT(!std::ranges::__simple_view<decltype(v)>); 135 136 using Iter = std::ranges::iterator_t<decltype(v)>; 137 using ConstIter = std::ranges::iterator_t<const decltype(v)>; 138 static_assert(!std::is_same_v<Iter, ConstIter>); 139 using Sentinel = std::ranges::sentinel_t<decltype(v)>; 140 using ConstSentinel = std::ranges::sentinel_t<const decltype(v)>; 141 static_assert(!std::is_same_v<Sentinel, ConstSentinel>); 142 143 static_assert(EqualComparable<Iter, Sentinel>); 144 static_assert(!EqualComparable<ConstIter, Sentinel>); 145 static_assert(!EqualComparable<Iter, ConstSentinel>); 146 static_assert(EqualComparable<ConstIter, ConstSentinel>); 147 } 148 return true; 149 } 150 151 int main(int, char**) { 152 test(); 153 static_assert(test()); 154 155 return 0; 156 } 157