xref: /llvm-project/libcxx/test/std/ranges/range.adaptors/range.join/types.h (revision e07a2f49e3d3c13b6e9b89e0f6118652f2b2d3ac)
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 <string>
15 #include <tuple>
16 
17 #include "test_macros.h"
18 #include "test_iterators.h"
19 #include "test_range.h"
20 
21 inline int globalBuffer[4][4] = {
22     {1111, 2222, 3333, 4444},
23     {555, 666, 777, 888},
24     {99, 1010, 1111, 1212},
25     {13, 14, 15, 16},
26 };
27 
28 template <template<class...> class Iter>
29 struct ChildViewBase : std::ranges::view_base {
30   int* ptr_;
31 
32   using iterator = Iter<int*>;
33   using const_iterator = Iter<const int*>;
34   using sentinel = sentinel_wrapper<iterator>;
35   using const_sentinel = sentinel_wrapper<const_iterator>;
36 
ptr_ChildViewBase37   constexpr ChildViewBase(int* ptr = globalBuffer[0]) : ptr_(ptr) {}
38   ChildViewBase(const ChildViewBase&) = delete;
39   ChildViewBase(ChildViewBase&&) = default;
40   ChildViewBase& operator=(const ChildViewBase&) = delete;
41   ChildViewBase& operator=(ChildViewBase&&) = default;
42 
beginChildViewBase43   constexpr iterator begin() { return iterator(ptr_); }
beginChildViewBase44   constexpr const_iterator begin() const { return const_iterator(ptr_); }
endChildViewBase45   constexpr sentinel end() { return sentinel(iterator(ptr_ + 4)); }
endChildViewBase46   constexpr const_sentinel end() const { return const_sentinel(const_iterator(ptr_ + 4)); }
47 };
48 using ChildView = ChildViewBase<cpp20_input_iterator>;
49 
50 inline ChildView globalChildren[4] = {
51     ChildView(globalBuffer[0]),
52     ChildView(globalBuffer[1]),
53     ChildView(globalBuffer[2]),
54     ChildView(globalBuffer[3]),
55 };
56 
57 template <class T, template<class...> class Iter = cpp17_input_iterator>
58 struct ParentView : std::ranges::view_base {
59   T* ptr_;
60   unsigned size_;
61 
62   using iterator = Iter<T*>;
63   using const_iterator = Iter<const T*>;
64   using sentinel = sentinel_wrapper<iterator>;
65   using const_sentinel = sentinel_wrapper<const_iterator>;
66 
ptr_ParentView67   constexpr ParentView(T* ptr, unsigned size = 4) : ptr_(ptr), size_(size) {}
68   constexpr ParentView(ChildView* ptr = globalChildren, unsigned size = 4)
69     requires std::same_as<ChildView, T>
ptr_ParentView70   : ptr_(ptr), size_(size) {}
71   ParentView(const ParentView&) = delete;
72   ParentView(ParentView&&) = default;
73   ParentView& operator=(const ParentView&) = delete;
74   ParentView& operator=(ParentView&&) = default;
75 
beginParentView76   constexpr iterator begin() { return iterator(ptr_); }
beginParentView77   constexpr const_iterator begin() const { return const_iterator(ptr_); }
endParentView78   constexpr sentinel end() { return sentinel(iterator(ptr_ + size_)); }
endParentView79   constexpr const_sentinel end() const { return const_sentinel(const_iterator(ptr_ + size_)); }
80 };
81 
82 template <class T>
83 ParentView(T*) -> ParentView<T>;
84 
85 template<class T>
86 using ForwardParentView = ParentView<T, forward_iterator>;
87 
88 struct CopyableChild : std::ranges::view_base {
89   int* ptr_;
90   unsigned size_;
91 
92   using iterator = cpp17_input_iterator<int*>;
93   using const_iterator = cpp17_input_iterator<const int*>;
94   using sentinel = sentinel_wrapper<iterator>;
95   using const_sentinel = sentinel_wrapper<const_iterator>;
96 
ptr_CopyableChild97   constexpr CopyableChild(int* ptr = globalBuffer[0], unsigned size = 4) : ptr_(ptr), size_(size) {}
98 
beginCopyableChild99   constexpr iterator begin() { return iterator(ptr_); }
beginCopyableChild100   constexpr const_iterator begin() const { return const_iterator(ptr_); }
endCopyableChild101   constexpr sentinel end() { return sentinel(iterator(ptr_ + size_)); }
endCopyableChild102   constexpr const_sentinel end() const { return const_sentinel(const_iterator(ptr_ + size_)); }
103 };
104 
105 template<template<class...> class Iter>
106 struct CopyableParentTemplate : std::ranges::view_base {
107   CopyableChild* ptr_;
108 
109   using iterator = Iter<CopyableChild*>;
110   using const_iterator = Iter<const CopyableChild*>;
111   using sentinel = sentinel_wrapper<iterator>;
112   using const_sentinel = sentinel_wrapper<const_iterator>;
113 
CopyableParentTemplateCopyableParentTemplate114   constexpr CopyableParentTemplate(CopyableChild* ptr) : ptr_(ptr) {}
115 
beginCopyableParentTemplate116   constexpr iterator begin() { return iterator(ptr_); }
beginCopyableParentTemplate117   constexpr const_iterator begin() const { return const_iterator(ptr_); }
endCopyableParentTemplate118   constexpr sentinel end() { return sentinel(iterator(ptr_ + 4)); }
endCopyableParentTemplate119   constexpr const_sentinel end() const { return const_sentinel(const_iterator(ptr_ + 4)); }
120 };
121 
122 using CopyableParent = CopyableParentTemplate<cpp17_input_iterator>;
123 using ForwardCopyableParent = CopyableParentTemplate<forward_iterator>;
124 
125 struct Box {
126   int x;
127 };
128 
129 template <class T>
130 struct InputValueIter {
131   typedef std::input_iterator_tag iterator_category;
132   typedef T value_type;
133   typedef int difference_type;
134   typedef T reference;
135 
136   T* ptr_ = nullptr;
137   constexpr InputValueIter() = default;
InputValueIterInputValueIter138   constexpr InputValueIter(T* ptr) : ptr_(ptr) {}
139 
140   constexpr T operator*() const { return std::move(*ptr_); }
141   constexpr void operator++(int) { ++ptr_; }
142   constexpr InputValueIter& operator++() {
143     ++ptr_;
144     return *this;
145   }
146 
147   constexpr T* operator->() { return ptr_; }
148 
149   constexpr friend bool operator==(const InputValueIter&, const InputValueIter&) = default;
150 };
151 
152 template <class T>
153 struct ValueView : std::ranges::view_base {
154   InputValueIter<T> ptr_;
155 
156   using sentinel = sentinel_wrapper<InputValueIter<T>>;
157 
ValueViewValueView158   constexpr ValueView(T* ptr) : ptr_(ptr) {}
159 
ValueViewValueView160   constexpr ValueView(ValueView&& other) : ptr_(other.ptr_) { other.ptr_.ptr_ = nullptr; }
161 
162   constexpr ValueView& operator=(ValueView&& other) {
163     ptr_ = other.ptr_;
164     other.ptr_ = InputValueIter<T>(nullptr);
165     return *this;
166   }
167 
168   ValueView(const ValueView&) = delete;
169   ValueView& operator=(const ValueView&) = delete;
170 
beginValueView171   constexpr InputValueIter<T> begin() const { return ptr_; }
endValueView172   constexpr sentinel end() const { return sentinel(InputValueIter<T>(ptr_.ptr_ + 4)); }
173 };
174 
175 template <class Iter, class Sent = Iter, class NonConstIter = Iter, class NonConstSent = Sent>
176 struct BufferView : std::ranges::view_base {
177 
178   using T = std::iter_value_t<Iter>;
179   T* data_;
180   std::size_t size_;
181 
182   template <std::size_t N>
BufferViewBufferView183   constexpr BufferView(T (&b)[N]) : data_(b), size_(N) {}
BufferViewBufferView184   constexpr BufferView(T* p, std::size_t s) : data_(p), size_(s) {}
185 
beginBufferView186   constexpr NonConstIter begin()
187     requires(!std::is_same_v<Iter, NonConstIter>) {
188     return NonConstIter(this->data_);
189   }
beginBufferView190   constexpr Iter begin() const { return Iter(this->data_); }
191 
endBufferView192   constexpr NonConstSent end()
193     requires(!std::is_same_v<Sent, NonConstSent>) {
194     if constexpr (std::is_same_v<NonConstIter, NonConstSent>) {
195       return NonConstIter(this->data_ + this->size_);
196     } else {
197       return NonConstSent(NonConstIter(this->data_ + this->size_));
198     }
199   }
200 
endBufferView201   constexpr Sent end() const {
202     if constexpr (std::is_same_v<Iter, Sent>) {
203       return Iter(this->data_ + this->size_);
204     } else {
205       return Sent(Iter(this->data_ + this->size_));
206     }
207   }
208 };
209 
210 using InputCommonInner = BufferView<common_input_iterator<int*>>;
211 static_assert(std::ranges::input_range<InputCommonInner>);
212 static_assert(!std::ranges::forward_range<InputCommonInner>);
213 static_assert(std::ranges::common_range<InputCommonInner>);
214 
215 using InputNonCommonInner = BufferView<common_input_iterator<int*>, sentinel_wrapper<common_input_iterator<int*>>>;
216 static_assert(std::ranges::input_range<InputNonCommonInner>);
217 static_assert(!std::ranges::forward_range<InputNonCommonInner>);
218 static_assert(!std::ranges::common_range<InputNonCommonInner>);
219 
220 using ForwardCommonInner = BufferView<forward_iterator<int*>>;
221 static_assert(std::ranges::forward_range<ForwardCommonInner>);
222 static_assert(!std::ranges::bidirectional_range<ForwardCommonInner>);
223 static_assert(std::ranges::common_range<ForwardCommonInner>);
224 
225 using ForwardNonCommonInner = BufferView<forward_iterator<int*>, sentinel_wrapper<forward_iterator<int*>>>;
226 static_assert(std::ranges::forward_range<ForwardNonCommonInner>);
227 static_assert(!std::ranges::bidirectional_range<ForwardNonCommonInner>);
228 static_assert(!std::ranges::common_range<ForwardNonCommonInner>);
229 
230 using BidiCommonInner = BufferView<bidirectional_iterator<int*>>;
231 static_assert(std::ranges::bidirectional_range<BidiCommonInner>);
232 static_assert(std::ranges::common_range<BidiCommonInner>);
233 
234 using BidiNonCommonInner = BufferView<bidirectional_iterator<int*>, sentinel_wrapper<bidirectional_iterator<int*>>>;
235 static_assert(std::ranges::bidirectional_range<BidiNonCommonInner>);
236 static_assert(!std::ranges::common_range<BidiNonCommonInner>);
237 
238 template <class Inner = BufferView<int*>>
239 using SimpleInputCommonOuter = BufferView<common_input_iterator<Inner*>>;
240 static_assert(!std::ranges::forward_range<SimpleInputCommonOuter<>>);
241 static_assert(!std::ranges::bidirectional_range<SimpleInputCommonOuter<>>);
242 static_assert(std::ranges::common_range<SimpleInputCommonOuter<>>);
243 static_assert(simple_view<SimpleInputCommonOuter<>>);
244 
245 template <class Inner = BufferView<int*>>
246 using NonSimpleInputCommonOuter = BufferView<common_input_iterator<const Inner*>, common_input_iterator<const Inner*>,
247                                              common_input_iterator< Inner*>, common_input_iterator< Inner*>>;
248 static_assert(!std::ranges::forward_range<NonSimpleInputCommonOuter<>>);
249 static_assert(!std::ranges::bidirectional_range<NonSimpleInputCommonOuter<>>);
250 static_assert(std::ranges::common_range<NonSimpleInputCommonOuter<>>);
251 static_assert(!simple_view<NonSimpleInputCommonOuter<>>);
252 
253 template <class Inner = BufferView<int*>>
254 using SimpleForwardCommonOuter = BufferView<forward_iterator<Inner*>>;
255 static_assert(std::ranges::forward_range<SimpleForwardCommonOuter<>>);
256 static_assert(!std::ranges::bidirectional_range<SimpleForwardCommonOuter<>>);
257 static_assert(std::ranges::common_range<SimpleForwardCommonOuter<>>);
258 static_assert(simple_view<SimpleForwardCommonOuter<>>);
259 
260 template <class Inner = BufferView<int*>>
261 using NonSimpleForwardCommonOuter = BufferView<forward_iterator<const Inner*>, forward_iterator<const Inner*>,
262                                                forward_iterator<Inner*>, forward_iterator<Inner*>>;
263 static_assert(std::ranges::forward_range<NonSimpleForwardCommonOuter<>>);
264 static_assert(!std::ranges::bidirectional_range<NonSimpleForwardCommonOuter<>>);
265 static_assert(std::ranges::common_range<NonSimpleForwardCommonOuter<>>);
266 static_assert(!simple_view<NonSimpleForwardCommonOuter<>>);
267 
268 template <class Inner = BufferView<int*>>
269 using SimpleForwardNonCommonOuter = BufferView<forward_iterator<Inner*>, sentinel_wrapper<forward_iterator<Inner*>>>;
270 static_assert(std::ranges::forward_range<SimpleForwardNonCommonOuter<>>);
271 static_assert(!std::ranges::bidirectional_range<SimpleForwardNonCommonOuter<>>);
272 static_assert(!std::ranges::common_range<SimpleForwardNonCommonOuter<>>);
273 static_assert(simple_view<SimpleForwardNonCommonOuter<>>);
274 
275 template <class Inner = BufferView<int*>>
276 using NonSimpleForwardNonCommonOuter =
277     BufferView<forward_iterator<const Inner*>, sentinel_wrapper<forward_iterator<const Inner*>>,
278                forward_iterator<Inner*>, sentinel_wrapper<forward_iterator<Inner*>>>;
279 static_assert(std::ranges::forward_range<NonSimpleForwardNonCommonOuter<>>);
280 static_assert(!std::ranges::bidirectional_range<NonSimpleForwardNonCommonOuter<>>);
281 static_assert(!std::ranges::common_range<NonSimpleForwardNonCommonOuter<>>);
282 static_assert(!simple_view<NonSimpleForwardNonCommonOuter<>>);
283 
284 template <class Inner = BufferView<int*>>
285 using BidiCommonOuter = BufferView<bidirectional_iterator<Inner*>>;
286 static_assert(std::ranges::bidirectional_range<BidiCommonOuter<>>);
287 static_assert(std::ranges::common_range<BidiCommonOuter<>>);
288 static_assert(simple_view<BidiCommonOuter<>>);
289 
290 // an iterator where its operator* makes a copy of underlying operator*
291 template <class It>
292 struct copying_iterator {
293   It it_ = It();
294 
295   using value_type = typename std::iterator_traits<It>::value_type;
296   using difference_type = typename std::iterator_traits<It>::difference_type;
297   using pointer = typename std::iterator_traits<It>::pointer;
298 
299   copying_iterator() requires std::default_initializable<It> = default;
copying_iteratorcopying_iterator300   constexpr copying_iterator(It it) : it_(std::move(it)) {}
301 
302   // makes a copy of underlying operator* to create a PRValue
303   constexpr value_type operator*() const { return *it_; }
304 
305   constexpr copying_iterator& operator++() {
306     ++it_;
307     return *this;
308   }
309   constexpr copying_iterator& operator--()
310     requires std::bidirectional_iterator<It> {
311     --it_;
312     return *this;
313   }
314   constexpr copying_iterator operator++(int)
315     requires std::forward_iterator<It> {
316     return copying_iterator(it_++);
317   }
318   constexpr void operator++(int) { return it_++; }
319   constexpr copying_iterator operator--(int)
320     requires std::bidirectional_iterator<It> {
321     return copying_iterator(it_--);
322   }
323 
324   friend constexpr bool operator==(const copying_iterator& x, const copying_iterator& y) = default;
325 };
326 
327 template <class Outer>
328 struct InnerRValue : Outer {
329 
330   using iterator = copying_iterator<std::ranges::iterator_t<Outer>>;
331   using const_iterator = copying_iterator<std::ranges::iterator_t<const Outer>>;
332   using sentinel = copying_iterator<std::ranges::sentinel_t<Outer>>;
333   using const_sentinel = copying_iterator<std::ranges::sentinel_t<const Outer>>;
334 
335   using Outer::Outer;
336   static_assert(std::ranges::common_range<Outer>, "non-common range is not supported yet");
337 
beginInnerRValue338   constexpr iterator begin() { return Outer::begin(); }
beginInnerRValue339   constexpr const_iterator begin() const
340     requires std::ranges::range<const Outer> {
341     return Outer::begin();
342   }
343 
endInnerRValue344   constexpr auto end() { return iterator{Outer::end()}; }
endInnerRValue345   constexpr auto end() const
346     requires std::ranges::range<const Outer> {
347     return const_iterator{Outer::end()};
348   }
349 };
350 static_assert(std::ranges::forward_range<InnerRValue<SimpleForwardCommonOuter<>>>);
351 static_assert(!std::ranges::bidirectional_range<InnerRValue<SimpleForwardCommonOuter<>>>);
352 static_assert(std::ranges::common_range<InnerRValue<SimpleForwardCommonOuter<>>>);
353 static_assert(simple_view<InnerRValue<SimpleForwardCommonOuter<>>>);
354 static_assert(!std::is_lvalue_reference_v<std::ranges::range_reference_t<InnerRValue<SimpleForwardCommonOuter<>>>>);
355 
356 struct move_swap_aware_iter {
357 
358   // This is a proxy-like iterator where `reference` is a prvalue, and
359   // `reference` and `value_type` are distinct types (similar to `zip_view::iterator`).
360   using value_type = std::pair<int, int>;
361   using reference = std::pair<int&, int&>;
362   using rvalue_reference = std::pair<int&&, int&&>;
363 
364   using difference_type = std::intptr_t;
365   using iterator_concept = std::input_iterator_tag;
366 
367   int* iter_move_called = nullptr;
368   int* iter_swap_called = nullptr;
369   int* i_ = nullptr;
370 
371   constexpr move_swap_aware_iter& operator++() {
372     ++i_;
373     return *this;
374   }
375   constexpr void operator++(int) { ++i_; }
376 
377   constexpr reference operator*() const { return reference(*i_, *i_); }
378   constexpr friend bool operator==(const move_swap_aware_iter& x, const move_swap_aware_iter& y) {
379     return x.i_ == y.i_;
380   }
381 
iter_movemove_swap_aware_iter382   constexpr friend rvalue_reference iter_move(const move_swap_aware_iter& x) noexcept {
383     ++(*x.iter_move_called);
384     return rvalue_reference{std::move(*x.i_), std::move(*x.i_)};
385   }
386 
iter_swapmove_swap_aware_iter387   constexpr friend void iter_swap(const move_swap_aware_iter& x, const move_swap_aware_iter& y) noexcept {
388     ++(*x.iter_swap_called);
389     std::swap(*x.i_, *y.i_);
390   }
391 };
392 
393 struct IterMoveSwapAwareView : BufferView<int*> {
394   int iter_move_called = 0;
395   int iter_swap_called = 0;
396   using BufferView<int*>::BufferView;
397 
beginIterMoveSwapAwareView398   constexpr auto begin() { return move_swap_aware_iter{&iter_move_called, &iter_swap_called, data_}; }
399 
endIterMoveSwapAwareView400   constexpr auto end() { return move_swap_aware_iter{&iter_move_called, &iter_swap_called, data_ + size_}; }
401 };
402 static_assert(std::ranges::input_range<IterMoveSwapAwareView>);
403 
404 class StashingIterator {
405 public:
406   using difference_type = std::ptrdiff_t;
407   using value_type      = std::string;
408 
StashingIterator()409   constexpr StashingIterator() : letter_('a') {}
410 
411   constexpr StashingIterator& operator++() {
412     str_ += letter_;
413     ++letter_;
414     return *this;
415   }
416 
417   constexpr void operator++(int) { ++*this; }
418 
419   constexpr value_type operator*() const { return str_; }
420 
421   constexpr bool operator==(std::default_sentinel_t) const { return letter_ > 'z'; }
422 
423 private:
424   char letter_;
425   value_type str_;
426 };
427 
428 using StashingRange = std::ranges::subrange<StashingIterator, std::default_sentinel_t>;
429 static_assert(std::ranges::input_range<StashingRange>);
430 static_assert(!std::ranges::forward_range<StashingRange>);
431 
432 class ConstNonJoinableRange : public std::ranges::view_base {
433 public:
begin()434   constexpr StashingIterator begin() { return {}; }
end()435   constexpr std::default_sentinel_t end() { return {}; }
436 
begin()437   constexpr const int* begin() const { return &val_; }
end()438   constexpr const int* end() const { return &val_ + 1; }
439 
440 private:
441   int val_ = 1;
442 };
443 static_assert(std::ranges::input_range<ConstNonJoinableRange>);
444 static_assert(std::ranges::input_range<const ConstNonJoinableRange>);
445 static_assert(std::ranges::input_range<std::ranges::range_reference_t<ConstNonJoinableRange>>);
446 static_assert(!std::ranges::input_range<std::ranges::range_reference_t<const ConstNonJoinableRange>>);
447 
448 #endif // TEST_STD_RANGES_RANGE_ADAPTORS_RANGE_JOIN_TYPES_H
449