]> git.ipfire.org Git - thirdparty/gcc.git/blob - libstdc++-v3/testsuite/util/testsuite_iterators.h
Fix typo in preprocessor check
[thirdparty/gcc.git] / libstdc++-v3 / testsuite / util / testsuite_iterators.h
1 // -*- C++ -*-
2 // Iterator Wrappers for the C++ library testsuite.
3 //
4 // Copyright (C) 2004-2019 Free Software Foundation, Inc.
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
9 // Free Software Foundation; either version 3, or (at your option)
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
18 // with this library; see the file COPYING3. If not see
19 // <http://www.gnu.org/licenses/>.
20 //
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>
31 #include <bits/stl_iterator_base_types.h>
32
33 #if __cplusplus >= 201103L
34 #include <bits/move.h>
35 #endif
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
46 namespace __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;
59
60 BoundsContainer(T* _first, T* _last) : first(_first), last(_last)
61 { }
62
63 std::size_t size() const { return last - first; }
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;
72
73 OutputContainer(T* _first, T* _last)
74 : BoundsContainer<T>(_first, _last), incrementedto(_first),
75 writtento(new bool[this->size()]())
76 { }
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;
90
91 WritableObject(T* ptr_in, OutputContainer<T>* SharedInfo_in):
92 ptr(ptr_in), SharedInfo(SharedInfo_in)
93 { }
94
95 #if __cplusplus >= 201103L
96 template<class U>
97 typename std::enable_if<std::is_assignable<T&, U>::value>::type
98 operator=(U&& new_val)
99 {
100 ITERATOR_VERIFY(SharedInfo->writtento[ptr - SharedInfo->first] == 0);
101 SharedInfo->writtento[ptr - SharedInfo->first] = 1;
102 *ptr = std::forward<U>(new_val);
103 }
104 #else
105 template<class U>
106 void
107 operator=(const U& new_val)
108 {
109 ITERATOR_VERIFY(SharedInfo->writtento[ptr - SharedInfo->first] == 0);
110 SharedInfo->writtento[ptr - SharedInfo->first] = 1;
111 *ptr = new_val;
112 }
113 #endif
114 };
115
116 /**
117 * @brief output_iterator wrapper for pointer
118 *
119 * This class takes a pointer and wraps it to provide exactly
120 * the requirements of a output_iterator. It should not be
121 * instantiated directly, but generated from a test_container
122 */
123 template<class T>
124 struct output_iterator_wrapper
125 : public std::iterator<std::output_iterator_tag, T, std::ptrdiff_t, T*, T&>
126 {
127 typedef OutputContainer<T> ContainerType;
128 T* ptr;
129 ContainerType* SharedInfo;
130
131 output_iterator_wrapper(T* _ptr, ContainerType* SharedInfo_in)
132 : ptr(_ptr), SharedInfo(SharedInfo_in)
133 {
134 ITERATOR_VERIFY(ptr >= SharedInfo->first && ptr <= SharedInfo->last);
135 }
136
137 #if __cplusplus >= 201103L
138 output_iterator_wrapper() = delete;
139
140 output_iterator_wrapper(const output_iterator_wrapper&) = default;
141
142 output_iterator_wrapper&
143 operator=(const output_iterator_wrapper&) = default;
144 #endif
145
146 WritableObject<T>
147 operator*() const
148 {
149 ITERATOR_VERIFY(ptr < SharedInfo->last);
150 ITERATOR_VERIFY(SharedInfo->writtento[ptr - SharedInfo->first] == false);
151 return WritableObject<T>(ptr, SharedInfo);
152 }
153
154 output_iterator_wrapper&
155 operator++()
156 {
157 ITERATOR_VERIFY(SharedInfo && ptr < SharedInfo->last);
158 ITERATOR_VERIFY(ptr>=SharedInfo->incrementedto);
159 ptr++;
160 SharedInfo->incrementedto=ptr;
161 return *this;
162 }
163
164 output_iterator_wrapper
165 operator++(int)
166 {
167 output_iterator_wrapper<T> tmp = *this;
168 ++*this;
169 return tmp;
170 }
171
172 #if __cplusplus >= 201103L
173 template<typename U>
174 void operator,(const U&) const = delete;
175 #else
176 private:
177 template<typename U>
178 void operator,(const U&) const;
179 #endif
180 };
181
182 #if __cplusplus >= 201103L
183 template<typename T, typename U>
184 void operator,(const T&, const output_iterator_wrapper<U>&) = delete;
185 #endif
186
187 #if __cplusplus >= 201103L
188 using std::remove_cv;
189 #else
190 template<typename T> struct remove_cv { typedef T type; };
191 template<typename T> struct remove_cv<const T> { typedef T type; };
192 template<typename T> struct remove_cv<volatile T> { typedef T type; };
193 template<typename T> struct remove_cv<const volatile T> { typedef T type; };
194 #endif
195
196 /**
197 * @brief input_iterator wrapper for pointer
198 *
199 * This class takes a pointer and wraps it to provide exactly
200 * the requirements of a input_iterator. It should not be
201 * instantiated directly, but generated from a test_container
202 */
203 template<class T>
204 class input_iterator_wrapper
205 : public std::iterator<std::input_iterator_tag, typename remove_cv<T>::type,
206 std::ptrdiff_t, T*, T&>
207 {
208 protected:
209 input_iterator_wrapper() : ptr(0), SharedInfo(0)
210 { }
211
212 public:
213 typedef BoundsContainer<T> ContainerType;
214 T* ptr;
215 ContainerType* SharedInfo;
216
217 input_iterator_wrapper(T* _ptr, ContainerType* SharedInfo_in)
218 : ptr(_ptr), SharedInfo(SharedInfo_in)
219 { ITERATOR_VERIFY(ptr >= SharedInfo->first && ptr <= SharedInfo->last); }
220
221 #if __cplusplus >= 201103L
222 input_iterator_wrapper(const input_iterator_wrapper&) = default;
223
224 input_iterator_wrapper&
225 operator=(const input_iterator_wrapper&) = default;
226 #endif
227
228 bool
229 operator==(const input_iterator_wrapper& in) const
230 {
231 ITERATOR_VERIFY(SharedInfo && SharedInfo == in.SharedInfo);
232 ITERATOR_VERIFY(ptr>=SharedInfo->first && in.ptr>=SharedInfo->first);
233 return ptr == in.ptr;
234 }
235
236 bool
237 operator!=(const input_iterator_wrapper& in) const
238 {
239 return !(*this == in);
240 }
241
242 T&
243 operator*() const
244 {
245 ITERATOR_VERIFY(SharedInfo && ptr < SharedInfo->last);
246 ITERATOR_VERIFY(ptr >= SharedInfo->first);
247 return *ptr;
248 }
249
250 T*
251 operator->() const
252 {
253 return &**this;
254 }
255
256 input_iterator_wrapper&
257 operator++()
258 {
259 ITERATOR_VERIFY(SharedInfo && ptr < SharedInfo->last);
260 ITERATOR_VERIFY(ptr>=SharedInfo->first);
261 ptr++;
262 SharedInfo->first=ptr;
263 return *this;
264 }
265
266 void
267 operator++(int)
268 {
269 ++*this;
270 }
271
272 #if __cplusplus >= 201103L
273 template<typename U>
274 void operator,(const U&) const = delete;
275 #else
276 private:
277 template<typename U>
278 void operator,(const U&) const;
279 #endif
280 };
281
282 #if __cplusplus >= 201103L
283 template<typename T, typename U>
284 void operator,(const T&, const input_iterator_wrapper<U>&) = delete;
285 #endif
286
287 /**
288 * @brief forward_iterator wrapper for pointer
289 *
290 * This class takes a pointer and wraps it to provide exactly
291 * the requirements of a forward_iterator. It should not be
292 * instantiated directly, but generated from a test_container
293 */
294 template<class T>
295 struct forward_iterator_wrapper : public input_iterator_wrapper<T>
296 {
297 typedef BoundsContainer<T> ContainerType;
298 typedef std::forward_iterator_tag iterator_category;
299
300 forward_iterator_wrapper(T* _ptr, ContainerType* SharedInfo_in)
301 : input_iterator_wrapper<T>(_ptr, SharedInfo_in)
302 { }
303
304 forward_iterator_wrapper()
305 { }
306
307 #if __cplusplus >= 201103L
308 forward_iterator_wrapper(const forward_iterator_wrapper&) = default;
309
310 forward_iterator_wrapper&
311 operator=(const forward_iterator_wrapper&) = default;
312 #endif
313
314 T&
315 operator*() const
316 {
317 ITERATOR_VERIFY(this->SharedInfo && this->ptr < this->SharedInfo->last);
318 return *(this->ptr);
319 }
320
321 T*
322 operator->() const
323 { return &**this; }
324
325 forward_iterator_wrapper&
326 operator++()
327 {
328 ITERATOR_VERIFY(this->SharedInfo && this->ptr < this->SharedInfo->last);
329 this->ptr++;
330 return *this;
331 }
332
333 forward_iterator_wrapper
334 operator++(int)
335 {
336 forward_iterator_wrapper<T> tmp = *this;
337 ++*this;
338 return tmp;
339 }
340 };
341
342 /**
343 * @brief bidirectional_iterator wrapper for pointer
344 *
345 * This class takes a pointer and wraps it to provide exactly
346 * the requirements of a bidirectional_iterator. It should not be
347 * instantiated directly, but generated from a test_container
348 */
349 template<class T>
350 struct bidirectional_iterator_wrapper : public forward_iterator_wrapper<T>
351 {
352 typedef BoundsContainer<T> ContainerType;
353 typedef std::bidirectional_iterator_tag iterator_category;
354
355 bidirectional_iterator_wrapper(T* _ptr, ContainerType* SharedInfo_in)
356 : forward_iterator_wrapper<T>(_ptr, SharedInfo_in)
357 { }
358
359 bidirectional_iterator_wrapper()
360 : forward_iterator_wrapper<T>()
361 { }
362
363 #if __cplusplus >= 201103L
364 bidirectional_iterator_wrapper(
365 const bidirectional_iterator_wrapper&) = default;
366
367 bidirectional_iterator_wrapper&
368 operator=(const bidirectional_iterator_wrapper&) = default;
369 #endif
370
371 bidirectional_iterator_wrapper&
372 operator++()
373 {
374 ITERATOR_VERIFY(this->SharedInfo && this->ptr < this->SharedInfo->last);
375 this->ptr++;
376 return *this;
377 }
378
379 bidirectional_iterator_wrapper
380 operator++(int)
381 {
382 bidirectional_iterator_wrapper<T> tmp = *this;
383 ++*this;
384 return tmp;
385 }
386
387 bidirectional_iterator_wrapper&
388 operator--()
389 {
390 ITERATOR_VERIFY(this->SharedInfo && this->ptr > this->SharedInfo->first);
391 this->ptr--;
392 return *this;
393 }
394
395 bidirectional_iterator_wrapper
396 operator--(int)
397 {
398 bidirectional_iterator_wrapper<T> tmp = *this;
399 --*this;
400 return tmp;
401 }
402 };
403
404 /**
405 * @brief random_access_iterator wrapper for pointer
406 *
407 * This class takes a pointer and wraps it to provide exactly
408 * the requirements of a random_access_iterator. It should not be
409 * instantiated directly, but generated from a test_container
410 */
411 template<class T>
412 struct random_access_iterator_wrapper
413 : public bidirectional_iterator_wrapper<T>
414 {
415 typedef BoundsContainer<T> ContainerType;
416 typedef std::random_access_iterator_tag iterator_category;
417
418 random_access_iterator_wrapper(T* _ptr, ContainerType* SharedInfo_in)
419 : bidirectional_iterator_wrapper<T>(_ptr, SharedInfo_in)
420 { }
421
422 random_access_iterator_wrapper()
423 : bidirectional_iterator_wrapper<T>()
424 { }
425
426 #if __cplusplus >= 201103L
427 random_access_iterator_wrapper(
428 const random_access_iterator_wrapper&) = default;
429
430 random_access_iterator_wrapper&
431 operator=(const random_access_iterator_wrapper&) = default;
432 #endif
433
434 random_access_iterator_wrapper&
435 operator++()
436 {
437 ITERATOR_VERIFY(this->SharedInfo && this->ptr < this->SharedInfo->last);
438 this->ptr++;
439 return *this;
440 }
441
442 random_access_iterator_wrapper
443 operator++(int)
444 {
445 random_access_iterator_wrapper<T> tmp = *this;
446 ++*this;
447 return tmp;
448 }
449
450 random_access_iterator_wrapper&
451 operator--()
452 {
453 ITERATOR_VERIFY(this->SharedInfo && this->ptr > this->SharedInfo->first);
454 this->ptr--;
455 return *this;
456 }
457
458 random_access_iterator_wrapper
459 operator--(int)
460 {
461 random_access_iterator_wrapper<T> tmp = *this;
462 --*this;
463 return tmp;
464 }
465
466 random_access_iterator_wrapper&
467 operator+=(std::ptrdiff_t n)
468 {
469 if(n > 0)
470 {
471 ITERATOR_VERIFY(n <= this->SharedInfo->last - this->ptr);
472 this->ptr += n;
473 }
474 else
475 {
476 ITERATOR_VERIFY(n <= this->ptr - this->SharedInfo->first);
477 this->ptr += n;
478 }
479 return *this;
480 }
481
482 random_access_iterator_wrapper&
483 operator-=(std::ptrdiff_t n)
484 { return *this += -n; }
485
486 random_access_iterator_wrapper
487 operator-(std::ptrdiff_t n) const
488 {
489 random_access_iterator_wrapper<T> tmp = *this;
490 return tmp -= n;
491 }
492
493 std::ptrdiff_t
494 operator-(const random_access_iterator_wrapper<T>& in) const
495 {
496 ITERATOR_VERIFY(this->SharedInfo == in.SharedInfo);
497 return this->ptr - in.ptr;
498 }
499
500 T&
501 operator[](std::ptrdiff_t n) const
502 { return *(*this + n); }
503
504 bool
505 operator<(const random_access_iterator_wrapper<T>& in) const
506 {
507 ITERATOR_VERIFY(this->SharedInfo == in.SharedInfo);
508 return this->ptr < in.ptr;
509 }
510
511 bool
512 operator>(const random_access_iterator_wrapper<T>& in) const
513 {
514 return in < *this;
515 }
516
517 bool
518 operator>=(const random_access_iterator_wrapper<T>& in) const
519 {
520 return !(*this < in);
521 }
522
523 bool
524 operator<=(const random_access_iterator_wrapper<T>& in) const
525 {
526 return !(*this > in);
527 }
528 };
529
530 template<typename T>
531 random_access_iterator_wrapper<T>
532 operator+(random_access_iterator_wrapper<T> it, std::ptrdiff_t n)
533 { return it += n; }
534
535 template<typename T>
536 random_access_iterator_wrapper<T>
537 operator+(std::ptrdiff_t n, random_access_iterator_wrapper<T> it)
538 { return it += n; }
539
540
541 /**
542 * @brief A container-type class for holding iterator wrappers
543 * test_container takes two parameters, a class T and an iterator
544 * wrapper templated by T (for example forward_iterator_wrapper<T>.
545 * It takes two pointers representing a range and presents them as
546 * a container of iterators.
547 */
548 template <class T, template<class TT> class ItType>
549 struct test_container
550 {
551 typename ItType<T>::ContainerType bounds;
552
553 test_container(T* _first, T* _last) : bounds(_first, _last)
554 { }
555
556 #if __cplusplus >= 201103L
557 template<std::size_t N>
558 explicit
559 test_container(T (&arr)[N]) : test_container(arr, arr+N)
560 { }
561 #endif
562
563 ItType<T>
564 it(int pos)
565 {
566 ITERATOR_VERIFY(pos >= 0 && pos <= size());
567 return ItType<T>(bounds.first + pos, &bounds);
568 }
569
570 ItType<T>
571 it(T* pos)
572 {
573 ITERATOR_VERIFY(pos >= bounds.first && pos <= bounds.last);
574 return ItType<T>(pos, &bounds);
575 }
576
577 const T&
578 val(int pos)
579 { return (bounds.first)[pos]; }
580
581 ItType<T>
582 begin()
583 { return it(bounds.first); }
584
585 ItType<T>
586 end()
587 { return it(bounds.last); }
588
589 std::size_t
590 size() const
591 { return bounds.size(); }
592 };
593
594 #if __cplusplus > 201703L
595 template<typename T>
596 struct contiguous_iterator_wrapper
597 : random_access_iterator_wrapper<T>
598 {
599 using random_access_iterator_wrapper<T>::random_access_iterator_wrapper;
600
601 using iterator_concept = std::contiguous_iterator_tag;
602
603 contiguous_iterator_wrapper&
604 operator++()
605 {
606 random_access_iterator_wrapper<T>::operator++();
607 return *this;
608 }
609
610 contiguous_iterator_wrapper&
611 operator--()
612 {
613 random_access_iterator_wrapper<T>::operator--();
614 return *this;
615 }
616
617 contiguous_iterator_wrapper
618 operator++(int)
619 {
620 auto tmp = *this;
621 ++*this;
622 return tmp;
623 }
624
625 contiguous_iterator_wrapper
626 operator--(int)
627 {
628 auto tmp = *this;
629 --*this;
630 return tmp;
631 }
632
633 contiguous_iterator_wrapper&
634 operator+=(std::ptrdiff_t n)
635 {
636 random_access_iterator_wrapper<T>::operator+=(n);
637 return *this;
638 }
639
640 friend contiguous_iterator_wrapper
641 operator+(contiguous_iterator_wrapper iter, std::ptrdiff_t n)
642 { return iter += n; }
643
644 friend contiguous_iterator_wrapper
645 operator+(std::ptrdiff_t n, contiguous_iterator_wrapper iter)
646 { return iter += n; }
647
648 contiguous_iterator_wrapper&
649 operator-=(std::ptrdiff_t n)
650 { return *this += -n; }
651
652 friend contiguous_iterator_wrapper
653 operator-(contiguous_iterator_wrapper iter, std::ptrdiff_t n)
654 { return iter -= n; }
655 };
656
657 // A type meeting the minimum std::range requirements
658 template<typename T, template<typename> class Iter>
659 class test_range
660 {
661 // Adds default constructor to Iter<T> if needed
662 struct iterator : Iter<T>
663 {
664 using Iter<T>::Iter;
665
666 iterator() : Iter<T>(nullptr, nullptr) { }
667
668 using Iter<T>::operator++;
669
670 iterator& operator++() { Iter<T>::operator++(); return *this; }
671 };
672
673 template<typename I>
674 struct sentinel
675 {
676 T* end;
677
678 friend bool operator==(const sentinel& s, const I& i)
679 { return s.end == i.ptr; }
680
681 friend bool operator!=(const sentinel& s, const I& i)
682 { return !(s == i); }
683
684 friend bool operator==(const I& i, const sentinel& s)
685 { return s == i; }
686
687 friend bool operator!=(const I& i, const sentinel& s)
688 { return !(s == i); }
689 };
690
691 auto
692 get_iterator(T* p)
693 {
694 if constexpr (std::default_constructible<Iter<T>>)
695 return Iter<T>(p, &bounds);
696 else
697 return iterator(p, &bounds);
698 }
699
700 public:
701 test_range(T* first, T* last) : bounds(first, last)
702 { }
703
704 template<std::size_t N>
705 explicit
706 test_range(T (&arr)[N]) : test_range(arr, arr+N)
707 { }
708
709 auto begin() & { return get_iterator(bounds.first); }
710
711 auto end() &
712 {
713 using I = decltype(get_iterator(bounds.last));
714 if constexpr (std::sentinel_for<I, I>)
715 return get_iterator(bounds.last);
716 else
717 return sentinel<I>{bounds.last};
718 }
719
720 typename Iter<T>::ContainerType bounds;
721 };
722
723 // A type meeting the minimum std::sized_range requirements
724 template<typename T, template<typename> class Iter>
725 struct test_sized_range : test_range<T, Iter>
726 {
727 using test_range<T, Iter>::test_range;
728
729 std::size_t size() const noexcept
730 { return this->bounds.size(); }
731 };
732 #endif // C++20
733 } // namespace __gnu_test
734 #endif // _TESTSUITE_ITERATORS