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