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
20int globalBuff[8];
21
22struct Empty {};
23
24using InputIter = cpp17_input_iterator<int*>;
25using ForwardIter = forward_iterator<int*>;
26using BidirIter = bidirectional_iterator<int*>;
27
28using ForwardSubrange = std::ranges::subrange<ForwardIter, ForwardIter, std::ranges::subrange_kind::unsized>;
29using SizedIntPtrSubrange = std::ranges::subrange<int*, int*, std::ranges::subrange_kind::sized>;
30
31struct 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
60struct 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
92private:
93 int *base_ = nullptr;
94 bool *minusWasCalled_ = nullptr;
95};
96static_assert(std::sized_sentinel_for<SizedSentinelForwardIter, SizedSentinelForwardIter>);
97
98struct 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};
126using ConvertibleForwardSubrange = std::ranges::subrange<ConvertibleForwardIter, int*,
127 std::ranges::subrange_kind::unsized>;
128static_assert(std::is_convertible_v<ConvertibleForwardIter, int*>);
129
130template<bool EnableConvertible>
131struct 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};
160using ConditionallyConvertibleIter = ConditionallyConvertibleBase<false>;
161using SizedSentinelForwardSubrange = std::ranges::subrange<ConditionallyConvertibleIter,
162 ConditionallyConvertibleIter,
163 std::ranges::subrange_kind::sized>;
164using ConvertibleSizedSentinelForwardIter = ConditionallyConvertibleBase<true>;
165using ConvertibleSizedSentinelForwardSubrange = std::ranges::subrange<ConvertibleSizedSentinelForwardIter, int*,
166 std::ranges::subrange_kind::sized>;
167
168struct ForwardBorrowedRange {
169 constexpr ForwardIter begin() const { return ForwardIter(globalBuff); }
170 constexpr ForwardIter end() const { return ForwardIter(globalBuff + 8); }
171};
172
173template<>
174inline constexpr bool std::ranges::enable_borrowed_range<ForwardBorrowedRange> = true;
175
176struct ForwardRange {
177 ForwardIter begin() const;
178 ForwardIter end() const;
179};
180
181struct ConvertibleForwardBorrowedRange {
182 constexpr ConvertibleForwardIter begin() const { return ConvertibleForwardIter(globalBuff); }
183 constexpr int *end() const { return globalBuff + 8; }
184};
185
186template<>
187inline constexpr bool std::ranges::enable_borrowed_range<ConvertibleForwardBorrowedRange> = true;
188
189struct 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
199template<>
200inline constexpr bool std::ranges::enable_borrowed_range<ForwardBorrowedRangeDifferentSentinel> = true;
201
202using DifferentSentinelSubrange = std::ranges::subrange<ForwardIter,
203 ForwardBorrowedRangeDifferentSentinel::sentinel,
204 std::ranges::subrange_kind::unsized>;
205
206struct 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
217template<>
218inline constexpr bool std::ranges::enable_borrowed_range<DifferentSentinelWithSizeMember> = true;
219
220using 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

source code of libcxx/test/std/ranges/range.utility/range.subrange/types.h