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 #ifndef ALMOST_SATISFIES_TYPES_H 10 #define ALMOST_SATISFIES_TYPES_H 11 12 #include <functional> 13 #include <iterator> 14 #include <ranges> 15 16 #include "test_iterators.h" 17 18 template <class T, class U = sentinel_wrapper<T>> 19 class UncheckedRange { 20 public: 21 T begin(); 22 U end(); 23 }; 24 25 static_assert(std::ranges::contiguous_range<UncheckedRange<int*, int*>>); 26 27 // almost an input_iterator 28 class InputIteratorNotDerivedFrom { 29 public: 30 using difference_type = long; 31 using value_type = int; 32 using iterator_category = void; 33 34 InputIteratorNotDerivedFrom& operator++(); 35 void operator++(int); 36 const int& operator*() const; 37 }; 38 39 using InputRangeNotDerivedFrom = UncheckedRange<InputIteratorNotDerivedFrom>; 40 41 static_assert(std::input_or_output_iterator<InputIteratorNotDerivedFrom>); 42 static_assert(std::indirectly_readable<InputIteratorNotDerivedFrom>); 43 static_assert(!std::input_iterator<InputIteratorNotDerivedFrom>); 44 static_assert(!std::ranges::input_range<InputRangeNotDerivedFrom>); 45 46 class InputIteratorNotIndirectlyReadable { 47 public: 48 using difference_type = long; 49 using iterator_category = std::input_iterator_tag; 50 51 InputIteratorNotIndirectlyReadable& operator++(); 52 void operator++(int); 53 const int& operator*() const; 54 }; 55 56 using InputRangeNotIndirectlyReadable = UncheckedRange<InputIteratorNotIndirectlyReadable>; 57 58 static_assert(std::input_or_output_iterator<InputIteratorNotIndirectlyReadable>); 59 static_assert(!std::indirectly_readable<InputIteratorNotIndirectlyReadable>); 60 static_assert(!std::input_iterator<InputIteratorNotIndirectlyReadable>); 61 static_assert(!std::ranges::input_range<InputIteratorNotIndirectlyReadable>); 62 63 class InputIteratorNotInputOrOutputIterator { 64 public: 65 using difference_type = long; 66 using value_type = int; 67 using iterator_category = std::input_iterator_tag; 68 69 int& operator++(); 70 void operator++(int); 71 const int& operator*() const; 72 }; 73 74 using InputRangeNotInputOrOutputIterator = UncheckedRange<InputIteratorNotInputOrOutputIterator>; 75 76 static_assert(!std::input_or_output_iterator<InputIteratorNotInputOrOutputIterator>); 77 static_assert(std::indirectly_readable<InputIteratorNotInputOrOutputIterator>); 78 static_assert(!std::input_iterator<InputIteratorNotInputOrOutputIterator>); 79 static_assert(!std::ranges::input_range<InputRangeNotInputOrOutputIterator>); 80 81 // almost an indirect_unary_predicate 82 class IndirectUnaryPredicateNotCopyConstructible { 83 public: 84 IndirectUnaryPredicateNotCopyConstructible(const IndirectUnaryPredicateNotCopyConstructible&) = delete; 85 bool operator()(int) const; 86 }; 87 88 static_assert(std::predicate<IndirectUnaryPredicateNotCopyConstructible, int&>); 89 static_assert(!std::indirect_unary_predicate<IndirectUnaryPredicateNotCopyConstructible, int*>); 90 91 class IndirectUnaryPredicateNotPredicate { 92 public: 93 bool operator()(int&&) const; 94 }; 95 96 static_assert(!std::predicate<IndirectUnaryPredicateNotPredicate, int&>); 97 static_assert(!std::indirect_unary_predicate<IndirectUnaryPredicateNotPredicate, int*>); 98 99 // almost a sentinel_for cpp20_input_iterator 100 class SentinelForNotSemiregular { 101 public: 102 SentinelForNotSemiregular() = delete; 103 using difference_type = long; 104 SentinelForNotSemiregular& operator++(); 105 void operator++(int); 106 const int& operator*() const; 107 friend bool operator==(const SentinelForNotSemiregular&, const cpp20_input_iterator<int*>&); 108 }; 109 110 using InputRangeNotSentinelSemiregular = UncheckedRange<cpp20_input_iterator<int*>, SentinelForNotSemiregular>; 111 using OutputRangeNotSentinelSemiregular = UncheckedRange<cpp20_output_iterator<int*>, SentinelForNotSemiregular>; 112 113 static_assert(std::input_or_output_iterator<SentinelForNotSemiregular>); 114 static_assert(!std::semiregular<SentinelForNotSemiregular>); 115 static_assert(!std::sentinel_for<SentinelForNotSemiregular, cpp20_input_iterator<int*>>); 116 117 // almost a sentinel_for cpp20_input_iterator 118 class SentinelForNotWeaklyEqualityComparableWith { 119 public: 120 using difference_type = long; 121 SentinelForNotWeaklyEqualityComparableWith& operator++(); 122 void operator++(int); 123 const int& operator*() const; 124 }; 125 126 using InputRangeNotSentinelEqualityComparableWith = 127 UncheckedRange<cpp20_input_iterator<int*>, SentinelForNotWeaklyEqualityComparableWith>; 128 using OutputRangeNotSentinelEqualityComparableWith = 129 UncheckedRange<cpp20_output_iterator<int*>, SentinelForNotWeaklyEqualityComparableWith>; 130 131 static_assert(std::input_or_output_iterator<SentinelForNotWeaklyEqualityComparableWith>); 132 static_assert(std::semiregular<SentinelForNotWeaklyEqualityComparableWith>); 133 static_assert(!std::sentinel_for<SentinelForNotWeaklyEqualityComparableWith, cpp20_input_iterator<int*>>); 134 135 class WeaklyIncrementableNotMovable { 136 public: 137 using difference_type = long; 138 WeaklyIncrementableNotMovable& operator++(); 139 void operator++(int); 140 WeaklyIncrementableNotMovable(const WeaklyIncrementableNotMovable&) = delete; 141 }; 142 143 static_assert(!std::movable<WeaklyIncrementableNotMovable>); 144 static_assert(!std::weakly_incrementable<WeaklyIncrementableNotMovable>); 145 146 // almost a forward_iterator 147 class ForwardIteratorNotDerivedFrom { 148 public: 149 using difference_type = long; 150 using value_type = int; 151 using iterator_category = std::input_iterator_tag; 152 153 ForwardIteratorNotDerivedFrom& operator++(); 154 ForwardIteratorNotDerivedFrom operator++(int); 155 const int& operator*() const; 156 bool operator==(const ForwardIteratorNotDerivedFrom&) const = default; 157 }; 158 159 using ForwardRangeNotDerivedFrom = UncheckedRange<ForwardIteratorNotDerivedFrom>; 160 161 static_assert(std::input_iterator<ForwardIteratorNotDerivedFrom>); 162 static_assert(std::incrementable<ForwardIteratorNotDerivedFrom>); 163 static_assert(std::sentinel_for<ForwardIteratorNotDerivedFrom, ForwardIteratorNotDerivedFrom>); 164 static_assert(!std::forward_iterator<ForwardIteratorNotDerivedFrom>); 165 166 class ForwardIteratorNotIncrementable { 167 public: 168 using difference_type = long; 169 using value_type = int; 170 using iterator_category = std::forward_iterator_tag; 171 172 ForwardIteratorNotIncrementable& operator++(); 173 int operator++(int); 174 const int& operator*() const; 175 bool operator==(const ForwardIteratorNotIncrementable&) const = default; 176 }; 177 178 using ForwardRangeNotIncrementable = UncheckedRange<ForwardIteratorNotIncrementable>; 179 180 static_assert(std::input_iterator<ForwardIteratorNotIncrementable>); 181 static_assert(!std::incrementable<ForwardIteratorNotIncrementable>); 182 static_assert(std::sentinel_for<ForwardIteratorNotIncrementable, ForwardIteratorNotIncrementable>); 183 static_assert(!std::forward_iterator<ForwardIteratorNotIncrementable>); 184 185 using ForwardRangeNotSentinelSemiregular = UncheckedRange<forward_iterator<int*>, SentinelForNotSemiregular>; 186 using ForwardRangeNotSentinelEqualityComparableWith = 187 UncheckedRange<forward_iterator<int*>, SentinelForNotWeaklyEqualityComparableWith>; 188 189 class BidirectionalIteratorNotDerivedFrom { 190 public: 191 using difference_type = long; 192 using value_type = int; 193 using iterator_category = std::forward_iterator_tag; 194 195 BidirectionalIteratorNotDerivedFrom& operator++(); 196 BidirectionalIteratorNotDerivedFrom operator++(int); 197 BidirectionalIteratorNotDerivedFrom& operator--(); 198 BidirectionalIteratorNotDerivedFrom operator--(int); 199 int& operator*() const; 200 201 bool operator==(const BidirectionalIteratorNotDerivedFrom&) const = default; 202 }; 203 204 using BidirectionalRangeNotDerivedFrom = UncheckedRange<BidirectionalIteratorNotDerivedFrom>; 205 using BidirectionalRangeNotSentinelSemiregular = 206 UncheckedRange<bidirectional_iterator<int*>, SentinelForNotSemiregular>; 207 using BidirectionalRangeNotSentinelWeaklyEqualityComparableWith = 208 UncheckedRange<bidirectional_iterator<int*>, SentinelForNotWeaklyEqualityComparableWith>; 209 210 static_assert(std::forward_iterator<BidirectionalIteratorNotDerivedFrom>); 211 static_assert(!std::bidirectional_iterator<BidirectionalIteratorNotDerivedFrom>); 212 static_assert(!std::ranges::bidirectional_range<BidirectionalRangeNotDerivedFrom>); 213 214 class BidirectionalIteratorNotDecrementable { 215 public: 216 using difference_type = long; 217 using value_type = int; 218 using iterator_category = std::bidirectional_iterator_tag; 219 220 BidirectionalIteratorNotDecrementable& operator++(); 221 BidirectionalIteratorNotDecrementable operator++(int); 222 int& operator*() const; 223 224 bool operator==(const BidirectionalIteratorNotDecrementable&) const = default; 225 }; 226 227 using BidirectionalRangeNotDecrementable = UncheckedRange<BidirectionalIteratorNotDecrementable>; 228 229 static_assert(std::forward_iterator<BidirectionalIteratorNotDecrementable>); 230 static_assert(!std::bidirectional_iterator<BidirectionalIteratorNotDecrementable>); 231 static_assert(!std::ranges::bidirectional_range<BidirectionalRangeNotDecrementable>); 232 233 class PermutableNotForwardIterator { 234 public: 235 using difference_type = long; 236 using value_type = int; 237 using iterator_category = std::input_iterator_tag; 238 239 PermutableNotForwardIterator& operator++(); 240 void operator++(int); 241 int& operator*() const; 242 }; 243 244 using PermutableRangeNotForwardIterator = UncheckedRange<PermutableNotForwardIterator>; 245 246 static_assert(std::input_iterator<PermutableNotForwardIterator>); 247 static_assert(!std::forward_iterator<PermutableNotForwardIterator>); 248 static_assert(!std::permutable<PermutableNotForwardIterator>); 249 250 class PermutableNotSwappable { 251 public: 252 class NotSwappable { 253 NotSwappable(NotSwappable&&) = delete; 254 }; 255 256 using difference_type = long; 257 using value_type = NotSwappable; 258 using iterator_category = std::contiguous_iterator_tag; 259 260 PermutableNotSwappable& operator++(); 261 PermutableNotSwappable operator++(int); 262 NotSwappable& operator*() const; 263 264 bool operator==(const PermutableNotSwappable&) const = default; 265 }; 266 267 using PermutableRangeNotSwappable = UncheckedRange<PermutableNotSwappable>; 268 269 static_assert(std::input_iterator<PermutableNotSwappable>); 270 static_assert(std::forward_iterator<PermutableNotSwappable>); 271 static_assert(!std::permutable<PermutableNotSwappable>); 272 static_assert(!std::indirectly_swappable<PermutableNotSwappable>); 273 274 class OutputIteratorNotInputOrOutputIterator { 275 public: 276 using difference_type = long; 277 using value_type = int; 278 using iterator_category = std::input_iterator_tag; 279 280 int& operator++(); 281 void operator++(int); 282 int& operator*(); 283 }; 284 285 using OutputRangeNotInputOrOutputIterator = UncheckedRange<InputIteratorNotInputOrOutputIterator>; 286 287 static_assert(!std::input_or_output_iterator<OutputIteratorNotInputOrOutputIterator>); 288 static_assert(std::indirectly_writable<OutputIteratorNotInputOrOutputIterator, int>); 289 static_assert(!std::output_iterator<OutputIteratorNotInputOrOutputIterator, int>); 290 static_assert(!std::ranges::input_range<OutputRangeNotInputOrOutputIterator>); 291 292 class OutputIteratorNotIndirectlyWritable { 293 public: 294 using difference_type = long; 295 using iterator_category = std::input_iterator_tag; 296 297 OutputIteratorNotIndirectlyWritable& operator++(); 298 void operator++(int); 299 const int& operator*() const; 300 }; 301 302 using OutputRangeNotIndirectlyWritable = UncheckedRange<OutputIteratorNotIndirectlyWritable>; 303 304 static_assert(std::input_or_output_iterator<OutputIteratorNotIndirectlyWritable>); 305 static_assert(!std::indirectly_writable<OutputIteratorNotIndirectlyWritable, int>); 306 static_assert(!std::output_iterator<OutputIteratorNotIndirectlyWritable, int>); 307 static_assert(!std::ranges::output_range<OutputIteratorNotIndirectlyWritable, int>); 308 309 class IndirectBinaryPredicateNotIndirectlyReadable { 310 public: 311 using difference_type = long; 312 using iterator_category = std::input_iterator_tag; 313 314 int& operator++(); 315 void operator++(int); 316 const int& operator*() const; 317 }; 318 319 using InputRangeIndirectBinaryPredicateNotIndirectlyReadable 320 = UncheckedRange<cpp20_input_iterator<int*>, IndirectBinaryPredicateNotIndirectlyReadable>; 321 322 static_assert(!std::indirect_binary_predicate<std::ranges::equal_to, IndirectBinaryPredicateNotIndirectlyReadable, int*>); 323 324 class RandomAccessIteratorNotDerivedFrom { 325 using Self = RandomAccessIteratorNotDerivedFrom; 326 327 public: 328 using value_type = int; 329 using difference_type = long; 330 using pointer = int*; 331 using reference = int&; 332 // Deliberately not using the `std::random_access_iterator_tag` category. 333 using iterator_category = std::bidirectional_iterator_tag; 334 335 reference operator*() const; 336 reference operator[](difference_type) const; 337 338 Self& operator++(); 339 Self& operator--(); 340 Self operator++(int); 341 Self operator--(int); 342 343 Self& operator+=(difference_type); 344 Self& operator-=(difference_type); 345 friend Self operator+(Self, difference_type); 346 friend Self operator+(difference_type, Self); 347 friend Self operator-(Self, difference_type); 348 friend difference_type operator-(Self, Self); 349 350 auto operator<=>(const Self&) const = default; 351 }; 352 353 static_assert(std::bidirectional_iterator<RandomAccessIteratorNotDerivedFrom>); 354 static_assert(!std::random_access_iterator<RandomAccessIteratorNotDerivedFrom>); 355 356 using RandomAccessRangeNotDerivedFrom = UncheckedRange<RandomAccessIteratorNotDerivedFrom>; 357 358 class RandomAccessIteratorBadIndex { 359 using Self = RandomAccessIteratorBadIndex; 360 361 public: 362 using value_type = int; 363 using difference_type = long; 364 using pointer = int*; 365 using reference = int&; 366 using iterator_category = std::random_access_iterator_tag; 367 368 reference operator*() const; 369 // Deliberately returning a type different from `reference`. 370 const int& operator[](difference_type) const; 371 372 Self& operator++(); 373 Self& operator--(); 374 Self operator++(int); 375 Self operator--(int); 376 377 Self& operator+=(difference_type); 378 Self& operator-=(difference_type); 379 friend Self operator+(Self, difference_type); 380 friend Self operator+(difference_type, Self); 381 friend Self operator-(Self, difference_type); 382 friend difference_type operator-(Self, Self); 383 384 auto operator<=>(const Self&) const = default; 385 }; 386 387 static_assert(std::bidirectional_iterator<RandomAccessIteratorBadIndex>); 388 static_assert(!std::random_access_iterator<RandomAccessIteratorBadIndex>); 389 390 using RandomAccessRangeBadIndex = UncheckedRange<RandomAccessIteratorBadIndex>; 391 392 template <class Iter> 393 class ComparatorNotCopyable { 394 public: 395 ComparatorNotCopyable(ComparatorNotCopyable&&) = default; 396 ComparatorNotCopyable& operator=(ComparatorNotCopyable&&) = default; 397 ComparatorNotCopyable(const ComparatorNotCopyable&) = delete; 398 ComparatorNotCopyable& operator=(const ComparatorNotCopyable&) = delete; 399 400 bool operator()(Iter&, Iter&) const; 401 }; 402 403 #endif // ALMOST_SATISFIES_TYPES_H 404