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 <cstddef> 14 #include <ranges> 15 #include <string> 16 #include <string_view> 17 #include <type_traits> 18 #include "test_macros.h" 19 #include "test_iterators.h" 20 21 // CopyableView 22 23 struct CopyableView : std::ranges::view_base { 24 std::string_view view_; 25 constexpr explicit CopyableView() = default; CopyableViewCopyableView26 constexpr CopyableView(const char* ptr) : view_(ptr) {} CopyableViewCopyableView27 constexpr CopyableView(std::string_view v) : view_(v) {} beginCopyableView28 constexpr forward_iterator<std::string_view::const_iterator> begin() const { return forward_iterator<std::string_view::const_iterator>(view_.begin()); } endCopyableView29 constexpr forward_iterator<std::string_view::const_iterator> end() const { return forward_iterator<std::string_view::const_iterator>(view_.end()); } 30 constexpr bool operator==(const CopyableView& rhs) const { return view_ == rhs.view_; } 31 }; 32 static_assert( std::ranges::forward_range<CopyableView>); 33 static_assert( std::ranges::forward_range<const CopyableView>); 34 static_assert( std::ranges::view<CopyableView>); 35 static_assert( std::is_copy_constructible_v<CopyableView>); 36 37 // ForwardView 38 39 struct ForwardView : std::ranges::view_base { 40 std::string_view view_; 41 constexpr explicit ForwardView() = default; ForwardViewForwardView42 constexpr ForwardView(const char* ptr) : view_(ptr) {} ForwardViewForwardView43 constexpr ForwardView(std::string_view v) : view_(v) {} 44 constexpr ForwardView(ForwardView&&) = default; 45 constexpr ForwardView& operator=(ForwardView&&) = default; beginForwardView46 constexpr forward_iterator<std::string_view::const_iterator> begin() const { return forward_iterator<std::string_view::const_iterator>(view_.begin()); } endForwardView47 constexpr forward_iterator<std::string_view::const_iterator> end() const { return forward_iterator<std::string_view::const_iterator>(view_.end()); } 48 }; 49 static_assert( std::ranges::forward_range<ForwardView>); 50 static_assert( std::ranges::forward_range<const ForwardView>); 51 static_assert( std::ranges::view<ForwardView>); 52 static_assert(!std::is_copy_constructible_v<ForwardView>); 53 static_assert( std::is_move_constructible_v<ForwardView>); 54 55 // ForwardDiffView 56 57 // Iterator types differ based on constness of this class. 58 struct ForwardDiffView : std::ranges::view_base { 59 std::string buffer_; 60 constexpr explicit ForwardDiffView() = default; ForwardDiffViewForwardDiffView61 constexpr ForwardDiffView(const char* ptr) : ForwardDiffView(std::string_view(ptr)) {} ForwardDiffViewForwardDiffView62 constexpr ForwardDiffView(std::string_view v) { 63 // Workaround https://github.com/llvm/llvm-project/issues/55867 64 buffer_ = v; 65 } 66 constexpr ForwardDiffView(ForwardDiffView&&) = default; 67 constexpr ForwardDiffView& operator=(ForwardDiffView&&) = default; 68 constexpr ForwardDiffView(const ForwardDiffView&) = default; 69 constexpr ForwardDiffView& operator=(const ForwardDiffView&) = default; beginForwardDiffView70 constexpr forward_iterator<char*> begin() { return forward_iterator<char*>(buffer_.data()); } endForwardDiffView71 constexpr forward_iterator<char*> end() { return forward_iterator<char*>(buffer_.data() + buffer_.size()); } beginForwardDiffView72 constexpr forward_iterator<const char*> begin() const { return forward_iterator<const char*>(buffer_.data()); } endForwardDiffView73 constexpr forward_iterator<const char*> end() const { return forward_iterator<const char*>(buffer_.data() + buffer_.size()); } 74 }; 75 static_assert( std::ranges::forward_range<ForwardView>); 76 static_assert( std::ranges::forward_range<const ForwardView>); 77 static_assert( std::ranges::view<ForwardView>); 78 static_assert(!std::same_as<std::ranges::iterator_t<ForwardDiffView>, std::ranges::iterator_t<const ForwardDiffView>>); 79 80 // ForwardOnlyIfNonConstView 81 82 template <class It> 83 class almost_forward_iterator { 84 It it_; 85 86 template <class U> friend class almost_forward_iterator; 87 88 public: 89 using iterator_category = std::forward_iterator_tag; 90 using value_type = typename std::iterator_traits<It>::value_type; 91 using difference_type = typename std::iterator_traits<It>::difference_type; 92 using pointer = It; 93 using reference = typename std::iterator_traits<It>::reference; 94 almost_forward_iterator()95 constexpr almost_forward_iterator() : it_() {} almost_forward_iterator(It it)96 constexpr explicit almost_forward_iterator(It it) : it_(it) {} 97 template <class U> almost_forward_iterator(const almost_forward_iterator<U> & u)98 constexpr almost_forward_iterator(const almost_forward_iterator<U>& u) : it_(u.it_) {} 99 100 constexpr reference operator*() const { return *it_; } 101 constexpr pointer operator->() const { return it_; } 102 103 constexpr almost_forward_iterator& operator++() { ++it_; return *this; } 104 // Notice the slightly different return type. 105 constexpr const almost_forward_iterator operator++(int) { return almost_forward_iterator(it_); } 106 107 friend constexpr bool operator==(const almost_forward_iterator& x, const almost_forward_iterator& y) { 108 return x.it_ == y.it_; 109 } 110 friend constexpr bool operator!=(const almost_forward_iterator& x, const almost_forward_iterator& y) { 111 return x.it_ != y.it_; 112 } 113 }; 114 static_assert(!std::forward_iterator<almost_forward_iterator<int*>>); 115 static_assert( std::input_iterator<almost_forward_iterator<int*>>); 116 117 struct ForwardOnlyIfNonConstView : std::ranges::view_base { 118 std::string_view view_; 119 120 constexpr explicit ForwardOnlyIfNonConstView() = default; ForwardOnlyIfNonConstViewForwardOnlyIfNonConstView121 constexpr ForwardOnlyIfNonConstView(const char* ptr) : view_(ptr) {} ForwardOnlyIfNonConstViewForwardOnlyIfNonConstView122 constexpr ForwardOnlyIfNonConstView(std::string_view v) : view_(v) {} 123 constexpr ForwardOnlyIfNonConstView(ForwardOnlyIfNonConstView&&) = default; 124 constexpr ForwardOnlyIfNonConstView& operator=(ForwardOnlyIfNonConstView&&) = default; 125 beginForwardOnlyIfNonConstView126 constexpr forward_iterator<std::string_view::const_iterator> begin() { return forward_iterator<std::string_view::const_iterator>(view_.begin()); } endForwardOnlyIfNonConstView127 constexpr forward_iterator<std::string_view::const_iterator> end() { return forward_iterator<std::string_view::const_iterator>(view_.end()); } beginForwardOnlyIfNonConstView128 constexpr almost_forward_iterator<std::string_view::const_iterator> begin() const { 129 return almost_forward_iterator<std::string_view::const_iterator>(view_.begin()); 130 } endForwardOnlyIfNonConstView131 constexpr almost_forward_iterator<std::string_view::const_iterator> end() const { 132 return almost_forward_iterator<std::string_view::const_iterator>(view_.end()); 133 } 134 }; 135 static_assert( std::ranges::forward_range<ForwardOnlyIfNonConstView>); 136 static_assert(!std::ranges::forward_range<const ForwardOnlyIfNonConstView>); 137 static_assert( std::ranges::view<ForwardOnlyIfNonConstView>); 138 139 // InputView 140 141 struct InputView : std::ranges::view_base { 142 std::string buffer_; 143 144 constexpr InputView() = default; InputViewInputView145 constexpr InputView(const char* s) : InputView(std::string_view(s)) {} InputViewInputView146 constexpr InputView(std::string_view v) { 147 // Workaround https://github.com/llvm/llvm-project/issues/55867 148 buffer_ = v; 149 } 150 beginInputView151 constexpr cpp20_input_iterator<char*> begin() { return cpp20_input_iterator<char*>(buffer_.data()); } endInputView152 constexpr sentinel_wrapper<cpp20_input_iterator<char*>> end() { 153 return sentinel_wrapper(cpp20_input_iterator<char*>(buffer_.data() + buffer_.size())); 154 } beginInputView155 constexpr cpp20_input_iterator<const char*> begin() const { 156 return cpp20_input_iterator<const char*>(buffer_.data()); 157 } endInputView158 constexpr sentinel_wrapper<cpp20_input_iterator<const char*>> end() const { 159 return sentinel_wrapper(cpp20_input_iterator<const char*>(buffer_.data() + buffer_.size())); 160 } 161 friend constexpr bool operator==(const InputView& lhs, const InputView& rhs) { 162 return lhs.buffer_ == rhs.buffer_; 163 } 164 }; 165 166 static_assert(std::ranges::input_range<InputView>); 167 static_assert(std::ranges::input_range<const InputView>); 168 static_assert(std::ranges::view<InputView>); 169 170 // ForwardTinyView 171 172 struct ForwardTinyView : std::ranges::view_base { 173 char c_[1] = {}; 174 constexpr ForwardTinyView() = default; ForwardTinyViewForwardTinyView175 constexpr ForwardTinyView(char c) { *c_ = c; } beginForwardTinyView176 constexpr forward_iterator<const char*> begin() const { return forward_iterator<const char*>(c_); } endForwardTinyView177 constexpr forward_iterator<const char*> end() const { return forward_iterator<const char*>(c_ + 1); } sizeForwardTinyView178 constexpr static std::size_t size() { return 1; } 179 }; 180 static_assert(std::ranges::forward_range<ForwardTinyView>); 181 static_assert(std::ranges::view<ForwardTinyView>); 182 LIBCPP_STATIC_ASSERT(std::ranges::__tiny_range<ForwardTinyView>); 183 184 // Aliases 185 186 using SplitViewCopyable = std::ranges::lazy_split_view<CopyableView, CopyableView>; 187 using OuterIterCopyable = std::ranges::iterator_t<SplitViewCopyable>; 188 using ValueTypeCopyable = OuterIterCopyable::value_type; 189 using InnerIterCopyable = std::ranges::iterator_t<ValueTypeCopyable>; 190 using BaseIterCopyable = std::ranges::iterator_t<CopyableView>; 191 192 using SplitViewForward = std::ranges::lazy_split_view<ForwardView, ForwardView>; 193 using OuterIterForward = std::ranges::iterator_t<SplitViewForward>; 194 using ValueTypeForward = OuterIterForward::value_type; 195 using InnerIterForward = std::ranges::iterator_t<ValueTypeForward>; 196 using BaseIterForward = std::ranges::iterator_t<ForwardView>; 197 198 using SplitViewInput = std::ranges::lazy_split_view<InputView, ForwardTinyView>; 199 using OuterIterInput = std::ranges::iterator_t<SplitViewInput>; 200 using ValueTypeInput = OuterIterInput::value_type; 201 using InnerIterInput = std::ranges::iterator_t<ValueTypeInput>; 202 using BaseIterInput = std::ranges::iterator_t<InputView>; 203 204 using SplitViewDiff = std::ranges::lazy_split_view<ForwardDiffView, ForwardDiffView>; 205 using OuterIterConst = decltype(std::declval<const SplitViewDiff>().begin()); 206 using OuterIterNonConst = decltype(std::declval<SplitViewDiff>().begin()); 207 static_assert(!std::same_as<OuterIterConst, OuterIterNonConst>); 208 using InnerIterConst = decltype((*std::declval<OuterIterConst>()).begin()); 209 using InnerIterNonConst = decltype((*std::declval<OuterIterNonConst>()).begin()); 210 static_assert(!std::same_as<InnerIterConst, InnerIterNonConst>); 211 212 #endif // TEST_STD_RANGES_RANGE_ADAPTORS_RANGE_LAZY_SPLIT_TYPES_H 213