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