]> 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//
99dee823 4// Copyright (C) 2004-2021 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
445877a9 125 : public std::iterator<std::output_iterator_tag, T, std::ptrdiff_t, T*, T&>
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;
178#else
179 private:
180 template<typename U>
181 void operator,(const U&) const;
182#endif
278d4cc4
CJ
183 };
184
d67be443
JW
185#if __cplusplus >= 201103L
186 template<typename T, typename U>
187 void operator,(const T&, const output_iterator_wrapper<U>&) = delete;
188#endif
189
5211593c 190#if __cplusplus >= 201103L
9921ac3d
JW
191 using std::remove_cv;
192#else
e112d53a
JW
193 template<typename T> struct remove_cv { typedef T type; };
194 template<typename T> struct remove_cv<const T> { typedef T type; };
195 template<typename T> struct remove_cv<volatile T> { typedef T type; };
196 template<typename T> struct remove_cv<const volatile T> { typedef T type; };
9921ac3d 197#endif
e112d53a 198
278d4cc4
CJ
199 /**
200 * @brief input_iterator wrapper for pointer
f92ab29f 201 *
278d4cc4
CJ
202 * This class takes a pointer and wraps it to provide exactly
203 * the requirements of a input_iterator. It should not be
f7fbb003 204 * instantiated directly, but generated from a test_container
278d4cc4
CJ
205 */
206 template<class T>
65be6ddd 207 class input_iterator_wrapper
e112d53a
JW
208 : public std::iterator<std::input_iterator_tag, typename remove_cv<T>::type,
209 std::ptrdiff_t, T*, T&>
278d4cc4 210 {
118158b6
JW
211 struct post_inc_proxy
212 {
213 struct deref_proxy
214 {
215 T* ptr;
216 operator const T&() const { return *ptr; }
217 } p;
218
219 deref_proxy operator*() const { return p; }
220 };
221
278d4cc4 222 protected:
0a70fb87 223 input_iterator_wrapper() : ptr(0), SharedInfo(0)
278d4cc4
CJ
224 { }
225
226 public:
227 typedef BoundsContainer<T> ContainerType;
228 T* ptr;
229 ContainerType* SharedInfo;
230
231 input_iterator_wrapper(T* _ptr, ContainerType* SharedInfo_in)
65be6ddd 232 : ptr(_ptr), SharedInfo(SharedInfo_in)
278d4cc4 233 { ITERATOR_VERIFY(ptr >= SharedInfo->first && ptr <= SharedInfo->last); }
f92ab29f 234
0a70fb87
JW
235#if __cplusplus >= 201103L
236 input_iterator_wrapper(const input_iterator_wrapper&) = default;
237
238 input_iterator_wrapper&
239 operator=(const input_iterator_wrapper&) = default;
240#endif
278d4cc4
CJ
241
242 bool
243 operator==(const input_iterator_wrapper& in) const
244 {
8fc81078 245 ITERATOR_VERIFY(SharedInfo && SharedInfo == in.SharedInfo);
278d4cc4
CJ
246 ITERATOR_VERIFY(ptr>=SharedInfo->first && in.ptr>=SharedInfo->first);
247 return ptr == in.ptr;
248 }
249
250 bool
251 operator!=(const input_iterator_wrapper& in) const
252 {
253 return !(*this == in);
254 }
255
256 T&
257 operator*() const
258 {
259 ITERATOR_VERIFY(SharedInfo && ptr < SharedInfo->last);
260 ITERATOR_VERIFY(ptr >= SharedInfo->first);
261 return *ptr;
262 }
263
264 T*
265 operator->() const
266 {
267 return &**this;
268 }
269
278d4cc4
CJ
270 input_iterator_wrapper&
271 operator++()
272 {
273 ITERATOR_VERIFY(SharedInfo && ptr < SharedInfo->last);
274 ITERATOR_VERIFY(ptr>=SharedInfo->first);
275 ptr++;
276 SharedInfo->first=ptr;
277 return *this;
278 }
279
118158b6 280 post_inc_proxy
278d4cc4
CJ
281 operator++(int)
282 {
118158b6 283 post_inc_proxy tmp = { { ptr } };
278d4cc4 284 ++*this;
118158b6 285 return tmp;
278d4cc4 286 }
f970a17d
JW
287
288#if __cplusplus >= 201103L
289 template<typename U>
290 void operator,(const U&) const = delete;
291#else
292 private:
293 template<typename U>
294 void operator,(const U&) const;
295#endif
278d4cc4
CJ
296 };
297
d67be443
JW
298#if __cplusplus >= 201103L
299 template<typename T, typename U>
300 void operator,(const T&, const input_iterator_wrapper<U>&) = delete;
301#endif
278d4cc4
CJ
302
303 /**
304 * @brief forward_iterator wrapper for pointer
f92ab29f 305 *
278d4cc4
CJ
306 * This class takes a pointer and wraps it to provide exactly
307 * the requirements of a forward_iterator. It should not be
f7fbb003 308 * instantiated directly, but generated from a test_container
278d4cc4
CJ
309 */
310 template<class T>
65be6ddd 311 struct forward_iterator_wrapper : public input_iterator_wrapper<T>
278d4cc4
CJ
312 {
313 typedef BoundsContainer<T> ContainerType;
314 typedef std::forward_iterator_tag iterator_category;
0a70fb87 315
278d4cc4 316 forward_iterator_wrapper(T* _ptr, ContainerType* SharedInfo_in)
65be6ddd 317 : input_iterator_wrapper<T>(_ptr, SharedInfo_in)
278d4cc4 318 { }
f92ab29f 319
0a70fb87 320 forward_iterator_wrapper()
278d4cc4
CJ
321 { }
322
0a70fb87
JW
323#if __cplusplus >= 201103L
324 forward_iterator_wrapper(const forward_iterator_wrapper&) = default;
325
326 forward_iterator_wrapper&
327 operator=(const forward_iterator_wrapper&) = default;
328#endif
278d4cc4
CJ
329
330 T&
331 operator*() const
332 {
333 ITERATOR_VERIFY(this->SharedInfo && this->ptr < this->SharedInfo->last);
334 return *(this->ptr);
335 }
336
337 T*
338 operator->() const
339 { return &**this; }
340
341 forward_iterator_wrapper&
342 operator++()
343 {
344 ITERATOR_VERIFY(this->SharedInfo && this->ptr < this->SharedInfo->last);
345 this->ptr++;
346 return *this;
347 }
348
349 forward_iterator_wrapper
350 operator++(int)
351 {
352 forward_iterator_wrapper<T> tmp = *this;
353 ++*this;
354 return tmp;
355 }
e94f2542
JW
356
357#if __cplusplus >= 201402L
358 bool
359 operator==(const forward_iterator_wrapper& it) const noexcept
360 {
361 // Since C++14 value-initialized forward iterators are comparable.
362 if (this->SharedInfo == nullptr || it.SharedInfo == nullptr)
363 return this->SharedInfo == it.SharedInfo && this->ptr == it.ptr;
364
365 const input_iterator_wrapper<T>& base_this = *this;
366 const input_iterator_wrapper<T>& base_that = it;
367 return base_this == base_that;
368 }
369
370 bool
371 operator!=(const forward_iterator_wrapper& it) const noexcept
372 {
373 return !(*this == it);
374 }
375#endif
f970a17d 376 };
278d4cc4
CJ
377
378 /**
379 * @brief bidirectional_iterator wrapper for pointer
f92ab29f 380 *
278d4cc4 381 * This class takes a pointer and wraps it to provide exactly
ac2dca4d 382 * the requirements of a bidirectional_iterator. It should not be
f7fbb003 383 * instantiated directly, but generated from a test_container
278d4cc4
CJ
384 */
385 template<class T>
65be6ddd 386 struct bidirectional_iterator_wrapper : public forward_iterator_wrapper<T>
278d4cc4
CJ
387 {
388 typedef BoundsContainer<T> ContainerType;
389 typedef std::bidirectional_iterator_tag iterator_category;
0a70fb87 390
278d4cc4 391 bidirectional_iterator_wrapper(T* _ptr, ContainerType* SharedInfo_in)
65be6ddd 392 : forward_iterator_wrapper<T>(_ptr, SharedInfo_in)
278d4cc4
CJ
393 { }
394
0a70fb87
JW
395 bidirectional_iterator_wrapper()
396 : forward_iterator_wrapper<T>()
278d4cc4
CJ
397 { }
398
0a70fb87
JW
399#if __cplusplus >= 201103L
400 bidirectional_iterator_wrapper(
401 const bidirectional_iterator_wrapper&) = default;
278d4cc4
CJ
402
403 bidirectional_iterator_wrapper&
0a70fb87
JW
404 operator=(const bidirectional_iterator_wrapper&) = default;
405#endif
f92ab29f 406
278d4cc4
CJ
407 bidirectional_iterator_wrapper&
408 operator++()
409 {
410 ITERATOR_VERIFY(this->SharedInfo && this->ptr < this->SharedInfo->last);
411 this->ptr++;
412 return *this;
413 }
414
415 bidirectional_iterator_wrapper
416 operator++(int)
417 {
418 bidirectional_iterator_wrapper<T> tmp = *this;
419 ++*this;
420 return tmp;
421 }
422
f92ab29f 423 bidirectional_iterator_wrapper&
278d4cc4
CJ
424 operator--()
425 {
426 ITERATOR_VERIFY(this->SharedInfo && this->ptr > this->SharedInfo->first);
427 this->ptr--;
428 return *this;
429 }
430
431 bidirectional_iterator_wrapper
432 operator--(int)
f92ab29f 433 {
278d4cc4
CJ
434 bidirectional_iterator_wrapper<T> tmp = *this;
435 --*this;
436 return tmp;
437 }
f970a17d 438 };
278d4cc4
CJ
439
440 /**
441 * @brief random_access_iterator wrapper for pointer
f92ab29f 442 *
278d4cc4 443 * This class takes a pointer and wraps it to provide exactly
ac2dca4d 444 * the requirements of a random_access_iterator. It should not be
f7fbb003 445 * instantiated directly, but generated from a test_container
278d4cc4
CJ
446 */
447 template<class T>
f92ab29f 448 struct random_access_iterator_wrapper
65be6ddd 449 : public bidirectional_iterator_wrapper<T>
278d4cc4
CJ
450 {
451 typedef BoundsContainer<T> ContainerType;
452 typedef std::random_access_iterator_tag iterator_category;
0a70fb87 453
278d4cc4 454 random_access_iterator_wrapper(T* _ptr, ContainerType* SharedInfo_in)
65be6ddd 455 : bidirectional_iterator_wrapper<T>(_ptr, SharedInfo_in)
278d4cc4
CJ
456 { }
457
0a70fb87
JW
458 random_access_iterator_wrapper()
459 : bidirectional_iterator_wrapper<T>()
278d4cc4
CJ
460 { }
461
0a70fb87
JW
462#if __cplusplus >= 201103L
463 random_access_iterator_wrapper(
464 const random_access_iterator_wrapper&) = default;
278d4cc4
CJ
465
466 random_access_iterator_wrapper&
0a70fb87
JW
467 operator=(const random_access_iterator_wrapper&) = default;
468#endif
278d4cc4
CJ
469
470 random_access_iterator_wrapper&
471 operator++()
472 {
473 ITERATOR_VERIFY(this->SharedInfo && this->ptr < this->SharedInfo->last);
474 this->ptr++;
475 return *this;
476 }
477
478 random_access_iterator_wrapper
479 operator++(int)
480 {
481 random_access_iterator_wrapper<T> tmp = *this;
482 ++*this;
483 return tmp;
484 }
485
486 random_access_iterator_wrapper&
487 operator--()
488 {
489 ITERATOR_VERIFY(this->SharedInfo && this->ptr > this->SharedInfo->first);
490 this->ptr--;
491 return *this;
492 }
493
494 random_access_iterator_wrapper
495 operator--(int)
496 {
497 random_access_iterator_wrapper<T> tmp = *this;
561e7a36 498 --*this;
278d4cc4
CJ
499 return tmp;
500 }
501
502 random_access_iterator_wrapper&
445877a9 503 operator+=(std::ptrdiff_t n)
278d4cc4
CJ
504 {
505 if(n > 0)
506 {
507 ITERATOR_VERIFY(n <= this->SharedInfo->last - this->ptr);
508 this->ptr += n;
509 }
510 else
511 {
e1008cd1 512 ITERATOR_VERIFY(-n <= this->ptr - this->SharedInfo->first);
278d4cc4
CJ
513 this->ptr += n;
514 }
515 return *this;
516 }
517
278d4cc4 518 random_access_iterator_wrapper&
445877a9 519 operator-=(std::ptrdiff_t n)
278d4cc4
CJ
520 { return *this += -n; }
521
522 random_access_iterator_wrapper
445877a9 523 operator-(std::ptrdiff_t n) const
278d4cc4
CJ
524 {
525 random_access_iterator_wrapper<T> tmp = *this;
526 return tmp -= n;
527 }
528
445877a9 529 std::ptrdiff_t
561e7a36 530 operator-(const random_access_iterator_wrapper<T>& in) const
278d4cc4
CJ
531 {
532 ITERATOR_VERIFY(this->SharedInfo == in.SharedInfo);
533 return this->ptr - in.ptr;
534 }
535
536 T&
445877a9 537 operator[](std::ptrdiff_t n) const
561e7a36 538 { return *(*this + n); }
278d4cc4
CJ
539
540 bool
541 operator<(const random_access_iterator_wrapper<T>& in) const
542 {
543 ITERATOR_VERIFY(this->SharedInfo == in.SharedInfo);
544 return this->ptr < in.ptr;
545 }
546
547 bool
548 operator>(const random_access_iterator_wrapper<T>& in) const
549 {
550 return in < *this;
551 }
552
553 bool
554 operator>=(const random_access_iterator_wrapper<T>& in) const
555 {
556 return !(*this < in);
557 }
558
f92ab29f 559 bool
278d4cc4
CJ
560 operator<=(const random_access_iterator_wrapper<T>& in) const
561 {
562 return !(*this > in);
563 }
f970a17d 564 };
278d4cc4 565
561e7a36
PC
566 template<typename T>
567 random_access_iterator_wrapper<T>
445877a9 568 operator+(random_access_iterator_wrapper<T> it, std::ptrdiff_t n)
561e7a36
PC
569 { return it += n; }
570
571 template<typename T>
572 random_access_iterator_wrapper<T>
f92ab29f 573 operator+(std::ptrdiff_t n, random_access_iterator_wrapper<T> it)
561e7a36
PC
574 { return it += n; }
575
278d4cc4 576
f92ab29f 577 /**
278d4cc4
CJ
578 * @brief A container-type class for holding iterator wrappers
579 * test_container takes two parameters, a class T and an iterator
580 * wrapper templated by T (for example forward_iterator_wrapper<T>.
f92ab29f 581 * It takes two pointers representing a range and presents them as
278d4cc4
CJ
582 * a container of iterators.
583 */
060269c4 584 template <class T, template<class TT> class ItType>
278d4cc4
CJ
585 struct test_container
586 {
587 typename ItType<T>::ContainerType bounds;
9921ac3d 588
4e66b02b 589 test_container(T* _first, T* _last) : bounds(_first, _last)
278d4cc4
CJ
590 { }
591
3ebacabd 592#if __cplusplus >= 201103L
4e66b02b
JW
593 template<std::size_t N>
594 explicit
595 test_container(T (&arr)[N]) : test_container(arr, arr+N)
596 { }
3ebacabd
JW
597#endif
598
278d4cc4
CJ
599 ItType<T>
600 it(int pos)
601 {
13feb023 602 ITERATOR_VERIFY(pos >= 0 && (unsigned)pos <= size());
278d4cc4
CJ
603 return ItType<T>(bounds.first + pos, &bounds);
604 }
605
606 ItType<T>
607 it(T* pos)
608 {
609 ITERATOR_VERIFY(pos >= bounds.first && pos <= bounds.last);
610 return ItType<T>(pos, &bounds);
611 }
612
c2240038
CJ
613 const T&
614 val(int pos)
615 { return (bounds.first)[pos]; }
616
278d4cc4
CJ
617 ItType<T>
618 begin()
619 { return it(bounds.first); }
620
621 ItType<T>
622 end()
623 { return it(bounds.last); }
ed920373
JW
624
625 std::size_t
626 size() const
9921ac3d 627 { return bounds.size(); }
4e66b02b 628 };
6d0dff49 629
e1008cd1
JW
630#if __cplusplus >= 201103L
631 template<typename T>
632 using output_container
633 = test_container<T, output_iterator_wrapper>;
634
635 template<typename T>
636 using input_container
637 = test_container<T, input_iterator_wrapper>;
638
639 template<typename T>
640 using forward_container
641 = test_container<T, forward_iterator_wrapper>;
642
643 template<typename T>
644 using bidirectional_container
645 = test_container<T, bidirectional_iterator_wrapper>;
646
647 template<typename T>
648 using random_access_container
649 = test_container<T, random_access_iterator_wrapper>;
650#endif
651
6d0dff49
JW
652#if __cplusplus > 201703L
653 template<typename T>
654 struct contiguous_iterator_wrapper
655 : random_access_iterator_wrapper<T>
656 {
657 using random_access_iterator_wrapper<T>::random_access_iterator_wrapper;
658
659 using iterator_concept = std::contiguous_iterator_tag;
660
661 contiguous_iterator_wrapper&
662 operator++()
663 {
664 random_access_iterator_wrapper<T>::operator++();
665 return *this;
666 }
667
668 contiguous_iterator_wrapper&
669 operator--()
670 {
671 random_access_iterator_wrapper<T>::operator--();
672 return *this;
673 }
674
675 contiguous_iterator_wrapper
676 operator++(int)
677 {
678 auto tmp = *this;
679 ++*this;
680 return tmp;
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+=(std::ptrdiff_t n)
693 {
694 random_access_iterator_wrapper<T>::operator+=(n);
695 return *this;
696 }
697
698 friend contiguous_iterator_wrapper
699 operator+(contiguous_iterator_wrapper iter, std::ptrdiff_t n)
700 { return iter += n; }
701
702 friend contiguous_iterator_wrapper
703 operator+(std::ptrdiff_t n, contiguous_iterator_wrapper iter)
704 { return iter += n; }
705
706 contiguous_iterator_wrapper&
707 operator-=(std::ptrdiff_t n)
708 { return *this += -n; }
709
710 friend contiguous_iterator_wrapper
711 operator-(contiguous_iterator_wrapper iter, std::ptrdiff_t n)
712 { return iter -= n; }
713 };
714
e1008cd1
JW
715 template<typename T>
716 using contiguous_container
717 = test_container<T, contiguous_iterator_wrapper>;
718
d6d4b339
PP
719 // A move-only input iterator type.
720 template<typename T>
721 struct input_iterator_wrapper_nocopy : input_iterator_wrapper<T>
722 {
723 using input_iterator_wrapper<T>::input_iterator_wrapper;
724
725 input_iterator_wrapper_nocopy()
726 : input_iterator_wrapper<T>(nullptr, nullptr)
727 { }
728
729 input_iterator_wrapper_nocopy(const input_iterator_wrapper_nocopy&) = delete;
730 input_iterator_wrapper_nocopy&
731 operator=(const input_iterator_wrapper_nocopy&) = delete;
732
733 input_iterator_wrapper_nocopy(input_iterator_wrapper_nocopy&&) = default;
734 input_iterator_wrapper_nocopy&
735 operator=(input_iterator_wrapper_nocopy&&) = default;
736
737 using input_iterator_wrapper<T>::operator++;
738
739 input_iterator_wrapper_nocopy&
740 operator++()
741 {
742 input_iterator_wrapper<T>::operator++();
743 return *this;
744 }
745 };
746
6d0dff49
JW
747 // A type meeting the minimum std::range requirements
748 template<typename T, template<typename> class Iter>
749 class test_range
750 {
4512b7d8
PP
751 // Exposes the protected default constructor of Iter<T> if needed. This
752 // is needed only when Iter is input_iterator_wrapper or
753 // output_iterator_wrapper, because legacy forward iterators and beyond
754 // are already default constructible.
6d0dff49
JW
755 struct iterator : Iter<T>
756 {
757 using Iter<T>::Iter;
758
6d0dff49
JW
759 using Iter<T>::operator++;
760
761 iterator& operator++() { Iter<T>::operator++(); return *this; }
762 };
763
764 template<typename I>
765 struct sentinel
766 {
767 T* end;
768
5cd2e126 769 friend bool operator==(const sentinel& s, const I& i) noexcept
6d0dff49 770 { return s.end == i.ptr; }
5cd2e126
JW
771
772 friend auto operator-(const sentinel& s, const I& i) noexcept
773 requires std::random_access_iterator<I>
774 { return s.end - i.ptr; }
775
776 friend auto operator-(const I& i, const sentinel& s) noexcept
777 requires std::random_access_iterator<I>
778 { return i.ptr - s.end; }
6d0dff49
JW
779 };
780
26af9cd8 781 protected:
6d0dff49
JW
782 auto
783 get_iterator(T* p)
784 {
a31517cb 785 if constexpr (std::default_initializable<Iter<T>>)
6d0dff49
JW
786 return Iter<T>(p, &bounds);
787 else
788 return iterator(p, &bounds);
789 }
790
791 public:
792 test_range(T* first, T* last) : bounds(first, last)
793 { }
794
795 template<std::size_t N>
796 explicit
797 test_range(T (&arr)[N]) : test_range(arr, arr+N)
798 { }
799
800 auto begin() & { return get_iterator(bounds.first); }
801
802 auto end() &
803 {
804 using I = decltype(get_iterator(bounds.last));
6e5a1963 805 return sentinel<I>{bounds.last};
6d0dff49
JW
806 }
807
808 typename Iter<T>::ContainerType bounds;
809 };
810
328b52d6
JW
811 template<typename T>
812 using test_contiguous_range
813 = test_range<T, contiguous_iterator_wrapper>;
814 template<typename T>
815 using test_random_access_range
816 = test_range<T, random_access_iterator_wrapper>;
817 template<typename T>
818 using test_bidirectional_range
819 = test_range<T, bidirectional_iterator_wrapper>;
820 template<typename T>
821 using test_forward_range
822 = test_range<T, forward_iterator_wrapper>;
823 template<typename T>
824 using test_input_range
825 = test_range<T, input_iterator_wrapper>;
826 template<typename T>
827 using test_output_range
828 = test_range<T, output_iterator_wrapper>;
829
6d0dff49
JW
830 // A type meeting the minimum std::sized_range requirements
831 template<typename T, template<typename> class Iter>
832 struct test_sized_range : test_range<T, Iter>
833 {
834 using test_range<T, Iter>::test_range;
835
836 std::size_t size() const noexcept
837 { return this->bounds.size(); }
838 };
328b52d6
JW
839
840 template<typename T>
841 using test_contiguous_sized_range
842 = test_sized_range<T, contiguous_iterator_wrapper>;
843 template<typename T>
844 using test_random_access_sized_range
845 = test_sized_range<T, random_access_iterator_wrapper>;
846 template<typename T>
847 using test_bidirectional_sized_range
848 = test_sized_range<T, bidirectional_iterator_wrapper>;
849 template<typename T>
850 using test_forward_sized_range
851 = test_sized_range<T, forward_iterator_wrapper>;
852 template<typename T>
853 using test_input_sized_range
854 = test_sized_range<T, input_iterator_wrapper>;
855 template<typename T>
856 using test_output_sized_range
857 = test_sized_range<T, output_iterator_wrapper>;
b5b2e387 858
26af9cd8
PP
859 // A type meeting the minimum std::sized_range requirements, and whose end()
860 // returns a sized sentinel.
861 template<typename T, template<typename> class Iter>
862 struct test_sized_range_sized_sent : test_sized_range<T, Iter>
863 {
864 using test_sized_range<T, Iter>::test_sized_range;
865
866 template<typename I>
867 struct sentinel
868 {
869 T* end;
870
871 friend bool operator==(const sentinel& s, const I& i) noexcept
872 { return s.end == i.ptr; }
873
874 friend std::iter_difference_t<I>
875 operator-(const sentinel& s, const I& i) noexcept
876 { return s.end - i.ptr; }
877
878 friend std::iter_difference_t<I>
879 operator-(const I& i, const sentinel& s) noexcept
880 { return i.ptr - s.end; }
881 };
882
883 auto end() &
884 {
885 using I = decltype(this->get_iterator(this->bounds.last));
886 return sentinel<I>{this->bounds.last};
887 }
888 };
889
68be73fc 890// test_range and test_sized_range do not own their elements, so they model
15411a64
JW
891// std::ranges::borrowed_range. This file does not define specializations of
892// std::ranges::enable_borrowed_range, so that individual tests can decide
68be73fc
JW
893// whether or not to do so.
894// This is also true for test_container, although only when it has forward
895// iterators (because output_iterator_wrapper and input_iterator_wrapper are
896// not default constructible so do not model std::input_or_output_iterator).
6d0dff49
JW
897#endif // C++20
898} // namespace __gnu_test
899#endif // _TESTSUITE_ITERATORS