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 struct ChildView : std::ranges::view_base { 27 int* ptr_; 28 29 using iterator = cpp20_input_iterator<int*>; 30 using const_iterator = cpp20_input_iterator<const int*>; 31 using sentinel = sentinel_wrapper<iterator>; 32 using const_sentinel = sentinel_wrapper<const_iterator>; 33 ptr_ChildView34 constexpr ChildView(int* ptr = globalBuffer[0]) : ptr_(ptr) {} 35 ChildView(const ChildView&) = delete; 36 ChildView(ChildView&&) = default; 37 ChildView& operator=(const ChildView&) = delete; 38 ChildView& operator=(ChildView&&) = default; 39 beginChildView40 constexpr iterator begin() { return iterator(ptr_); } beginChildView41 constexpr const_iterator begin() const { return const_iterator(ptr_); } endChildView42 constexpr sentinel end() { return sentinel(iterator(ptr_ + 4)); } endChildView43 constexpr const_sentinel end() const { return const_sentinel(const_iterator(ptr_ + 4)); } 44 }; 45 46 inline ChildView globalChildren[4] = { 47 ChildView(globalBuffer[0]), 48 ChildView(globalBuffer[1]), 49 ChildView(globalBuffer[2]), 50 ChildView(globalBuffer[3]), 51 }; 52 53 template <class T> 54 struct ParentView : std::ranges::view_base { 55 T* ptr_; 56 unsigned size_; 57 58 using iterator = cpp20_input_iterator<T*>; 59 using const_iterator = cpp20_input_iterator<const T*>; 60 using sentinel = sentinel_wrapper<iterator>; 61 using const_sentinel = sentinel_wrapper<const_iterator>; 62 ptr_ParentView63 constexpr ParentView(T* ptr, unsigned size = 4) : ptr_(ptr), size_(size) {} 64 constexpr ParentView(ChildView* ptr = globalChildren, unsigned size = 4) 65 requires std::same_as<ChildView, T> ptr_ParentView66 : ptr_(ptr), size_(size) {} 67 ParentView(const ParentView&) = delete; 68 ParentView(ParentView&&) = default; 69 ParentView& operator=(const ParentView&) = delete; 70 ParentView& operator=(ParentView&&) = default; 71 beginParentView72 constexpr iterator begin() { return iterator(ptr_); } beginParentView73 constexpr const_iterator begin() const { return const_iterator(ptr_); } endParentView74 constexpr sentinel end() { return sentinel(iterator(ptr_ + size_)); } endParentView75 constexpr const_sentinel end() const { return const_sentinel(const_iterator(ptr_ + size_)); } 76 }; 77 78 struct CopyableChild : std::ranges::view_base { 79 int* ptr_; 80 unsigned size_; 81 82 using iterator = cpp17_input_iterator<int*>; 83 using const_iterator = cpp17_input_iterator<const int*>; 84 using sentinel = sentinel_wrapper<iterator>; 85 using const_sentinel = sentinel_wrapper<const_iterator>; 86 ptr_CopyableChild87 constexpr CopyableChild(int* ptr = globalBuffer[0], unsigned size = 4) : ptr_(ptr), size_(size) {} 88 beginCopyableChild89 constexpr iterator begin() { return iterator(ptr_); } beginCopyableChild90 constexpr const_iterator begin() const { return const_iterator(ptr_); } endCopyableChild91 constexpr sentinel end() { return sentinel(iterator(ptr_ + size_)); } endCopyableChild92 constexpr const_sentinel end() const { return const_sentinel(const_iterator(ptr_ + size_)); } 93 }; 94 95 struct CopyableParent : std::ranges::view_base { 96 CopyableChild* ptr_; 97 98 using iterator = cpp17_input_iterator<CopyableChild*>; 99 using const_iterator = cpp17_input_iterator<const CopyableChild*>; 100 using sentinel = sentinel_wrapper<iterator>; 101 using const_sentinel = sentinel_wrapper<const_iterator>; 102 CopyableParentCopyableParent103 constexpr CopyableParent(CopyableChild* ptr) : ptr_(ptr) {} 104 beginCopyableParent105 constexpr iterator begin() { return iterator(ptr_); } beginCopyableParent106 constexpr const_iterator begin() const { return const_iterator(ptr_); } endCopyableParent107 constexpr sentinel end() { return sentinel(iterator(ptr_ + 4)); } endCopyableParent108 constexpr const_sentinel end() const { return const_sentinel(const_iterator(ptr_ + 4)); } 109 }; 110 111 struct Box { 112 int x; 113 }; 114 115 template <class T> 116 struct InputValueIter { 117 typedef std::input_iterator_tag iterator_category; 118 typedef T value_type; 119 typedef int difference_type; 120 typedef T reference; 121 122 T* ptr_ = nullptr; 123 constexpr InputValueIter() = default; InputValueIterInputValueIter124 constexpr InputValueIter(T* ptr) : ptr_(ptr) {} 125 126 constexpr T operator*() const { return std::move(*ptr_); } 127 constexpr void operator++(int) { ++ptr_; } 128 constexpr InputValueIter& operator++() { 129 ++ptr_; 130 return *this; 131 } 132 133 constexpr T* operator->() { return ptr_; } 134 135 constexpr friend bool operator==(const InputValueIter&, const InputValueIter&) = default; 136 }; 137 138 template <class T> 139 struct ValueView : std::ranges::view_base { 140 InputValueIter<T> ptr_; 141 142 using sentinel = sentinel_wrapper<InputValueIter<T>>; 143 ValueViewValueView144 constexpr ValueView(T* ptr) : ptr_(ptr) {} 145 ValueViewValueView146 constexpr ValueView(ValueView&& other) : ptr_(other.ptr_) { other.ptr_.ptr_ = nullptr; } 147 148 constexpr ValueView& operator=(ValueView&& other) { 149 ptr_ = other.ptr_; 150 other.ptr_ = InputValueIter<T>(nullptr); 151 return *this; 152 } 153 154 ValueView(const ValueView&) = delete; 155 ValueView& operator=(const ValueView&) = delete; 156 beginValueView157 constexpr InputValueIter<T> begin() const { return ptr_; } endValueView158 constexpr sentinel end() const { return sentinel(InputValueIter<T>(ptr_.ptr_ + 4)); } 159 }; 160 161 template <class Iter, class Sent = Iter, class NonConstIter = Iter, class NonConstSent = Sent> 162 struct BufferView : std::ranges::view_base { 163 164 using T = std::iter_value_t<Iter>; 165 T* data_; 166 std::size_t size_; 167 168 template <std::size_t N> BufferViewBufferView169 constexpr BufferView(T (&b)[N]) : data_(b), size_(N) {} BufferViewBufferView170 constexpr BufferView(T* p, std::size_t s) : data_(p), size_(s) {} 171 beginBufferView172 constexpr NonConstIter begin() 173 requires(!std::is_same_v<Iter, NonConstIter>) { 174 return NonConstIter(this->data_); 175 } beginBufferView176 constexpr Iter begin() const { return Iter(this->data_); } 177 endBufferView178 constexpr NonConstSent end() 179 requires(!std::is_same_v<Sent, NonConstSent>) { 180 if constexpr (std::is_same_v<NonConstIter, NonConstSent>) { 181 return NonConstIter(this->data_ + this->size_); 182 } else { 183 return NonConstSent(NonConstIter(this->data_ + this->size_)); 184 } 185 } 186 endBufferView187 constexpr Sent end() const { 188 if constexpr (std::is_same_v<Iter, Sent>) { 189 return Iter(this->data_ + this->size_); 190 } else { 191 return Sent(Iter(this->data_ + this->size_)); 192 } 193 } 194 }; 195 196 // an `input_iterator` that can be used in a `common_range` 197 template <class Base> 198 struct common_input_iterator { 199 Base it_; 200 201 using value_type = std::iter_value_t<Base>; 202 using difference_type = std::intptr_t; 203 using iterator_concept = std::input_iterator_tag; 204 205 constexpr common_input_iterator() = default; common_input_iteratorcommon_input_iterator206 constexpr explicit common_input_iterator(Base it) : it_(it) {} 207 208 constexpr common_input_iterator& operator++() { 209 ++it_; 210 return *this; 211 } 212 constexpr void operator++(int) { ++it_; } 213 214 constexpr std::iter_reference_t<Base> operator*() const { return *it_; } 215 216 friend constexpr bool operator==(common_input_iterator const&, common_input_iterator const&) = default; 217 }; 218 219 using InputCommonInner = BufferView<common_input_iterator<int*>>; 220 static_assert(std::ranges::input_range<InputCommonInner>); 221 static_assert(!std::ranges::forward_range<InputCommonInner>); 222 static_assert(std::ranges::common_range<InputCommonInner>); 223 224 using InputNonCommonInner = BufferView<common_input_iterator<int*>, sentinel_wrapper<common_input_iterator<int*>>>; 225 static_assert(std::ranges::input_range<InputNonCommonInner>); 226 static_assert(!std::ranges::forward_range<InputNonCommonInner>); 227 static_assert(!std::ranges::common_range<InputNonCommonInner>); 228 229 using ForwardCommonInner = BufferView<forward_iterator<int*>>; 230 static_assert(std::ranges::forward_range<ForwardCommonInner>); 231 static_assert(!std::ranges::bidirectional_range<ForwardCommonInner>); 232 static_assert(std::ranges::common_range<ForwardCommonInner>); 233 234 using ForwardNonCommonInner = BufferView<forward_iterator<int*>, sentinel_wrapper<forward_iterator<int*>>>; 235 static_assert(std::ranges::forward_range<ForwardNonCommonInner>); 236 static_assert(!std::ranges::bidirectional_range<ForwardNonCommonInner>); 237 static_assert(!std::ranges::common_range<ForwardNonCommonInner>); 238 239 using BidiCommonInner = BufferView<bidirectional_iterator<int*>>; 240 static_assert(std::ranges::bidirectional_range<BidiCommonInner>); 241 static_assert(std::ranges::common_range<BidiCommonInner>); 242 243 using BidiNonCommonInner = BufferView<bidirectional_iterator<int*>, sentinel_wrapper<bidirectional_iterator<int*>>>; 244 static_assert(std::ranges::bidirectional_range<BidiNonCommonInner>); 245 static_assert(!std::ranges::common_range<BidiNonCommonInner>); 246 247 template <class Inner = BufferView<int*>> 248 using SimpleInputCommonOuter = BufferView<common_input_iterator<Inner*>>; 249 static_assert(!std::ranges::forward_range<SimpleInputCommonOuter<>>); 250 static_assert(!std::ranges::bidirectional_range<SimpleInputCommonOuter<>>); 251 static_assert(std::ranges::common_range<SimpleInputCommonOuter<>>); 252 LIBCPP_STATIC_ASSERT(std::ranges::__simple_view<SimpleInputCommonOuter<>>); 253 254 template <class Inner = BufferView<int*>> 255 using NonSimpleInputCommonOuter = BufferView<common_input_iterator<const Inner*>, common_input_iterator<const Inner*>, 256 common_input_iterator< Inner*>, common_input_iterator< Inner*>>; 257 static_assert(!std::ranges::forward_range<NonSimpleInputCommonOuter<>>); 258 static_assert(!std::ranges::bidirectional_range<NonSimpleInputCommonOuter<>>); 259 static_assert(std::ranges::common_range<NonSimpleInputCommonOuter<>>); 260 LIBCPP_STATIC_ASSERT(!std::ranges::__simple_view<NonSimpleInputCommonOuter<>>); 261 262 template <class Inner = BufferView<int*>> 263 using SimpleForwardCommonOuter = BufferView<forward_iterator<Inner*>>; 264 static_assert(std::ranges::forward_range<SimpleForwardCommonOuter<>>); 265 static_assert(!std::ranges::bidirectional_range<SimpleForwardCommonOuter<>>); 266 static_assert(std::ranges::common_range<SimpleForwardCommonOuter<>>); 267 LIBCPP_STATIC_ASSERT(std::ranges::__simple_view<SimpleForwardCommonOuter<>>); 268 269 template <class Inner = BufferView<int*>> 270 using NonSimpleForwardCommonOuter = BufferView<forward_iterator<const Inner*>, forward_iterator<const Inner*>, 271 forward_iterator<Inner*>, forward_iterator<Inner*>>; 272 static_assert(std::ranges::forward_range<NonSimpleForwardCommonOuter<>>); 273 static_assert(!std::ranges::bidirectional_range<NonSimpleForwardCommonOuter<>>); 274 static_assert(std::ranges::common_range<NonSimpleForwardCommonOuter<>>); 275 LIBCPP_STATIC_ASSERT(!std::ranges::__simple_view<NonSimpleForwardCommonOuter<>>); 276 277 template <class Inner = BufferView<int*>> 278 using SimpleForwardNonCommonOuter = BufferView<forward_iterator<Inner*>, sentinel_wrapper<forward_iterator<Inner*>>>; 279 static_assert(std::ranges::forward_range<SimpleForwardNonCommonOuter<>>); 280 static_assert(!std::ranges::bidirectional_range<SimpleForwardNonCommonOuter<>>); 281 static_assert(!std::ranges::common_range<SimpleForwardNonCommonOuter<>>); 282 LIBCPP_STATIC_ASSERT(std::ranges::__simple_view<SimpleForwardNonCommonOuter<>>); 283 284 template <class Inner = BufferView<int*>> 285 using NonSimpleForwardNonCommonOuter = 286 BufferView<forward_iterator<const Inner*>, sentinel_wrapper<forward_iterator<const Inner*>>, 287 forward_iterator<Inner*>, sentinel_wrapper<forward_iterator<Inner*>>>; 288 static_assert(std::ranges::forward_range<NonSimpleForwardNonCommonOuter<>>); 289 static_assert(!std::ranges::bidirectional_range<NonSimpleForwardNonCommonOuter<>>); 290 static_assert(!std::ranges::common_range<NonSimpleForwardNonCommonOuter<>>); 291 LIBCPP_STATIC_ASSERT(!std::ranges::__simple_view<NonSimpleForwardNonCommonOuter<>>); 292 293 template <class Inner = BufferView<int*>> 294 using BidiCommonOuter = BufferView<bidirectional_iterator<Inner*>>; 295 static_assert(std::ranges::bidirectional_range<BidiCommonOuter<>>); 296 static_assert(std::ranges::common_range<BidiCommonOuter<>>); 297 LIBCPP_STATIC_ASSERT(std::ranges::__simple_view<BidiCommonOuter<>>); 298 299 // an iterator where its operator* makes a copy of underlying operator* 300 template <class It> 301 struct copying_iterator { 302 It it_ = It(); 303 304 using value_type = typename std::iterator_traits<It>::value_type; 305 using difference_type = typename std::iterator_traits<It>::difference_type; 306 using pointer = typename std::iterator_traits<It>::pointer; 307 308 copying_iterator() requires std::default_initializable<It> = default; copying_iteratorcopying_iterator309 constexpr copying_iterator(It it) : it_(std::move(it)) {} 310 311 // makes a copy of underlying operator* to create a PRValue 312 constexpr value_type operator*() const { return *it_; } 313 314 constexpr copying_iterator& operator++() { 315 ++it_; 316 return *this; 317 } 318 constexpr copying_iterator& operator--() 319 requires std::bidirectional_iterator<It> { 320 --it_; 321 return *this; 322 } 323 constexpr copying_iterator operator++(int) 324 requires std::forward_iterator<It> { 325 return copying_iterator(it_++); 326 } 327 constexpr void operator++(int) { return it_++; } 328 constexpr copying_iterator operator--(int) 329 requires std::bidirectional_iterator<It> { 330 return copying_iterator(it_--); 331 } 332 333 friend constexpr bool operator==(const copying_iterator& x, const copying_iterator& y) = default; 334 }; 335 336 template <class Outer> 337 struct InnerRValue : Outer { 338 339 using iterator = copying_iterator<std::ranges::iterator_t<Outer>>; 340 using const_iterator = copying_iterator<std::ranges::iterator_t<const Outer>>; 341 using sentinel = copying_iterator<std::ranges::sentinel_t<Outer>>; 342 using const_sentinel = copying_iterator<std::ranges::sentinel_t<const Outer>>; 343 344 using Outer::Outer; 345 static_assert(std::ranges::common_range<Outer>, "non-common range is not supported yet"); 346 beginInnerRValue347 constexpr iterator begin() { return Outer::begin(); } beginInnerRValue348 constexpr const_iterator begin() const 349 requires std::ranges::range<const Outer> { 350 return Outer::begin(); 351 } 352 endInnerRValue353 constexpr auto end() { return iterator{Outer::end()}; } endInnerRValue354 constexpr auto end() const 355 requires std::ranges::range<const Outer> { 356 return const_iterator{Outer::end()}; 357 } 358 }; 359 static_assert(std::ranges::forward_range<InnerRValue<SimpleForwardCommonOuter<>>>); 360 static_assert(!std::ranges::bidirectional_range<InnerRValue<SimpleForwardCommonOuter<>>>); 361 static_assert(std::ranges::common_range<InnerRValue<SimpleForwardCommonOuter<>>>); 362 LIBCPP_STATIC_ASSERT(std::ranges::__simple_view<InnerRValue<SimpleForwardCommonOuter<>>>); 363 static_assert(!std::is_lvalue_reference_v<std::ranges::range_reference_t<InnerRValue<SimpleForwardCommonOuter<>>>>); 364 365 struct move_swap_aware_iter { 366 367 // This is a proxy-like iterator where `reference` is a prvalue, and 368 // `reference` and `value_type` are distinct types (similar to `zip_view::iterator`). 369 using value_type = std::pair<int, int>; 370 using reference = std::pair<int&, int&>; 371 using rvalue_reference = std::pair<int&&, int&&>; 372 373 using difference_type = std::intptr_t; 374 using iterator_concept = std::input_iterator_tag; 375 376 int* iter_move_called = nullptr; 377 int* iter_swap_called = nullptr; 378 int* i_ = nullptr; 379 380 constexpr move_swap_aware_iter& operator++() { 381 ++i_; 382 return *this; 383 } 384 constexpr void operator++(int) { ++i_; } 385 386 constexpr reference operator*() const { return reference(*i_, *i_); } 387 constexpr friend bool operator==(const move_swap_aware_iter& x, const move_swap_aware_iter& y) { 388 return x.i_ == y.i_; 389 } 390 iter_movemove_swap_aware_iter391 constexpr friend rvalue_reference iter_move(const move_swap_aware_iter& x) noexcept { 392 ++(*x.iter_move_called); 393 return rvalue_reference{std::move(*x.i_), std::move(*x.i_)}; 394 } 395 iter_swapmove_swap_aware_iter396 constexpr friend void iter_swap(const move_swap_aware_iter& x, const move_swap_aware_iter& y) noexcept { 397 ++(*x.iter_swap_called); 398 std::swap(*x.i_, *y.i_); 399 } 400 }; 401 402 struct IterMoveSwapAwareView : BufferView<int*> { 403 int iter_move_called = 0; 404 int iter_swap_called = 0; 405 using BufferView<int*>::BufferView; 406 beginIterMoveSwapAwareView407 constexpr auto begin() { return move_swap_aware_iter{&iter_move_called, &iter_swap_called, data_}; } 408 endIterMoveSwapAwareView409 constexpr auto end() { return move_swap_aware_iter{&iter_move_called, &iter_swap_called, data_ + size_}; } 410 }; 411 static_assert(std::ranges::input_range<IterMoveSwapAwareView>); 412 413 #endif // TEST_STD_RANGES_RANGE_ADAPTORS_RANGE_JOIN_TYPES_H 414