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_LAZY_SPLIT_TYPES_H 10 #define TEST_STD_RANGES_RANGE_ADAPTORS_RANGE_LAZY_SPLIT_TYPES_H 11 12 #include <concepts> 13 #include <ranges> 14 #include <string> 15 #include <string_view> 16 #include <type_traits> 17 #include "test_macros.h" 18 #include "test_iterators.h" 19 20 // CopyableView 21 22 struct CopyableView : std::ranges::view_base { 23 std::string_view view_; 24 constexpr explicit CopyableView() = default; CopyableViewCopyableView25 constexpr CopyableView(const char* ptr) : view_(ptr) {} CopyableViewCopyableView26 constexpr CopyableView(std::string_view v) : view_(v) {} beginCopyableView27 constexpr forward_iterator<const char*> begin() const { return forward_iterator<const char*>(view_.begin()); } endCopyableView28 constexpr forward_iterator<const char*> end() const { return forward_iterator<const char*>(view_.end()); } 29 constexpr bool operator==(const CopyableView& rhs) const { return view_ == rhs.view_; } 30 }; 31 static_assert( std::ranges::forward_range<CopyableView>); 32 static_assert( std::ranges::forward_range<const CopyableView>); 33 static_assert( std::ranges::view<CopyableView>); 34 static_assert( std::is_copy_constructible_v<CopyableView>); 35 36 // ForwardView 37 38 struct ForwardView : std::ranges::view_base { 39 std::string_view view_; 40 constexpr explicit ForwardView() = default; ForwardViewForwardView41 constexpr ForwardView(const char* ptr) : view_(ptr) {} ForwardViewForwardView42 constexpr ForwardView(std::string_view v) : view_(v) {} 43 constexpr ForwardView(ForwardView&&) = default; 44 constexpr ForwardView& operator=(ForwardView&&) = default; beginForwardView45 constexpr forward_iterator<const char*> begin() const { return forward_iterator<const char*>(view_.begin()); } endForwardView46 constexpr forward_iterator<const char*> end() const { return forward_iterator<const char*>(view_.end()); } 47 }; 48 static_assert( std::ranges::forward_range<ForwardView>); 49 static_assert( std::ranges::forward_range<const ForwardView>); 50 static_assert( std::ranges::view<ForwardView>); 51 static_assert(!std::is_copy_constructible_v<ForwardView>); 52 static_assert( std::is_move_constructible_v<ForwardView>); 53 54 // ForwardDiffView 55 56 // Iterator types differ based on constness of this class. 57 struct ForwardDiffView : std::ranges::view_base { 58 std::string buffer_; 59 constexpr explicit ForwardDiffView() = default; ForwardDiffViewForwardDiffView60 constexpr ForwardDiffView(const char* ptr) : ForwardDiffView(std::string_view(ptr)) {} ForwardDiffViewForwardDiffView61 constexpr ForwardDiffView(std::string_view v) { 62 // Workaround https://github.com/llvm/llvm-project/issues/55867 63 buffer_ = v; 64 } 65 constexpr ForwardDiffView(ForwardDiffView&&) = default; 66 constexpr ForwardDiffView& operator=(ForwardDiffView&&) = default; 67 constexpr ForwardDiffView(const ForwardDiffView&) = default; 68 constexpr ForwardDiffView& operator=(const ForwardDiffView&) = default; beginForwardDiffView69 constexpr forward_iterator<char*> begin() { return forward_iterator<char*>(buffer_.begin().base()); } endForwardDiffView70 constexpr forward_iterator<char*> end() { return forward_iterator<char*>(buffer_.end().base()); } beginForwardDiffView71 constexpr forward_iterator<const char*> begin() const { return forward_iterator<const char*>(buffer_.begin().base()); } endForwardDiffView72 constexpr forward_iterator<const char*> end() const { return forward_iterator<const char*>(buffer_.end().base()); } 73 }; 74 static_assert( std::ranges::forward_range<ForwardView>); 75 static_assert( std::ranges::forward_range<const ForwardView>); 76 static_assert( std::ranges::view<ForwardView>); 77 static_assert(!std::same_as<std::ranges::iterator_t<ForwardDiffView>, std::ranges::iterator_t<const ForwardDiffView>>); 78 79 // ForwardOnlyIfNonConstView 80 81 template <class It> 82 class almost_forward_iterator { 83 It it_; 84 85 template <class U> friend class almost_forward_iterator; 86 87 public: 88 using iterator_category = std::forward_iterator_tag; 89 using value_type = typename std::iterator_traits<It>::value_type; 90 using difference_type = typename std::iterator_traits<It>::difference_type; 91 using pointer = It; 92 using reference = typename std::iterator_traits<It>::reference; 93 almost_forward_iterator()94 constexpr almost_forward_iterator() : it_() {} almost_forward_iterator(It it)95 constexpr explicit almost_forward_iterator(It it) : it_(it) {} 96 template <class U> almost_forward_iterator(const almost_forward_iterator<U> & u)97 constexpr almost_forward_iterator(const almost_forward_iterator<U>& u) : it_(u.it_) {} 98 99 constexpr reference operator*() const { return *it_; } 100 constexpr pointer operator->() const { return it_; } 101 102 constexpr almost_forward_iterator& operator++() { ++it_; return *this; } 103 // Notice the slightly different return type. 104 constexpr const almost_forward_iterator operator++(int) { return almost_forward_iterator(it_); } 105 106 friend constexpr bool operator==(const almost_forward_iterator& x, const almost_forward_iterator& y) { 107 return x.it_ == y.it_; 108 } 109 friend constexpr bool operator!=(const almost_forward_iterator& x, const almost_forward_iterator& y) { 110 return x.it_ != y.it_; 111 } 112 }; 113 static_assert(!std::forward_iterator<almost_forward_iterator<int*>>); 114 static_assert( std::input_iterator<almost_forward_iterator<int*>>); 115 116 struct ForwardOnlyIfNonConstView : std::ranges::view_base { 117 std::string_view view_; 118 119 constexpr explicit ForwardOnlyIfNonConstView() = default; ForwardOnlyIfNonConstViewForwardOnlyIfNonConstView120 constexpr ForwardOnlyIfNonConstView(const char* ptr) : view_(ptr) {} ForwardOnlyIfNonConstViewForwardOnlyIfNonConstView121 constexpr ForwardOnlyIfNonConstView(std::string_view v) : view_(v) {} 122 constexpr ForwardOnlyIfNonConstView(ForwardOnlyIfNonConstView&&) = default; 123 constexpr ForwardOnlyIfNonConstView& operator=(ForwardOnlyIfNonConstView&&) = default; 124 beginForwardOnlyIfNonConstView125 constexpr forward_iterator<const char*> begin() { return forward_iterator<const char*>(view_.begin()); } endForwardOnlyIfNonConstView126 constexpr forward_iterator<const char*> end() { return forward_iterator<const char*>(view_.end()); } beginForwardOnlyIfNonConstView127 constexpr almost_forward_iterator<const char*> begin() const { 128 return almost_forward_iterator<const char*>(view_.begin()); 129 } endForwardOnlyIfNonConstView130 constexpr almost_forward_iterator<const char*> end() const { 131 return almost_forward_iterator<const char*>(view_.end()); 132 } 133 }; 134 static_assert( std::ranges::forward_range<ForwardOnlyIfNonConstView>); 135 static_assert(!std::ranges::forward_range<const ForwardOnlyIfNonConstView>); 136 static_assert( std::ranges::view<ForwardOnlyIfNonConstView>); 137 138 // InputView 139 140 struct InputView : std::ranges::view_base { 141 std::string buffer_; 142 143 constexpr InputView() = default; InputViewInputView144 constexpr InputView(const char* s) : InputView(std::string_view(s)) {} InputViewInputView145 constexpr InputView(std::string_view v) { 146 // Workaround https://github.com/llvm/llvm-project/issues/55867 147 buffer_ = v; 148 } 149 beginInputView150 constexpr cpp20_input_iterator<char*> begin() { return cpp20_input_iterator<char*>(buffer_.begin().base()); } endInputView151 constexpr sentinel_wrapper<cpp20_input_iterator<char*>> end() { 152 return sentinel_wrapper(cpp20_input_iterator<char*>(buffer_.end().base())); 153 } beginInputView154 constexpr cpp20_input_iterator<const char*> begin() const { 155 return cpp20_input_iterator<const char*>(buffer_.begin().base()); 156 } endInputView157 constexpr sentinel_wrapper<cpp20_input_iterator<const char*>> end() const { 158 return sentinel_wrapper(cpp20_input_iterator<const char*>(buffer_.end().base())); 159 } 160 friend constexpr bool operator==(const InputView& lhs, const InputView& rhs) { 161 return lhs.buffer_ == rhs.buffer_; 162 } 163 }; 164 165 static_assert(std::ranges::input_range<InputView>); 166 static_assert(std::ranges::input_range<const InputView>); 167 static_assert(std::ranges::view<InputView>); 168 169 // ForwardTinyView 170 171 struct ForwardTinyView : std::ranges::view_base { 172 char c_[1] = {}; 173 constexpr ForwardTinyView() = default; ForwardTinyViewForwardTinyView174 constexpr ForwardTinyView(char c) { *c_ = c; } beginForwardTinyView175 constexpr forward_iterator<const char*> begin() const { return forward_iterator<const char*>(c_); } endForwardTinyView176 constexpr forward_iterator<const char*> end() const { return forward_iterator<const char*>(c_ + 1); } sizeForwardTinyView177 constexpr static size_t size() { return 1; } 178 }; 179 static_assert(std::ranges::forward_range<ForwardTinyView>); 180 static_assert(std::ranges::view<ForwardTinyView>); 181 LIBCPP_STATIC_ASSERT(std::ranges::__tiny_range<ForwardTinyView>); 182 183 // Aliases 184 185 using SplitViewCopyable = std::ranges::lazy_split_view<CopyableView, CopyableView>; 186 using OuterIterCopyable = std::ranges::iterator_t<SplitViewCopyable>; 187 using ValueTypeCopyable = OuterIterCopyable::value_type; 188 using InnerIterCopyable = std::ranges::iterator_t<ValueTypeCopyable>; 189 using BaseIterCopyable = std::ranges::iterator_t<CopyableView>; 190 191 using SplitViewForward = std::ranges::lazy_split_view<ForwardView, ForwardView>; 192 using OuterIterForward = std::ranges::iterator_t<SplitViewForward>; 193 using ValueTypeForward = OuterIterForward::value_type; 194 using InnerIterForward = std::ranges::iterator_t<ValueTypeForward>; 195 using BaseIterForward = std::ranges::iterator_t<ForwardView>; 196 197 using SplitViewInput = std::ranges::lazy_split_view<InputView, ForwardTinyView>; 198 using OuterIterInput = std::ranges::iterator_t<SplitViewInput>; 199 using ValueTypeInput = OuterIterInput::value_type; 200 using InnerIterInput = std::ranges::iterator_t<ValueTypeInput>; 201 using BaseIterInput = std::ranges::iterator_t<InputView>; 202 203 using SplitViewDiff = std::ranges::lazy_split_view<ForwardDiffView, ForwardDiffView>; 204 using OuterIterConst = decltype(std::declval<const SplitViewDiff>().begin()); 205 using OuterIterNonConst = decltype(std::declval<SplitViewDiff>().begin()); 206 static_assert(!std::same_as<OuterIterConst, OuterIterNonConst>); 207 using InnerIterConst = decltype((*std::declval<OuterIterConst>()).begin()); 208 using InnerIterNonConst = decltype((*std::declval<OuterIterNonConst>()).begin()); 209 static_assert(!std::same_as<InnerIterConst, InnerIterNonConst>); 210 211 #endif // TEST_STD_RANGES_RANGE_ADAPTORS_RANGE_LAZY_SPLIT_TYPES_H 212