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 // UNSUPPORTED: c++03, c++11, c++14, c++17
10 // UNSUPPORTED: libcpp-has-no-incomplete-ranges
11 
12 // template<input_range V, forward_range Pattern>
13 //   requires view<V> && view<Pattern> &&
14 //            indirectly_comparable<iterator_t<V>, iterator_t<Pattern>, ranges::equal_to> &&
15 //            (forward_range<V> || tiny-range<Pattern>)
16 // class lazy_split_view;
17 
18 #include <ranges>
19 
20 #include "test_iterators.h"
21 #include "types.h"
22 
23 struct ForwardRange {
24   forward_iterator<int*> begin() const;
25   forward_iterator<int*> end() const;
26 };
27 static_assert( std::ranges::forward_range<ForwardRange>);
28 
29 template <class View, class Pattern>
30 concept CanInstantiate = requires {
31   typename std::ranges::lazy_split_view<View, Pattern>;
32 };
33 
34 // All constraints satisfied (`View` and `Pattern` are forward views).
35 namespace test1 {
36 
37   using View = ForwardView;
38   using Pattern = ForwardView;
39   static_assert( std::ranges::forward_range<View>);
40   static_assert( std::ranges::forward_range<Pattern>);
41   static_assert( std::ranges::view<View>);
42   static_assert( std::ranges::view<Pattern>);
43   static_assert( std::indirectly_comparable<
44       std::ranges::iterator_t<View>, std::ranges::iterator_t<Pattern>, std::ranges::equal_to>);
45   static_assert( CanInstantiate<View, Pattern>);
46 
47 } // namespace test1
48 
49 // All constraints satisfied (`View` is an input view and `Pattern` is a tiny view).
50 namespace test2 {
51 
52   using View = InputView;
53   using Pattern = ForwardTinyView;
54   static_assert( std::ranges::input_range<View>);
55   static_assert( std::ranges::forward_range<Pattern>);
56   static_assert( std::ranges::view<View>);
57   static_assert( std::ranges::view<Pattern>);
58   static_assert( std::indirectly_comparable<
59       std::ranges::iterator_t<View>, std::ranges::iterator_t<Pattern>, std::ranges::equal_to>);
60   static_assert( CanInstantiate<View, Pattern>);
61 
62 } // namespace test2
63 
64 // `View` is not an input range.
65 namespace test3 {
66 
67   struct AlmostInputIterator {
68     using value_type = char;
69     using difference_type = ptrdiff_t;
70     using iterator_concept = int;
71 
72     constexpr const char& operator*() const;
73     constexpr AlmostInputIterator& operator++();
74     constexpr void operator++(int);
75     constexpr bool operator==(const AlmostInputIterator&) const;
76   };
77 
78   static_assert( std::input_or_output_iterator<AlmostInputIterator>);
79   static_assert(!std::input_iterator<AlmostInputIterator>);
80 
81   struct NonInputView : std::ranges::view_base {
82     AlmostInputIterator begin() const;
83     AlmostInputIterator end() const;
84   };
85 
86   using View = NonInputView;
87   using Pattern = ForwardTinyView;
88   static_assert(!std::ranges::input_range<View>);
89   static_assert( std::ranges::forward_range<Pattern>);
90   static_assert( std::ranges::view<View>);
91   static_assert( std::ranges::view<Pattern>);
92   static_assert( std::indirectly_comparable<
93       std::ranges::iterator_t<View>, std::ranges::iterator_t<Pattern>, std::ranges::equal_to>);
94   static_assert(!CanInstantiate<View, Pattern>);
95 
96 } // namespace test3
97 
98 // `View` is not a view.
99 namespace test4 {
100 
101   using View = ForwardRange;
102   using Pattern = ForwardView;
103   static_assert( std::ranges::input_range<View>);
104   static_assert( std::ranges::forward_range<Pattern>);
105   static_assert(!std::ranges::view<View>);
106   static_assert( std::ranges::view<Pattern>);
107   static_assert( std::indirectly_comparable<
108       std::ranges::iterator_t<View>, std::ranges::iterator_t<Pattern>, std::ranges::equal_to>);
109   static_assert(!CanInstantiate<View, Pattern>);
110 
111 } // namespace test4
112 
113 // `Pattern` is not a forward range.
114 namespace test5 {
115 
116   using View = ForwardView;
117   using Pattern = InputView;
118   static_assert( std::ranges::input_range<View>);
119   static_assert(!std::ranges::forward_range<Pattern>);
120   static_assert( std::ranges::view<View>);
121   static_assert( std::ranges::view<Pattern>);
122   static_assert( std::indirectly_comparable<
123       std::ranges::iterator_t<View>, std::ranges::iterator_t<Pattern>, std::ranges::equal_to>);
124   static_assert(!CanInstantiate<View, Pattern>);
125 
126 } // namespace test5
127 
128 // Not indirectly comparable.
129 namespace test6 {
130 
131   struct Empty{};
132   struct IntForwardView : std::ranges::view_base {
133     constexpr forward_iterator<Empty*> begin() const { return {}; }
134     constexpr forward_iterator<Empty*> end() const { return {}; }
135   };
136 
137   using View = ForwardView;
138   using Pattern = IntForwardView;
139   static_assert( std::ranges::input_range<View>);
140   static_assert( std::ranges::forward_range<Pattern>);
141   static_assert( std::ranges::view<View>);
142   static_assert( std::ranges::view<Pattern>);
143   static_assert(!std::indirectly_comparable<
144       std::ranges::iterator_t<View>, std::ranges::iterator_t<Pattern>, std::ranges::equal_to>);
145   static_assert(!CanInstantiate<View, Pattern>);
146 
147 } // namespace test6
148 
149 // `View` is an input range and `Pattern` is not a tiny range.
150 namespace test7 {
151 
152   using View = InputView;
153   using Pattern = ForwardView;
154   static_assert( std::ranges::input_range<View>);
155   static_assert(!std::ranges::forward_range<View>);
156   static_assert( std::ranges::forward_range<Pattern>);
157   LIBCPP_STATIC_ASSERT(!std::ranges::__tiny_range<Pattern>);
158   static_assert( std::ranges::view<View>);
159   static_assert( std::ranges::view<Pattern>);
160   static_assert( std::indirectly_comparable<
161       std::ranges::iterator_t<View>, std::ranges::iterator_t<Pattern>, std::ranges::equal_to>);
162   static_assert(!CanInstantiate<View, Pattern>);
163 
164 } // namespace test7
165 
166 // `View` is an input range and `Pattern` is almost a tiny range, except the `size()` function is not `constexpr`.
167 namespace test8 {
168 
169   struct AlmostTinyRange : std::ranges::view_base {
170     int* begin() const;
171     int* end() const;
172     static size_t size() { return 1; }
173   };
174 
175   using View = InputView;
176   using Pattern = AlmostTinyRange;
177   static_assert( std::ranges::input_range<View>);
178   static_assert(!std::ranges::forward_range<View>);
179   static_assert( std::ranges::forward_range<Pattern>);
180   LIBCPP_STATIC_ASSERT(!std::ranges::__tiny_range<Pattern>);
181   static_assert( std::ranges::view<View>);
182   static_assert( std::ranges::view<Pattern>);
183   static_assert( std::indirectly_comparable<
184       std::ranges::iterator_t<View>, std::ranges::iterator_t<Pattern>, std::ranges::equal_to>);
185   static_assert(!CanInstantiate<View, Pattern>);
186 
187 } // namespace test8
188 
189 // `View` is an input range and `Pattern` is almost a tiny range, except the `size()` returns a number `>2`.
190 namespace test9 {
191 
192   struct AlmostTinyRange : std::ranges::view_base {
193     int* begin() const;
194     int* end() const;
195     constexpr static size_t size() { return 2; }
196   };
197 
198   using View = InputView;
199   using Pattern = ForwardView;
200   static_assert( std::ranges::input_range<View>);
201   static_assert(!std::ranges::forward_range<View>);
202   static_assert( std::ranges::forward_range<Pattern>);
203   LIBCPP_STATIC_ASSERT(!std::ranges::__tiny_range<Pattern>);
204   static_assert( std::ranges::view<View>);
205   static_assert( std::ranges::view<Pattern>);
206   static_assert( std::indirectly_comparable<
207       std::ranges::iterator_t<View>, std::ranges::iterator_t<Pattern>, std::ranges::equal_to>);
208   static_assert(!CanInstantiate<View, Pattern>);
209 
210 } // namespace test9
211