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; |
45 | 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 | |
57 | 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; |
70 | 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; |
109 | 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 | |
120 | 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; |
143 | constexpr explicit ConditionallyConvertibleBase(int *ptr) : base_(ptr) {} |
144 | |
145 | 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 |
158 | 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 { |
169 | constexpr ForwardIter begin() const { return ForwardIter(globalBuff); } |
170 | 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 { |
182 | constexpr ConvertibleForwardIter begin() const { return ConvertibleForwardIter(globalBuff); } |
183 | 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 | |
195 | constexpr ForwardIter begin() const { return ForwardIter(globalBuff); } |
196 | constexpr sentinel end() const { return sentinel{.value: 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 | |
212 | constexpr ForwardIter begin() const { return ForwardIter(globalBuff); } |
213 | constexpr sentinel end() const { return sentinel{.value: globalBuff + 8}; } |
214 | 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 | |