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 #ifndef LIBCXX_TEST_STD_RANGES_RANGE_UTILITY_RANGE_SUBRANGE_TYPES_H 10 #define LIBCXX_TEST_STD_RANGES_RANGE_UTILITY_RANGE_SUBRANGE_TYPES_H 11 12 #include <cstddef> 13 #include <iterator> 14 #include <ranges> 15 #include <type_traits> 16 17 #include "test_macros.h" 18 #include "test_iterators.h" 19 20 int globalBuff[8]; 21 22 struct Empty {}; 23 24 using InputIter = cpp17_input_iterator<int*>; 25 using ForwardIter = forward_iterator<int*>; 26 using BidirIter = bidirectional_iterator<int*>; 27 28 using ForwardSubrange = std::ranges::subrange<ForwardIter, ForwardIter, std::ranges::subrange_kind::unsized>; 29 using SizedIntPtrSubrange = std::ranges::subrange<int*, int*, std::ranges::subrange_kind::sized>; 30 31 struct MoveOnlyForwardIter { 32 typedef std::forward_iterator_tag iterator_category; 33 typedef int value_type; 34 typedef std::ptrdiff_t difference_type; 35 typedef int* pointer; 36 typedef int& reference; 37 typedef MoveOnlyForwardIter self; 38 39 int *base = nullptr; 40 41 MoveOnlyForwardIter() = default; 42 MoveOnlyForwardIter(MoveOnlyForwardIter &&) = default; 43 MoveOnlyForwardIter &operator=(MoveOnlyForwardIter&&) = default; 44 MoveOnlyForwardIter(MoveOnlyForwardIter const&) = delete; MoveOnlyForwardIterMoveOnlyForwardIter45 constexpr MoveOnlyForwardIter(int *ptr) : base(ptr) { } 46 47 friend bool operator==(const self&, const self&); 48 friend constexpr bool operator==(const self& lhs, int* rhs) { return lhs.base == rhs; } 49 50 reference operator*() const; 51 pointer operator->() const; 52 self& operator++(); 53 self operator++(int); 54 self& operator--(); 55 self operator--(int); 56 pointerMoveOnlyForwardIter57 constexpr operator pointer() const { return base; } 58 }; 59 60 struct SizedSentinelForwardIter { 61 typedef std::forward_iterator_tag iterator_category; 62 typedef int value_type; 63 typedef std::ptrdiff_t difference_type; 64 typedef int* pointer; 65 typedef int& reference; 66 typedef std::make_unsigned_t<std::ptrdiff_t> udifference_type; 67 typedef SizedSentinelForwardIter self; 68 69 SizedSentinelForwardIter() = default; SizedSentinelForwardIterSizedSentinelForwardIter70 constexpr explicit SizedSentinelForwardIter(int *ptr, bool *minusWasCalled) 71 : base_(ptr), minusWasCalled_(minusWasCalled) 72 { } 73 74 friend constexpr bool operator==(const self& lhs, const self& rhs) { return lhs.base_ == rhs.base_; } 75 76 reference operator*() const; 77 pointer operator->() const; 78 self& operator++(); 79 self operator++(int); 80 self& operator--(); 81 self operator--(int); 82 83 friend constexpr difference_type operator-(SizedSentinelForwardIter const& a, 84 SizedSentinelForwardIter const& b) { 85 if (a.minusWasCalled_) 86 *a.minusWasCalled_ = true; 87 if (b.minusWasCalled_) 88 *b.minusWasCalled_ = true; 89 return a.base_ - b.base_; 90 } 91 92 private: 93 int *base_ = nullptr; 94 bool *minusWasCalled_ = nullptr; 95 }; 96 static_assert(std::sized_sentinel_for<SizedSentinelForwardIter, SizedSentinelForwardIter>); 97 98 struct ConvertibleForwardIter { 99 typedef std::forward_iterator_tag iterator_category; 100 typedef int value_type; 101 typedef std::ptrdiff_t difference_type; 102 typedef int* pointer; 103 typedef int& reference; 104 typedef ConvertibleForwardIter self; 105 106 int *base_ = nullptr; 107 108 constexpr ConvertibleForwardIter() = default; ConvertibleForwardIterConvertibleForwardIter109 constexpr explicit ConvertibleForwardIter(int *ptr) : base_(ptr) { } 110 111 friend bool operator==(const self&, const self&); 112 113 reference operator*() const; 114 pointer operator->() const; 115 self& operator++(); 116 self operator++(int); 117 self& operator--(); 118 self operator--(int); 119 pointerConvertibleForwardIter120 constexpr operator pointer() const { return base_; } 121 122 // Explicitly deleted so this doesn't model sized_sentinel_for. 123 friend constexpr difference_type operator-(int *, self const&) = delete; 124 friend constexpr difference_type operator-(self const&, int*) = delete; 125 }; 126 using ConvertibleForwardSubrange = std::ranges::subrange<ConvertibleForwardIter, int*, 127 std::ranges::subrange_kind::unsized>; 128 static_assert(std::is_convertible_v<ConvertibleForwardIter, int*>); 129 130 template<bool EnableConvertible> 131 struct ConditionallyConvertibleBase { 132 typedef std::forward_iterator_tag iterator_category; 133 typedef int value_type; 134 typedef std::ptrdiff_t difference_type; 135 typedef int* pointer; 136 typedef int& reference; 137 typedef std::make_unsigned_t<std::ptrdiff_t> udifference_type; 138 typedef ConditionallyConvertibleBase self; 139 140 int *base_ = nullptr; 141 142 constexpr ConditionallyConvertibleBase() = default; ConditionallyConvertibleBaseConditionallyConvertibleBase143 constexpr explicit ConditionallyConvertibleBase(int *ptr) : base_(ptr) {} 144 baseConditionallyConvertibleBase145 constexpr int *base() const { return base_; } 146 147 friend bool operator==(const self&, const self&) = default; 148 149 reference operator*() const; 150 pointer operator->() const; 151 self& operator++(); 152 self operator++(int); 153 self& operator--(); 154 self operator--(int); 155 156 template<bool E = EnableConvertible> 157 requires E pointerConditionallyConvertibleBase158 constexpr operator pointer() const { return base_; } 159 }; 160 using ConditionallyConvertibleIter = ConditionallyConvertibleBase<false>; 161 using SizedSentinelForwardSubrange = std::ranges::subrange<ConditionallyConvertibleIter, 162 ConditionallyConvertibleIter, 163 std::ranges::subrange_kind::sized>; 164 using ConvertibleSizedSentinelForwardIter = ConditionallyConvertibleBase<true>; 165 using ConvertibleSizedSentinelForwardSubrange = std::ranges::subrange<ConvertibleSizedSentinelForwardIter, int*, 166 std::ranges::subrange_kind::sized>; 167 168 struct ForwardBorrowedRange { beginForwardBorrowedRange169 constexpr ForwardIter begin() const { return ForwardIter(globalBuff); } endForwardBorrowedRange170 constexpr ForwardIter end() const { return ForwardIter(globalBuff + 8); } 171 }; 172 173 template<> 174 inline constexpr bool std::ranges::enable_borrowed_range<ForwardBorrowedRange> = true; 175 176 struct ForwardRange { 177 ForwardIter begin() const; 178 ForwardIter end() const; 179 }; 180 181 struct ConvertibleForwardBorrowedRange { beginConvertibleForwardBorrowedRange182 constexpr ConvertibleForwardIter begin() const { return ConvertibleForwardIter(globalBuff); } endConvertibleForwardBorrowedRange183 constexpr int *end() const { return globalBuff + 8; } 184 }; 185 186 template<> 187 inline constexpr bool std::ranges::enable_borrowed_range<ConvertibleForwardBorrowedRange> = true; 188 189 struct ForwardBorrowedRangeDifferentSentinel { 190 struct sentinel { 191 int *value; 192 friend bool operator==(sentinel s, ForwardIter i) { return s.value == base(i); } 193 }; 194 beginForwardBorrowedRangeDifferentSentinel195 constexpr ForwardIter begin() const { return ForwardIter(globalBuff); } endForwardBorrowedRangeDifferentSentinel196 constexpr sentinel end() const { return sentinel{globalBuff + 8}; } 197 }; 198 199 template<> 200 inline constexpr bool std::ranges::enable_borrowed_range<ForwardBorrowedRangeDifferentSentinel> = true; 201 202 using DifferentSentinelSubrange = std::ranges::subrange<ForwardIter, 203 ForwardBorrowedRangeDifferentSentinel::sentinel, 204 std::ranges::subrange_kind::unsized>; 205 206 struct DifferentSentinelWithSizeMember { 207 struct sentinel { 208 int *value; 209 friend bool operator==(sentinel s, ForwardIter i) { return s.value == base(i); } 210 }; 211 beginDifferentSentinelWithSizeMember212 constexpr ForwardIter begin() const { return ForwardIter(globalBuff); } endDifferentSentinelWithSizeMember213 constexpr sentinel end() const { return sentinel{globalBuff + 8}; } sizeDifferentSentinelWithSizeMember214 constexpr std::size_t size() const { return 8; } 215 }; 216 217 template<> 218 inline constexpr bool std::ranges::enable_borrowed_range<DifferentSentinelWithSizeMember> = true; 219 220 using DifferentSentinelWithSizeMemberSubrange = std::ranges::subrange<ForwardIter, 221 DifferentSentinelWithSizeMember::sentinel, 222 std::ranges::subrange_kind::unsized>; 223 224 #endif // LIBCXX_TEST_STD_RANGES_RANGE_UTILITY_RANGE_SUBRANGE_TYPES_H 225