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