• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 TEST_STD_RANGES_RANGE_ADAPTORS_RANGE_JOIN_TYPES_H
10 #define TEST_STD_RANGES_RANGE_ADAPTORS_RANGE_JOIN_TYPES_H
11 
12 #include <concepts>
13 #include <cstdint>
14 #include <tuple>
15 
16 #include "test_macros.h"
17 #include "test_iterators.h"
18 
19 inline int globalBuffer[4][4] = {
20     {1111, 2222, 3333, 4444},
21     {555, 666, 777, 888},
22     {99, 1010, 1111, 1212},
23     {13, 14, 15, 16},
24 };
25 
26 template <template<class...> class Iter>
27 struct ChildViewBase : std::ranges::view_base {
28   int* ptr_;
29 
30   using iterator = Iter<int*>;
31   using const_iterator = Iter<const int*>;
32   using sentinel = sentinel_wrapper<iterator>;
33   using const_sentinel = sentinel_wrapper<const_iterator>;
34 
ptr_ChildViewBase35   constexpr ChildViewBase(int* ptr = globalBuffer[0]) : ptr_(ptr) {}
36   ChildViewBase(const ChildViewBase&) = delete;
37   ChildViewBase(ChildViewBase&&) = default;
38   ChildViewBase& operator=(const ChildViewBase&) = delete;
39   ChildViewBase& operator=(ChildViewBase&&) = default;
40 
beginChildViewBase41   constexpr iterator begin() { return iterator(ptr_); }
beginChildViewBase42   constexpr const_iterator begin() const { return const_iterator(ptr_); }
endChildViewBase43   constexpr sentinel end() { return sentinel(iterator(ptr_ + 4)); }
endChildViewBase44   constexpr const_sentinel end() const { return const_sentinel(const_iterator(ptr_ + 4)); }
45 };
46 using ChildView = ChildViewBase<cpp20_input_iterator>;
47 
48 inline ChildView globalChildren[4] = {
49     ChildView(globalBuffer[0]),
50     ChildView(globalBuffer[1]),
51     ChildView(globalBuffer[2]),
52     ChildView(globalBuffer[3]),
53 };
54 
55 template <class T>
56 struct ParentView : std::ranges::view_base {
57   T* ptr_;
58   unsigned size_;
59 
60   using iterator = cpp20_input_iterator<T*>;
61   using const_iterator = cpp20_input_iterator<const T*>;
62   using sentinel = sentinel_wrapper<iterator>;
63   using const_sentinel = sentinel_wrapper<const_iterator>;
64 
ptr_ParentView65   constexpr ParentView(T* ptr, unsigned size = 4) : ptr_(ptr), size_(size) {}
66   constexpr ParentView(ChildView* ptr = globalChildren, unsigned size = 4)
67     requires std::same_as<ChildView, T>
ptr_ParentView68   : ptr_(ptr), size_(size) {}
69   ParentView(const ParentView&) = delete;
70   ParentView(ParentView&&) = default;
71   ParentView& operator=(const ParentView&) = delete;
72   ParentView& operator=(ParentView&&) = default;
73 
beginParentView74   constexpr iterator begin() { return iterator(ptr_); }
beginParentView75   constexpr const_iterator begin() const { return const_iterator(ptr_); }
endParentView76   constexpr sentinel end() { return sentinel(iterator(ptr_ + size_)); }
endParentView77   constexpr const_sentinel end() const { return const_sentinel(const_iterator(ptr_ + size_)); }
78 };
79 
80 template <class T>
81 ParentView(T*) -> ParentView<T>;
82 
83 struct CopyableChild : std::ranges::view_base {
84   int* ptr_;
85   unsigned size_;
86 
87   using iterator = cpp17_input_iterator<int*>;
88   using const_iterator = cpp17_input_iterator<const int*>;
89   using sentinel = sentinel_wrapper<iterator>;
90   using const_sentinel = sentinel_wrapper<const_iterator>;
91 
ptr_CopyableChild92   constexpr CopyableChild(int* ptr = globalBuffer[0], unsigned size = 4) : ptr_(ptr), size_(size) {}
93 
beginCopyableChild94   constexpr iterator begin() { return iterator(ptr_); }
beginCopyableChild95   constexpr const_iterator begin() const { return const_iterator(ptr_); }
endCopyableChild96   constexpr sentinel end() { return sentinel(iterator(ptr_ + size_)); }
endCopyableChild97   constexpr const_sentinel end() const { return const_sentinel(const_iterator(ptr_ + size_)); }
98 };
99 
100 struct CopyableParent : std::ranges::view_base {
101   CopyableChild* ptr_;
102 
103   using iterator = cpp17_input_iterator<CopyableChild*>;
104   using const_iterator = cpp17_input_iterator<const CopyableChild*>;
105   using sentinel = sentinel_wrapper<iterator>;
106   using const_sentinel = sentinel_wrapper<const_iterator>;
107 
CopyableParentCopyableParent108   constexpr CopyableParent(CopyableChild* ptr) : ptr_(ptr) {}
109 
beginCopyableParent110   constexpr iterator begin() { return iterator(ptr_); }
beginCopyableParent111   constexpr const_iterator begin() const { return const_iterator(ptr_); }
endCopyableParent112   constexpr sentinel end() { return sentinel(iterator(ptr_ + 4)); }
endCopyableParent113   constexpr const_sentinel end() const { return const_sentinel(const_iterator(ptr_ + 4)); }
114 };
115 
116 struct Box {
117   int x;
118 };
119 
120 template <class T>
121 struct InputValueIter {
122   typedef std::input_iterator_tag iterator_category;
123   typedef T value_type;
124   typedef int difference_type;
125   typedef T reference;
126 
127   T* ptr_ = nullptr;
128   constexpr InputValueIter() = default;
InputValueIterInputValueIter129   constexpr InputValueIter(T* ptr) : ptr_(ptr) {}
130 
131   constexpr T operator*() const { return std::move(*ptr_); }
132   constexpr void operator++(int) { ++ptr_; }
133   constexpr InputValueIter& operator++() {
134     ++ptr_;
135     return *this;
136   }
137 
138   constexpr T* operator->() { return ptr_; }
139 
140   constexpr friend bool operator==(const InputValueIter&, const InputValueIter&) = default;
141 };
142 
143 template <class T>
144 struct ValueView : std::ranges::view_base {
145   InputValueIter<T> ptr_;
146 
147   using sentinel = sentinel_wrapper<InputValueIter<T>>;
148 
ValueViewValueView149   constexpr ValueView(T* ptr) : ptr_(ptr) {}
150 
ValueViewValueView151   constexpr ValueView(ValueView&& other) : ptr_(other.ptr_) { other.ptr_.ptr_ = nullptr; }
152 
153   constexpr ValueView& operator=(ValueView&& other) {
154     ptr_ = other.ptr_;
155     other.ptr_ = InputValueIter<T>(nullptr);
156     return *this;
157   }
158 
159   ValueView(const ValueView&) = delete;
160   ValueView& operator=(const ValueView&) = delete;
161 
beginValueView162   constexpr InputValueIter<T> begin() const { return ptr_; }
endValueView163   constexpr sentinel end() const { return sentinel(InputValueIter<T>(ptr_.ptr_ + 4)); }
164 };
165 
166 template <class Iter, class Sent = Iter, class NonConstIter = Iter, class NonConstSent = Sent>
167 struct BufferView : std::ranges::view_base {
168 
169   using T = std::iter_value_t<Iter>;
170   T* data_;
171   std::size_t size_;
172 
173   template <std::size_t N>
BufferViewBufferView174   constexpr BufferView(T (&b)[N]) : data_(b), size_(N) {}
BufferViewBufferView175   constexpr BufferView(T* p, std::size_t s) : data_(p), size_(s) {}
176 
beginBufferView177   constexpr NonConstIter begin()
178     requires(!std::is_same_v<Iter, NonConstIter>) {
179     return NonConstIter(this->data_);
180   }
beginBufferView181   constexpr Iter begin() const { return Iter(this->data_); }
182 
endBufferView183   constexpr NonConstSent end()
184     requires(!std::is_same_v<Sent, NonConstSent>) {
185     if constexpr (std::is_same_v<NonConstIter, NonConstSent>) {
186       return NonConstIter(this->data_ + this->size_);
187     } else {
188       return NonConstSent(NonConstIter(this->data_ + this->size_));
189     }
190   }
191 
endBufferView192   constexpr Sent end() const {
193     if constexpr (std::is_same_v<Iter, Sent>) {
194       return Iter(this->data_ + this->size_);
195     } else {
196       return Sent(Iter(this->data_ + this->size_));
197     }
198   }
199 };
200 
201 using InputCommonInner = BufferView<common_input_iterator<int*>>;
202 static_assert(std::ranges::input_range<InputCommonInner>);
203 static_assert(!std::ranges::forward_range<InputCommonInner>);
204 static_assert(std::ranges::common_range<InputCommonInner>);
205 
206 using InputNonCommonInner = BufferView<common_input_iterator<int*>, sentinel_wrapper<common_input_iterator<int*>>>;
207 static_assert(std::ranges::input_range<InputNonCommonInner>);
208 static_assert(!std::ranges::forward_range<InputNonCommonInner>);
209 static_assert(!std::ranges::common_range<InputNonCommonInner>);
210 
211 using ForwardCommonInner = BufferView<forward_iterator<int*>>;
212 static_assert(std::ranges::forward_range<ForwardCommonInner>);
213 static_assert(!std::ranges::bidirectional_range<ForwardCommonInner>);
214 static_assert(std::ranges::common_range<ForwardCommonInner>);
215 
216 using ForwardNonCommonInner = BufferView<forward_iterator<int*>, sentinel_wrapper<forward_iterator<int*>>>;
217 static_assert(std::ranges::forward_range<ForwardNonCommonInner>);
218 static_assert(!std::ranges::bidirectional_range<ForwardNonCommonInner>);
219 static_assert(!std::ranges::common_range<ForwardNonCommonInner>);
220 
221 using BidiCommonInner = BufferView<bidirectional_iterator<int*>>;
222 static_assert(std::ranges::bidirectional_range<BidiCommonInner>);
223 static_assert(std::ranges::common_range<BidiCommonInner>);
224 
225 using BidiNonCommonInner = BufferView<bidirectional_iterator<int*>, sentinel_wrapper<bidirectional_iterator<int*>>>;
226 static_assert(std::ranges::bidirectional_range<BidiNonCommonInner>);
227 static_assert(!std::ranges::common_range<BidiNonCommonInner>);
228 
229 template <class Inner = BufferView<int*>>
230 using SimpleInputCommonOuter = BufferView<common_input_iterator<Inner*>>;
231 static_assert(!std::ranges::forward_range<SimpleInputCommonOuter<>>);
232 static_assert(!std::ranges::bidirectional_range<SimpleInputCommonOuter<>>);
233 static_assert(std::ranges::common_range<SimpleInputCommonOuter<>>);
234 LIBCPP_STATIC_ASSERT(std::ranges::__simple_view<SimpleInputCommonOuter<>>);
235 
236 template <class Inner = BufferView<int*>>
237 using NonSimpleInputCommonOuter = BufferView<common_input_iterator<const Inner*>, common_input_iterator<const Inner*>,
238                                              common_input_iterator< Inner*>, common_input_iterator< Inner*>>;
239 static_assert(!std::ranges::forward_range<NonSimpleInputCommonOuter<>>);
240 static_assert(!std::ranges::bidirectional_range<NonSimpleInputCommonOuter<>>);
241 static_assert(std::ranges::common_range<NonSimpleInputCommonOuter<>>);
242 LIBCPP_STATIC_ASSERT(!std::ranges::__simple_view<NonSimpleInputCommonOuter<>>);
243 
244 template <class Inner = BufferView<int*>>
245 using SimpleForwardCommonOuter = BufferView<forward_iterator<Inner*>>;
246 static_assert(std::ranges::forward_range<SimpleForwardCommonOuter<>>);
247 static_assert(!std::ranges::bidirectional_range<SimpleForwardCommonOuter<>>);
248 static_assert(std::ranges::common_range<SimpleForwardCommonOuter<>>);
249 LIBCPP_STATIC_ASSERT(std::ranges::__simple_view<SimpleForwardCommonOuter<>>);
250 
251 template <class Inner = BufferView<int*>>
252 using NonSimpleForwardCommonOuter = BufferView<forward_iterator<const Inner*>, forward_iterator<const Inner*>,
253                                                forward_iterator<Inner*>, forward_iterator<Inner*>>;
254 static_assert(std::ranges::forward_range<NonSimpleForwardCommonOuter<>>);
255 static_assert(!std::ranges::bidirectional_range<NonSimpleForwardCommonOuter<>>);
256 static_assert(std::ranges::common_range<NonSimpleForwardCommonOuter<>>);
257 LIBCPP_STATIC_ASSERT(!std::ranges::__simple_view<NonSimpleForwardCommonOuter<>>);
258 
259 template <class Inner = BufferView<int*>>
260 using SimpleForwardNonCommonOuter = BufferView<forward_iterator<Inner*>, sentinel_wrapper<forward_iterator<Inner*>>>;
261 static_assert(std::ranges::forward_range<SimpleForwardNonCommonOuter<>>);
262 static_assert(!std::ranges::bidirectional_range<SimpleForwardNonCommonOuter<>>);
263 static_assert(!std::ranges::common_range<SimpleForwardNonCommonOuter<>>);
264 LIBCPP_STATIC_ASSERT(std::ranges::__simple_view<SimpleForwardNonCommonOuter<>>);
265 
266 template <class Inner = BufferView<int*>>
267 using NonSimpleForwardNonCommonOuter =
268     BufferView<forward_iterator<const Inner*>, sentinel_wrapper<forward_iterator<const Inner*>>,
269                forward_iterator<Inner*>, sentinel_wrapper<forward_iterator<Inner*>>>;
270 static_assert(std::ranges::forward_range<NonSimpleForwardNonCommonOuter<>>);
271 static_assert(!std::ranges::bidirectional_range<NonSimpleForwardNonCommonOuter<>>);
272 static_assert(!std::ranges::common_range<NonSimpleForwardNonCommonOuter<>>);
273 LIBCPP_STATIC_ASSERT(!std::ranges::__simple_view<NonSimpleForwardNonCommonOuter<>>);
274 
275 template <class Inner = BufferView<int*>>
276 using BidiCommonOuter = BufferView<bidirectional_iterator<Inner*>>;
277 static_assert(std::ranges::bidirectional_range<BidiCommonOuter<>>);
278 static_assert(std::ranges::common_range<BidiCommonOuter<>>);
279 LIBCPP_STATIC_ASSERT(std::ranges::__simple_view<BidiCommonOuter<>>);
280 
281 // an iterator where its operator* makes a copy of underlying operator*
282 template <class It>
283 struct copying_iterator {
284   It it_ = It();
285 
286   using value_type = typename std::iterator_traits<It>::value_type;
287   using difference_type = typename std::iterator_traits<It>::difference_type;
288   using pointer = typename std::iterator_traits<It>::pointer;
289 
290   copying_iterator() requires std::default_initializable<It> = default;
copying_iteratorcopying_iterator291   constexpr copying_iterator(It it) : it_(std::move(it)) {}
292 
293   // makes a copy of underlying operator* to create a PRValue
294   constexpr value_type operator*() const { return *it_; }
295 
296   constexpr copying_iterator& operator++() {
297     ++it_;
298     return *this;
299   }
300   constexpr copying_iterator& operator--()
301     requires std::bidirectional_iterator<It> {
302     --it_;
303     return *this;
304   }
305   constexpr copying_iterator operator++(int)
306     requires std::forward_iterator<It> {
307     return copying_iterator(it_++);
308   }
309   constexpr void operator++(int) { return it_++; }
310   constexpr copying_iterator operator--(int)
311     requires std::bidirectional_iterator<It> {
312     return copying_iterator(it_--);
313   }
314 
315   friend constexpr bool operator==(const copying_iterator& x, const copying_iterator& y) = default;
316 };
317 
318 template <class Outer>
319 struct InnerRValue : Outer {
320 
321   using iterator = copying_iterator<std::ranges::iterator_t<Outer>>;
322   using const_iterator = copying_iterator<std::ranges::iterator_t<const Outer>>;
323   using sentinel = copying_iterator<std::ranges::sentinel_t<Outer>>;
324   using const_sentinel = copying_iterator<std::ranges::sentinel_t<const Outer>>;
325 
326   using Outer::Outer;
327   static_assert(std::ranges::common_range<Outer>, "non-common range is not supported yet");
328 
beginInnerRValue329   constexpr iterator begin() { return Outer::begin(); }
beginInnerRValue330   constexpr const_iterator begin() const
331     requires std::ranges::range<const Outer> {
332     return Outer::begin();
333   }
334 
endInnerRValue335   constexpr auto end() { return iterator{Outer::end()}; }
endInnerRValue336   constexpr auto end() const
337     requires std::ranges::range<const Outer> {
338     return const_iterator{Outer::end()};
339   }
340 };
341 static_assert(std::ranges::forward_range<InnerRValue<SimpleForwardCommonOuter<>>>);
342 static_assert(!std::ranges::bidirectional_range<InnerRValue<SimpleForwardCommonOuter<>>>);
343 static_assert(std::ranges::common_range<InnerRValue<SimpleForwardCommonOuter<>>>);
344 LIBCPP_STATIC_ASSERT(std::ranges::__simple_view<InnerRValue<SimpleForwardCommonOuter<>>>);
345 static_assert(!std::is_lvalue_reference_v<std::ranges::range_reference_t<InnerRValue<SimpleForwardCommonOuter<>>>>);
346 
347 struct move_swap_aware_iter {
348 
349   // This is a proxy-like iterator where `reference` is a prvalue, and
350   // `reference` and `value_type` are distinct types (similar to `zip_view::iterator`).
351   using value_type = std::pair<int, int>;
352   using reference = std::pair<int&, int&>;
353   using rvalue_reference = std::pair<int&&, int&&>;
354 
355   using difference_type = std::intptr_t;
356   using iterator_concept = std::input_iterator_tag;
357 
358   int* iter_move_called = nullptr;
359   int* iter_swap_called = nullptr;
360   int* i_ = nullptr;
361 
362   constexpr move_swap_aware_iter& operator++() {
363     ++i_;
364     return *this;
365   }
366   constexpr void operator++(int) { ++i_; }
367 
368   constexpr reference operator*() const { return reference(*i_, *i_); }
369   constexpr friend bool operator==(const move_swap_aware_iter& x, const move_swap_aware_iter& y) {
370     return x.i_ == y.i_;
371   }
372 
iter_movemove_swap_aware_iter373   constexpr friend rvalue_reference iter_move(const move_swap_aware_iter& x) noexcept {
374     ++(*x.iter_move_called);
375     return rvalue_reference{std::move(*x.i_), std::move(*x.i_)};
376   }
377 
iter_swapmove_swap_aware_iter378   constexpr friend void iter_swap(const move_swap_aware_iter& x, const move_swap_aware_iter& y) noexcept {
379     ++(*x.iter_swap_called);
380     std::swap(*x.i_, *y.i_);
381   }
382 };
383 
384 struct IterMoveSwapAwareView : BufferView<int*> {
385   int iter_move_called = 0;
386   int iter_swap_called = 0;
387   using BufferView<int*>::BufferView;
388 
beginIterMoveSwapAwareView389   constexpr auto begin() { return move_swap_aware_iter{&iter_move_called, &iter_swap_called, data_}; }
390 
endIterMoveSwapAwareView391   constexpr auto end() { return move_swap_aware_iter{&iter_move_called, &iter_swap_called, data_ + size_}; }
392 };
393 static_assert(std::ranges::input_range<IterMoveSwapAwareView>);
394 
395 #endif // TEST_STD_RANGES_RANGE_ADAPTORS_RANGE_JOIN_TYPES_H
396