]> git.ipfire.org Git - thirdparty/gcc.git/blame - libstdc++-v3/testsuite/util/testsuite_iterators.h
Update copyright years.
[thirdparty/gcc.git] / libstdc++-v3 / testsuite / util / testsuite_iterators.h
CommitLineData
278d4cc4 1// -*- C++ -*-
f92ab29f 2// Iterator Wrappers for the C++ library testsuite.
278d4cc4 3//
7adcbafe 4// Copyright (C) 2004-2022 Free Software Foundation, Inc.
278d4cc4
CJ
5//
6// This file is part of the GNU ISO C++ Library. This library is free
7// software; you can redistribute it and/or modify it under the
8// terms of the GNU General Public License as published by the
748086b7 9// Free Software Foundation; either version 3, or (at your option)
278d4cc4
CJ
10// any later version.
11//
12// This library is distributed in the hope that it will be useful,
13// but WITHOUT ANY WARRANTY; without even the implied warranty of
14// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15// GNU General Public License for more details.
16//
17// You should have received a copy of the GNU General Public License along
748086b7
JJ
18// with this library; see the file COPYING3. If not see
19// <http://www.gnu.org/licenses/>.
278d4cc4 20//
278d4cc4
CJ
21
22// This file provides the following:
23//
24// input_iterator_wrapper, output_iterator_wrapper
25// forward_iterator_wrapper, bidirectional_iterator_wrapper and
26// random_access_wrapper, which attempt to exactly perform the requirements
27// of these types of iterators. These are constructed from the class
28// test_container, which is given two pointers to T and an iterator type.
29
30#include <testsuite_hooks.h>
acb8a4ef 31#include <bits/stl_iterator_base_types.h>
cb2168c9 32
734f5023 33#if __cplusplus >= 201103L
ca0f8fd1 34#include <bits/move.h>
cb2168c9 35#endif
278d4cc4
CJ
36
37#ifndef _TESTSUITE_ITERATORS
38#define _TESTSUITE_ITERATORS
39
40#ifdef DISABLE_ITERATOR_DEBUG
41#define ITERATOR_VERIFY(x)
42#else
43#define ITERATOR_VERIFY(x) VERIFY(x)
44#endif
45
46namespace __gnu_test
47{
48 /**
49 * @brief Simple container for holding two pointers.
50 *
51 * Note that input_iterator_wrapper changes first to denote
52 * how the valid range of == , ++, etc. change as the iterators are used.
53 */
54 template<typename T>
55 struct BoundsContainer
56 {
57 T* first;
58 T* last;
9921ac3d 59
65be6ddd 60 BoundsContainer(T* _first, T* _last) : first(_first), last(_last)
278d4cc4 61 { }
9921ac3d
JW
62
63 std::size_t size() const { return last - first; }
278d4cc4
CJ
64 };
65
66 // Simple container for holding state of a set of output iterators.
67 template<typename T>
68 struct OutputContainer : public BoundsContainer<T>
69 {
70 T* incrementedto;
71 bool* writtento;
9921ac3d 72
278d4cc4 73 OutputContainer(T* _first, T* _last)
9921ac3d
JW
74 : BoundsContainer<T>(_first, _last), incrementedto(_first),
75 writtento(new bool[this->size()]())
76 { }
278d4cc4
CJ
77
78 ~OutputContainer()
79 { delete[] writtento; }
80 };
81
82 // Produced by output_iterator to allow limited writing to pointer
83 template<class T>
84 class WritableObject
85 {
86 T* ptr;
87
88 public:
89 OutputContainer<T>* SharedInfo;
9921ac3d
JW
90
91 WritableObject(T* ptr_in, OutputContainer<T>* SharedInfo_in):
278d4cc4
CJ
92 ptr(ptr_in), SharedInfo(SharedInfo_in)
93 { }
94
734f5023 95#if __cplusplus >= 201103L
561e7a36 96 template<class U>
9921ac3d 97 typename std::enable_if<std::is_assignable<T&, U>::value>::type
328b52d6 98 operator=(U&& new_val) const
278d4cc4
CJ
99 {
100 ITERATOR_VERIFY(SharedInfo->writtento[ptr - SharedInfo->first] == 0);
101 SharedInfo->writtento[ptr - SharedInfo->first] = 1;
01bbe151 102 *ptr = std::forward<U>(new_val);
278d4cc4 103 }
01bbe151 104#else
3c167a8b
PC
105 template<class U>
106 void
01bbe151 107 operator=(const U& new_val)
3c167a8b
PC
108 {
109 ITERATOR_VERIFY(SharedInfo->writtento[ptr - SharedInfo->first] == 0);
110 SharedInfo->writtento[ptr - SharedInfo->first] = 1;
01bbe151 111 *ptr = new_val;
3c167a8b
PC
112 }
113#endif
278d4cc4
CJ
114 };
115
116 /**
117 * @brief output_iterator wrapper for pointer
f92ab29f 118 *
278d4cc4
CJ
119 * This class takes a pointer and wraps it to provide exactly
120 * the requirements of a output_iterator. It should not be
f7fbb003 121 * instantiated directly, but generated from a test_container
278d4cc4
CJ
122 */
123 template<class T>
65be6ddd 124 struct output_iterator_wrapper
0614bbbe 125 : public std::iterator<std::output_iterator_tag, void, std::ptrdiff_t, void, void>
278d4cc4 126 {
4512b7d8
PP
127 protected:
128 output_iterator_wrapper() : ptr(0), SharedInfo(0)
129 { }
130
131 public:
278d4cc4
CJ
132 typedef OutputContainer<T> ContainerType;
133 T* ptr;
134 ContainerType* SharedInfo;
135
136 output_iterator_wrapper(T* _ptr, ContainerType* SharedInfo_in)
65be6ddd 137 : ptr(_ptr), SharedInfo(SharedInfo_in)
278d4cc4
CJ
138 {
139 ITERATOR_VERIFY(ptr >= SharedInfo->first && ptr <= SharedInfo->last);
140 }
f92ab29f 141
0a70fb87 142#if __cplusplus >= 201103L
0a70fb87
JW
143 output_iterator_wrapper(const output_iterator_wrapper&) = default;
144
145 output_iterator_wrapper&
146 operator=(const output_iterator_wrapper&) = default;
147#endif
278d4cc4
CJ
148
149 WritableObject<T>
150 operator*() const
151 {
152 ITERATOR_VERIFY(ptr < SharedInfo->last);
153 ITERATOR_VERIFY(SharedInfo->writtento[ptr - SharedInfo->first] == false);
154 return WritableObject<T>(ptr, SharedInfo);
155 }
f92ab29f 156
278d4cc4
CJ
157 output_iterator_wrapper&
158 operator++()
159 {
160 ITERATOR_VERIFY(SharedInfo && ptr < SharedInfo->last);
561e7a36 161 ITERATOR_VERIFY(ptr>=SharedInfo->incrementedto);
278d4cc4 162 ptr++;
561e7a36 163 SharedInfo->incrementedto=ptr;
278d4cc4
CJ
164 return *this;
165 }
166
167 output_iterator_wrapper
168 operator++(int)
169 {
170 output_iterator_wrapper<T> tmp = *this;
171 ++*this;
172 return tmp;
173 }
174
f970a17d
JW
175#if __cplusplus >= 201103L
176 template<typename U>
177 void operator,(const U&) const = delete;
aca7a025
JW
178
179 void operator&() const = delete;
f970a17d
JW
180#else
181 private:
182 template<typename U>
183 void operator,(const U&) const;
aca7a025
JW
184
185 void operator&() const;
f970a17d 186#endif
278d4cc4
CJ
187 };
188
d67be443
JW
189#if __cplusplus >= 201103L
190 template<typename T, typename U>
191 void operator,(const T&, const output_iterator_wrapper<U>&) = delete;
192#endif
193
5211593c 194#if __cplusplus >= 201103L
9921ac3d
JW
195 using std::remove_cv;
196#else
e112d53a
JW
197 template<typename T> struct remove_cv { typedef T type; };
198 template<typename T> struct remove_cv<const T> { typedef T type; };
199 template<typename T> struct remove_cv<volatile T> { typedef T type; };
200 template<typename T> struct remove_cv<const volatile T> { typedef T type; };
9921ac3d 201#endif
e112d53a 202
278d4cc4
CJ
203 /**
204 * @brief input_iterator wrapper for pointer
f92ab29f 205 *
278d4cc4
CJ
206 * This class takes a pointer and wraps it to provide exactly
207 * the requirements of a input_iterator. It should not be
f7fbb003 208 * instantiated directly, but generated from a test_container
278d4cc4
CJ
209 */
210 template<class T>
65be6ddd 211 class input_iterator_wrapper
e112d53a
JW
212 : public std::iterator<std::input_iterator_tag, typename remove_cv<T>::type,
213 std::ptrdiff_t, T*, T&>
278d4cc4 214 {
118158b6
JW
215 struct post_inc_proxy
216 {
217 struct deref_proxy
218 {
219 T* ptr;
220 operator const T&() const { return *ptr; }
221 } p;
222
223 deref_proxy operator*() const { return p; }
224 };
225
278d4cc4 226 protected:
0a70fb87 227 input_iterator_wrapper() : ptr(0), SharedInfo(0)
278d4cc4
CJ
228 { }
229
230 public:
231 typedef BoundsContainer<T> ContainerType;
232 T* ptr;
233 ContainerType* SharedInfo;
234
235 input_iterator_wrapper(T* _ptr, ContainerType* SharedInfo_in)
65be6ddd 236 : ptr(_ptr), SharedInfo(SharedInfo_in)
278d4cc4 237 { ITERATOR_VERIFY(ptr >= SharedInfo->first && ptr <= SharedInfo->last); }
f92ab29f 238
0a70fb87
JW
239#if __cplusplus >= 201103L
240 input_iterator_wrapper(const input_iterator_wrapper&) = default;
241
242 input_iterator_wrapper&
243 operator=(const input_iterator_wrapper&) = default;
244#endif
278d4cc4
CJ
245
246 bool
247 operator==(const input_iterator_wrapper& in) const
248 {
8fc81078 249 ITERATOR_VERIFY(SharedInfo && SharedInfo == in.SharedInfo);
278d4cc4
CJ
250 ITERATOR_VERIFY(ptr>=SharedInfo->first && in.ptr>=SharedInfo->first);
251 return ptr == in.ptr;
252 }
253
254 bool
255 operator!=(const input_iterator_wrapper& in) const
256 {
257 return !(*this == in);
258 }
259
260 T&
261 operator*() const
262 {
263 ITERATOR_VERIFY(SharedInfo && ptr < SharedInfo->last);
264 ITERATOR_VERIFY(ptr >= SharedInfo->first);
265 return *ptr;
266 }
267
268 T*
269 operator->() const
270 {
271 return &**this;
272 }
273
278d4cc4
CJ
274 input_iterator_wrapper&
275 operator++()
276 {
277 ITERATOR_VERIFY(SharedInfo && ptr < SharedInfo->last);
278 ITERATOR_VERIFY(ptr>=SharedInfo->first);
279 ptr++;
280 SharedInfo->first=ptr;
281 return *this;
282 }
283
118158b6 284 post_inc_proxy
278d4cc4
CJ
285 operator++(int)
286 {
118158b6 287 post_inc_proxy tmp = { { ptr } };
278d4cc4 288 ++*this;
118158b6 289 return tmp;
278d4cc4 290 }
f970a17d
JW
291
292#if __cplusplus >= 201103L
293 template<typename U>
294 void operator,(const U&) const = delete;
aca7a025
JW
295
296 void operator&() const = delete;
f970a17d
JW
297#else
298 private:
299 template<typename U>
300 void operator,(const U&) const;
aca7a025
JW
301
302 void operator&() const;
f970a17d 303#endif
278d4cc4
CJ
304 };
305
d67be443
JW
306#if __cplusplus >= 201103L
307 template<typename T, typename U>
308 void operator,(const T&, const input_iterator_wrapper<U>&) = delete;
309#endif
278d4cc4
CJ
310
311 /**
312 * @brief forward_iterator wrapper for pointer
f92ab29f 313 *
278d4cc4
CJ
314 * This class takes a pointer and wraps it to provide exactly
315 * the requirements of a forward_iterator. It should not be
f7fbb003 316 * instantiated directly, but generated from a test_container
278d4cc4
CJ
317 */
318 template<class T>
65be6ddd 319 struct forward_iterator_wrapper : public input_iterator_wrapper<T>
278d4cc4
CJ
320 {
321 typedef BoundsContainer<T> ContainerType;
322 typedef std::forward_iterator_tag iterator_category;
0a70fb87 323
278d4cc4 324 forward_iterator_wrapper(T* _ptr, ContainerType* SharedInfo_in)
65be6ddd 325 : input_iterator_wrapper<T>(_ptr, SharedInfo_in)
278d4cc4 326 { }
f92ab29f 327
0a70fb87 328 forward_iterator_wrapper()
278d4cc4
CJ
329 { }
330
0a70fb87
JW
331#if __cplusplus >= 201103L
332 forward_iterator_wrapper(const forward_iterator_wrapper&) = default;
333
334 forward_iterator_wrapper&
335 operator=(const forward_iterator_wrapper&) = default;
336#endif
278d4cc4
CJ
337
338 T&
339 operator*() const
340 {
341 ITERATOR_VERIFY(this->SharedInfo && this->ptr < this->SharedInfo->last);
342 return *(this->ptr);
343 }
344
345 T*
346 operator->() const
347 { return &**this; }
348
349 forward_iterator_wrapper&
350 operator++()
351 {
352 ITERATOR_VERIFY(this->SharedInfo && this->ptr < this->SharedInfo->last);
353 this->ptr++;
354 return *this;
355 }
356
357 forward_iterator_wrapper
358 operator++(int)
359 {
360 forward_iterator_wrapper<T> tmp = *this;
361 ++*this;
362 return tmp;
363 }
e94f2542
JW
364
365#if __cplusplus >= 201402L
366 bool
367 operator==(const forward_iterator_wrapper& it) const noexcept
368 {
369 // Since C++14 value-initialized forward iterators are comparable.
370 if (this->SharedInfo == nullptr || it.SharedInfo == nullptr)
371 return this->SharedInfo == it.SharedInfo && this->ptr == it.ptr;
372
373 const input_iterator_wrapper<T>& base_this = *this;
374 const input_iterator_wrapper<T>& base_that = it;
375 return base_this == base_that;
376 }
377
378 bool
379 operator!=(const forward_iterator_wrapper& it) const noexcept
380 {
381 return !(*this == it);
382 }
383#endif
f970a17d 384 };
278d4cc4
CJ
385
386 /**
387 * @brief bidirectional_iterator wrapper for pointer
f92ab29f 388 *
278d4cc4 389 * This class takes a pointer and wraps it to provide exactly
ac2dca4d 390 * the requirements of a bidirectional_iterator. It should not be
f7fbb003 391 * instantiated directly, but generated from a test_container
278d4cc4
CJ
392 */
393 template<class T>
65be6ddd 394 struct bidirectional_iterator_wrapper : public forward_iterator_wrapper<T>
278d4cc4
CJ
395 {
396 typedef BoundsContainer<T> ContainerType;
397 typedef std::bidirectional_iterator_tag iterator_category;
0a70fb87 398
278d4cc4 399 bidirectional_iterator_wrapper(T* _ptr, ContainerType* SharedInfo_in)
65be6ddd 400 : forward_iterator_wrapper<T>(_ptr, SharedInfo_in)
278d4cc4
CJ
401 { }
402
0a70fb87
JW
403 bidirectional_iterator_wrapper()
404 : forward_iterator_wrapper<T>()
278d4cc4
CJ
405 { }
406
0a70fb87
JW
407#if __cplusplus >= 201103L
408 bidirectional_iterator_wrapper(
409 const bidirectional_iterator_wrapper&) = default;
278d4cc4
CJ
410
411 bidirectional_iterator_wrapper&
0a70fb87
JW
412 operator=(const bidirectional_iterator_wrapper&) = default;
413#endif
f92ab29f 414
278d4cc4
CJ
415 bidirectional_iterator_wrapper&
416 operator++()
417 {
418 ITERATOR_VERIFY(this->SharedInfo && this->ptr < this->SharedInfo->last);
419 this->ptr++;
420 return *this;
421 }
422
423 bidirectional_iterator_wrapper
424 operator++(int)
425 {
426 bidirectional_iterator_wrapper<T> tmp = *this;
427 ++*this;
428 return tmp;
429 }
430
f92ab29f 431 bidirectional_iterator_wrapper&
278d4cc4
CJ
432 operator--()
433 {
434 ITERATOR_VERIFY(this->SharedInfo && this->ptr > this->SharedInfo->first);
435 this->ptr--;
436 return *this;
437 }
438
439 bidirectional_iterator_wrapper
440 operator--(int)
f92ab29f 441 {
278d4cc4
CJ
442 bidirectional_iterator_wrapper<T> tmp = *this;
443 --*this;
444 return tmp;
445 }
f970a17d 446 };
278d4cc4
CJ
447
448 /**
449 * @brief random_access_iterator wrapper for pointer
f92ab29f 450 *
278d4cc4 451 * This class takes a pointer and wraps it to provide exactly
ac2dca4d 452 * the requirements of a random_access_iterator. It should not be
f7fbb003 453 * instantiated directly, but generated from a test_container
278d4cc4
CJ
454 */
455 template<class T>
f92ab29f 456 struct random_access_iterator_wrapper
65be6ddd 457 : public bidirectional_iterator_wrapper<T>
278d4cc4
CJ
458 {
459 typedef BoundsContainer<T> ContainerType;
460 typedef std::random_access_iterator_tag iterator_category;
0a70fb87 461
278d4cc4 462 random_access_iterator_wrapper(T* _ptr, ContainerType* SharedInfo_in)
65be6ddd 463 : bidirectional_iterator_wrapper<T>(_ptr, SharedInfo_in)
278d4cc4
CJ
464 { }
465
0a70fb87
JW
466 random_access_iterator_wrapper()
467 : bidirectional_iterator_wrapper<T>()
278d4cc4
CJ
468 { }
469
0a70fb87
JW
470#if __cplusplus >= 201103L
471 random_access_iterator_wrapper(
472 const random_access_iterator_wrapper&) = default;
278d4cc4
CJ
473
474 random_access_iterator_wrapper&
0a70fb87
JW
475 operator=(const random_access_iterator_wrapper&) = default;
476#endif
278d4cc4
CJ
477
478 random_access_iterator_wrapper&
479 operator++()
480 {
481 ITERATOR_VERIFY(this->SharedInfo && this->ptr < this->SharedInfo->last);
482 this->ptr++;
483 return *this;
484 }
485
486 random_access_iterator_wrapper
487 operator++(int)
488 {
489 random_access_iterator_wrapper<T> tmp = *this;
490 ++*this;
491 return tmp;
492 }
493
494 random_access_iterator_wrapper&
495 operator--()
496 {
497 ITERATOR_VERIFY(this->SharedInfo && this->ptr > this->SharedInfo->first);
498 this->ptr--;
499 return *this;
500 }
501
502 random_access_iterator_wrapper
503 operator--(int)
504 {
505 random_access_iterator_wrapper<T> tmp = *this;
561e7a36 506 --*this;
278d4cc4
CJ
507 return tmp;
508 }
509
510 random_access_iterator_wrapper&
445877a9 511 operator+=(std::ptrdiff_t n)
278d4cc4
CJ
512 {
513 if(n > 0)
514 {
515 ITERATOR_VERIFY(n <= this->SharedInfo->last - this->ptr);
516 this->ptr += n;
517 }
518 else
519 {
e1008cd1 520 ITERATOR_VERIFY(-n <= this->ptr - this->SharedInfo->first);
278d4cc4
CJ
521 this->ptr += n;
522 }
523 return *this;
524 }
525
278d4cc4 526 random_access_iterator_wrapper&
445877a9 527 operator-=(std::ptrdiff_t n)
278d4cc4
CJ
528 { return *this += -n; }
529
530 random_access_iterator_wrapper
445877a9 531 operator-(std::ptrdiff_t n) const
278d4cc4
CJ
532 {
533 random_access_iterator_wrapper<T> tmp = *this;
534 return tmp -= n;
535 }
536
445877a9 537 std::ptrdiff_t
561e7a36 538 operator-(const random_access_iterator_wrapper<T>& in) const
278d4cc4
CJ
539 {
540 ITERATOR_VERIFY(this->SharedInfo == in.SharedInfo);
541 return this->ptr - in.ptr;
542 }
543
544 T&
445877a9 545 operator[](std::ptrdiff_t n) const
561e7a36 546 { return *(*this + n); }
278d4cc4
CJ
547
548 bool
549 operator<(const random_access_iterator_wrapper<T>& in) const
550 {
551 ITERATOR_VERIFY(this->SharedInfo == in.SharedInfo);
552 return this->ptr < in.ptr;
553 }
554
555 bool
556 operator>(const random_access_iterator_wrapper<T>& in) const
557 {
558 return in < *this;
559 }
560
561 bool
562 operator>=(const random_access_iterator_wrapper<T>& in) const
563 {
564 return !(*this < in);
565 }
566
f92ab29f 567 bool
278d4cc4
CJ
568 operator<=(const random_access_iterator_wrapper<T>& in) const
569 {
570 return !(*this > in);
571 }
f970a17d 572 };
278d4cc4 573
561e7a36
PC
574 template<typename T>
575 random_access_iterator_wrapper<T>
445877a9 576 operator+(random_access_iterator_wrapper<T> it, std::ptrdiff_t n)
561e7a36
PC
577 { return it += n; }
578
579 template<typename T>
580 random_access_iterator_wrapper<T>
f92ab29f 581 operator+(std::ptrdiff_t n, random_access_iterator_wrapper<T> it)
561e7a36
PC
582 { return it += n; }
583
278d4cc4 584
f92ab29f 585 /**
278d4cc4
CJ
586 * @brief A container-type class for holding iterator wrappers
587 * test_container takes two parameters, a class T and an iterator
588 * wrapper templated by T (for example forward_iterator_wrapper<T>.
f92ab29f 589 * It takes two pointers representing a range and presents them as
278d4cc4
CJ
590 * a container of iterators.
591 */
060269c4 592 template <class T, template<class TT> class ItType>
278d4cc4
CJ
593 struct test_container
594 {
595 typename ItType<T>::ContainerType bounds;
9921ac3d 596
4e66b02b 597 test_container(T* _first, T* _last) : bounds(_first, _last)
278d4cc4
CJ
598 { }
599
3ebacabd 600#if __cplusplus >= 201103L
4e66b02b
JW
601 template<std::size_t N>
602 explicit
603 test_container(T (&arr)[N]) : test_container(arr, arr+N)
604 { }
3ebacabd
JW
605#endif
606
278d4cc4
CJ
607 ItType<T>
608 it(int pos)
609 {
13feb023 610 ITERATOR_VERIFY(pos >= 0 && (unsigned)pos <= size());
278d4cc4
CJ
611 return ItType<T>(bounds.first + pos, &bounds);
612 }
613
614 ItType<T>
615 it(T* pos)
616 {
617 ITERATOR_VERIFY(pos >= bounds.first && pos <= bounds.last);
618 return ItType<T>(pos, &bounds);
619 }
620
c2240038
CJ
621 const T&
622 val(int pos)
623 { return (bounds.first)[pos]; }
624
278d4cc4
CJ
625 ItType<T>
626 begin()
627 { return it(bounds.first); }
628
629 ItType<T>
630 end()
631 { return it(bounds.last); }
ed920373
JW
632
633 std::size_t
634 size() const
9921ac3d 635 { return bounds.size(); }
4e66b02b 636 };
6d0dff49 637
e1008cd1
JW
638#if __cplusplus >= 201103L
639 template<typename T>
640 using output_container
641 = test_container<T, output_iterator_wrapper>;
642
643 template<typename T>
644 using input_container
645 = test_container<T, input_iterator_wrapper>;
646
647 template<typename T>
648 using forward_container
649 = test_container<T, forward_iterator_wrapper>;
650
651 template<typename T>
652 using bidirectional_container
653 = test_container<T, bidirectional_iterator_wrapper>;
654
655 template<typename T>
656 using random_access_container
657 = test_container<T, random_access_iterator_wrapper>;
658#endif
659
6d0dff49
JW
660#if __cplusplus > 201703L
661 template<typename T>
662 struct contiguous_iterator_wrapper
663 : random_access_iterator_wrapper<T>
664 {
665 using random_access_iterator_wrapper<T>::random_access_iterator_wrapper;
666
667 using iterator_concept = std::contiguous_iterator_tag;
668
669 contiguous_iterator_wrapper&
670 operator++()
671 {
672 random_access_iterator_wrapper<T>::operator++();
673 return *this;
674 }
675
676 contiguous_iterator_wrapper&
677 operator--()
678 {
679 random_access_iterator_wrapper<T>::operator--();
680 return *this;
681 }
682
683 contiguous_iterator_wrapper
684 operator++(int)
685 {
686 auto tmp = *this;
687 ++*this;
688 return tmp;
689 }
690
691 contiguous_iterator_wrapper
692 operator--(int)
693 {
694 auto tmp = *this;
695 --*this;
696 return tmp;
697 }
698
699 contiguous_iterator_wrapper&
700 operator+=(std::ptrdiff_t n)
701 {
702 random_access_iterator_wrapper<T>::operator+=(n);
703 return *this;
704 }
705
706 friend contiguous_iterator_wrapper
707 operator+(contiguous_iterator_wrapper iter, std::ptrdiff_t n)
708 { return iter += n; }
709
710 friend contiguous_iterator_wrapper
711 operator+(std::ptrdiff_t n, contiguous_iterator_wrapper iter)
712 { return iter += n; }
713
714 contiguous_iterator_wrapper&
715 operator-=(std::ptrdiff_t n)
716 { return *this += -n; }
717
718 friend contiguous_iterator_wrapper
719 operator-(contiguous_iterator_wrapper iter, std::ptrdiff_t n)
720 { return iter -= n; }
721 };
722
e1008cd1
JW
723 template<typename T>
724 using contiguous_container
725 = test_container<T, contiguous_iterator_wrapper>;
726
d6d4b339
PP
727 // A move-only input iterator type.
728 template<typename T>
729 struct input_iterator_wrapper_nocopy : input_iterator_wrapper<T>
730 {
731 using input_iterator_wrapper<T>::input_iterator_wrapper;
732
733 input_iterator_wrapper_nocopy()
734 : input_iterator_wrapper<T>(nullptr, nullptr)
735 { }
736
737 input_iterator_wrapper_nocopy(const input_iterator_wrapper_nocopy&) = delete;
738 input_iterator_wrapper_nocopy&
739 operator=(const input_iterator_wrapper_nocopy&) = delete;
740
741 input_iterator_wrapper_nocopy(input_iterator_wrapper_nocopy&&) = default;
742 input_iterator_wrapper_nocopy&
743 operator=(input_iterator_wrapper_nocopy&&) = default;
744
745 using input_iterator_wrapper<T>::operator++;
746
747 input_iterator_wrapper_nocopy&
748 operator++()
749 {
750 input_iterator_wrapper<T>::operator++();
751 return *this;
752 }
753 };
754
6d0dff49
JW
755 // A type meeting the minimum std::range requirements
756 template<typename T, template<typename> class Iter>
757 class test_range
758 {
4512b7d8
PP
759 // Exposes the protected default constructor of Iter<T> if needed. This
760 // is needed only when Iter is input_iterator_wrapper or
761 // output_iterator_wrapper, because legacy forward iterators and beyond
762 // are already default constructible.
6d0dff49
JW
763 struct iterator : Iter<T>
764 {
765 using Iter<T>::Iter;
766
6d0dff49
JW
767 using Iter<T>::operator++;
768
769 iterator& operator++() { Iter<T>::operator++(); return *this; }
770 };
771
772 template<typename I>
773 struct sentinel
774 {
775 T* end;
776
5cd2e126 777 friend bool operator==(const sentinel& s, const I& i) noexcept
6d0dff49 778 { return s.end == i.ptr; }
5cd2e126
JW
779
780 friend auto operator-(const sentinel& s, const I& i) noexcept
781 requires std::random_access_iterator<I>
782 { return s.end - i.ptr; }
783
784 friend auto operator-(const I& i, const sentinel& s) noexcept
785 requires std::random_access_iterator<I>
786 { return i.ptr - s.end; }
6d0dff49
JW
787 };
788
26af9cd8 789 protected:
6d0dff49
JW
790 auto
791 get_iterator(T* p)
792 {
a31517cb 793 if constexpr (std::default_initializable<Iter<T>>)
6d0dff49
JW
794 return Iter<T>(p, &bounds);
795 else
796 return iterator(p, &bounds);
797 }
798
799 public:
800 test_range(T* first, T* last) : bounds(first, last)
801 { }
802
803 template<std::size_t N>
804 explicit
805 test_range(T (&arr)[N]) : test_range(arr, arr+N)
806 { }
807
808 auto begin() & { return get_iterator(bounds.first); }
809
810 auto end() &
811 {
812 using I = decltype(get_iterator(bounds.last));
6e5a1963 813 return sentinel<I>{bounds.last};
6d0dff49
JW
814 }
815
816 typename Iter<T>::ContainerType bounds;
817 };
818
328b52d6
JW
819 template<typename T>
820 using test_contiguous_range
821 = test_range<T, contiguous_iterator_wrapper>;
822 template<typename T>
823 using test_random_access_range
824 = test_range<T, random_access_iterator_wrapper>;
825 template<typename T>
826 using test_bidirectional_range
827 = test_range<T, bidirectional_iterator_wrapper>;
828 template<typename T>
829 using test_forward_range
830 = test_range<T, forward_iterator_wrapper>;
831 template<typename T>
832 using test_input_range
833 = test_range<T, input_iterator_wrapper>;
834 template<typename T>
835 using test_output_range
836 = test_range<T, output_iterator_wrapper>;
837
6d0dff49
JW
838 // A type meeting the minimum std::sized_range requirements
839 template<typename T, template<typename> class Iter>
840 struct test_sized_range : test_range<T, Iter>
841 {
842 using test_range<T, Iter>::test_range;
843
844 std::size_t size() const noexcept
845 { return this->bounds.size(); }
846 };
328b52d6
JW
847
848 template<typename T>
849 using test_contiguous_sized_range
850 = test_sized_range<T, contiguous_iterator_wrapper>;
851 template<typename T>
852 using test_random_access_sized_range
853 = test_sized_range<T, random_access_iterator_wrapper>;
854 template<typename T>
855 using test_bidirectional_sized_range
856 = test_sized_range<T, bidirectional_iterator_wrapper>;
857 template<typename T>
858 using test_forward_sized_range
859 = test_sized_range<T, forward_iterator_wrapper>;
860 template<typename T>
861 using test_input_sized_range
862 = test_sized_range<T, input_iterator_wrapper>;
863 template<typename T>
864 using test_output_sized_range
865 = test_sized_range<T, output_iterator_wrapper>;
b5b2e387 866
26af9cd8
PP
867 // A type meeting the minimum std::sized_range requirements, and whose end()
868 // returns a sized sentinel.
869 template<typename T, template<typename> class Iter>
870 struct test_sized_range_sized_sent : test_sized_range<T, Iter>
871 {
872 using test_sized_range<T, Iter>::test_sized_range;
873
874 template<typename I>
875 struct sentinel
876 {
877 T* end;
878
879 friend bool operator==(const sentinel& s, const I& i) noexcept
880 { return s.end == i.ptr; }
881
882 friend std::iter_difference_t<I>
883 operator-(const sentinel& s, const I& i) noexcept
884 { return s.end - i.ptr; }
885
886 friend std::iter_difference_t<I>
887 operator-(const I& i, const sentinel& s) noexcept
888 { return i.ptr - s.end; }
889 };
890
891 auto end() &
892 {
893 using I = decltype(this->get_iterator(this->bounds.last));
894 return sentinel<I>{this->bounds.last};
895 }
896 };
897
68be73fc 898// test_range and test_sized_range do not own their elements, so they model
15411a64
JW
899// std::ranges::borrowed_range. This file does not define specializations of
900// std::ranges::enable_borrowed_range, so that individual tests can decide
68be73fc
JW
901// whether or not to do so.
902// This is also true for test_container, although only when it has forward
903// iterators (because output_iterator_wrapper and input_iterator_wrapper are
904// not default constructible so do not model std::input_or_output_iterator).
b9e35ee6
JW
905
906
907 // Test for basic properties of C++20 16.3.3.6 [customization.point.object].
908 template<typename T>
909 constexpr bool
910 is_customization_point_object(T& obj) noexcept
911 {
912 // A [CPO] is a function object with a literal class type.
913 static_assert( std::is_class_v<T> || std::is_union_v<T> );
914 static_assert( __is_literal_type(T) );
915 // The type of a [CPO], ignoring cv-qualifiers, shall model semiregular.
916 static_assert( std::semiregular<std::remove_cv_t<T>> );
917
918 return true;
919 }
920
6d0dff49
JW
921#endif // C++20
922} // namespace __gnu_test
923#endif // _TESTSUITE_ITERATORS