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