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