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