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