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