[committed] [RISC-V] Fix false-positive uninitialized variable
[official-gcc.git] / libstdc++-v3 / testsuite / util / testsuite_iterators.h
blobec2971284b4cb8cf372938456ff42166132bebc0
1 // -*- C++ -*-
2 // Iterator Wrappers for the C++ library testsuite.
3 //
4 // Copyright (C) 2004-2024 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.
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.
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/>.
22 // This file provides the following:
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.
30 #include <testsuite_hooks.h>
31 #include <bits/stl_iterator_base_types.h>
33 #if __cplusplus >= 201103L
34 #include <bits/move.h>
35 #endif
37 #ifndef _TESTSUITE_ITERATORS
38 #define _TESTSUITE_ITERATORS
40 #ifdef DISABLE_ITERATOR_DEBUG
41 #define ITERATOR_VERIFY(x)
42 #else
43 #define ITERATOR_VERIFY(x) VERIFY(x)
44 #endif
46 namespace __gnu_test
48 /**
49 * @brief Simple container for holding two pointers.
51 * Note that input_iterator_wrapper changes first to denote
52 * how the valid range of == , ++, etc. change as the iterators are used.
54 template<typename T>
55 struct BoundsContainer
57 T* first;
58 T* last;
60 BoundsContainer(T* _first, T* _last) : first(_first), last(_last)
61 { }
63 std::size_t size() const { return last - first; }
66 // Simple container for holding state of a set of output iterators.
67 template<typename T>
68 struct OutputContainer : public BoundsContainer<T>
70 T* incrementedto;
71 bool* writtento;
73 OutputContainer(T* _first, T* _last)
74 : BoundsContainer<T>(_first, _last), incrementedto(_first),
75 writtento(new bool[this->size()]())
76 { }
78 ~OutputContainer()
79 { delete[] writtento; }
82 // Produced by output_iterator to allow limited writing to pointer
83 template<class T>
84 class WritableObject
86 T* ptr;
88 public:
89 OutputContainer<T>* SharedInfo;
91 WritableObject(T* ptr_in, OutputContainer<T>* SharedInfo_in):
92 ptr(ptr_in), SharedInfo(SharedInfo_in)
93 { }
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) const
100 ITERATOR_VERIFY(SharedInfo->writtento[ptr - SharedInfo->first] == 0);
101 SharedInfo->writtento[ptr - SharedInfo->first] = 1;
102 *ptr = std::forward<U>(new_val);
104 #else
105 template<class U>
106 void
107 operator=(const U& new_val)
109 ITERATOR_VERIFY(SharedInfo->writtento[ptr - SharedInfo->first] == 0);
110 SharedInfo->writtento[ptr - SharedInfo->first] = 1;
111 *ptr = new_val;
113 #endif
117 * @brief output_iterator wrapper for pointer
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
123 template<class T>
124 struct output_iterator_wrapper
126 protected:
127 output_iterator_wrapper() : ptr(0), SharedInfo(0)
130 public:
131 typedef std::output_iterator_tag iterator_category;
132 typedef T value_type;
133 typedef std::ptrdiff_t difference_type;
134 typedef T* pointer;
135 typedef T& reference;
137 typedef OutputContainer<T> ContainerType;
138 T* ptr;
139 ContainerType* SharedInfo;
141 output_iterator_wrapper(T* _ptr, ContainerType* SharedInfo_in)
142 : ptr(_ptr), SharedInfo(SharedInfo_in)
144 ITERATOR_VERIFY(ptr >= SharedInfo->first && ptr <= SharedInfo->last);
147 #if __cplusplus >= 201103L
148 output_iterator_wrapper(const output_iterator_wrapper&) = default;
150 output_iterator_wrapper&
151 operator=(const output_iterator_wrapper&) = default;
152 #endif
154 WritableObject<T>
155 operator*() const
157 ITERATOR_VERIFY(ptr < SharedInfo->last);
158 ITERATOR_VERIFY(SharedInfo->writtento[ptr - SharedInfo->first] == false);
159 return WritableObject<T>(ptr, SharedInfo);
162 output_iterator_wrapper&
163 operator++()
165 ITERATOR_VERIFY(SharedInfo && ptr < SharedInfo->last);
166 ITERATOR_VERIFY(ptr>=SharedInfo->incrementedto);
167 ptr++;
168 SharedInfo->incrementedto=ptr;
169 return *this;
172 output_iterator_wrapper
173 operator++(int)
175 output_iterator_wrapper<T> tmp = *this;
176 ++*this;
177 return tmp;
180 #if __cplusplus >= 201103L
181 template<typename U>
182 void operator,(const U&) const = delete;
184 void operator&() const = delete;
185 #else
186 private:
187 template<typename U>
188 void operator,(const U&) const;
190 void operator&() const;
191 #endif
194 #if __cplusplus >= 201103L
195 template<typename T, typename U>
196 void operator,(const T&, const output_iterator_wrapper<U>&) = delete;
197 #endif
199 #if __cplusplus >= 201103L
200 using std::remove_cv;
201 #else
202 template<typename T> struct remove_cv { typedef T type; };
203 template<typename T> struct remove_cv<const T> { typedef T type; };
204 template<typename T> struct remove_cv<volatile T> { typedef T type; };
205 template<typename T> struct remove_cv<const volatile T> { typedef T type; };
206 #endif
209 * @brief input_iterator wrapper for pointer
211 * This class takes a pointer and wraps it to provide exactly
212 * the requirements of a input_iterator. It should not be
213 * instantiated directly, but generated from a test_container
215 template<class T>
216 class input_iterator_wrapper
218 struct post_inc_proxy
220 struct deref_proxy
222 T* ptr;
223 operator const T&() const { return *ptr; }
224 } p;
226 deref_proxy operator*() const { return p; }
229 protected:
230 input_iterator_wrapper() : ptr(0), SharedInfo(0)
233 public:
234 typedef std::input_iterator_tag iterator_category;
235 typedef typename remove_cv<T>::type value_type;
236 typedef std::ptrdiff_t difference_type;
237 typedef T* pointer;
238 typedef T& reference;
240 typedef BoundsContainer<T> ContainerType;
241 T* ptr;
242 ContainerType* SharedInfo;
244 input_iterator_wrapper(T* _ptr, ContainerType* SharedInfo_in)
245 : ptr(_ptr), SharedInfo(SharedInfo_in)
246 { ITERATOR_VERIFY(ptr >= SharedInfo->first && ptr <= SharedInfo->last); }
248 #if __cplusplus >= 201103L
249 input_iterator_wrapper(const input_iterator_wrapper&) = default;
251 input_iterator_wrapper&
252 operator=(const input_iterator_wrapper&) = default;
253 #endif
255 bool
256 operator==(const input_iterator_wrapper& in) const
258 ITERATOR_VERIFY(SharedInfo && SharedInfo == in.SharedInfo);
259 ITERATOR_VERIFY(ptr>=SharedInfo->first && in.ptr>=SharedInfo->first);
260 return ptr == in.ptr;
263 bool
264 operator!=(const input_iterator_wrapper& in) const
266 return !(*this == in);
270 operator*() const
272 ITERATOR_VERIFY(SharedInfo && ptr < SharedInfo->last);
273 ITERATOR_VERIFY(ptr >= SharedInfo->first);
274 return *ptr;
278 operator->() const
280 return &**this;
283 input_iterator_wrapper&
284 operator++()
286 ITERATOR_VERIFY(SharedInfo && ptr < SharedInfo->last);
287 ITERATOR_VERIFY(ptr>=SharedInfo->first);
288 ptr++;
289 SharedInfo->first=ptr;
290 return *this;
293 post_inc_proxy
294 operator++(int)
296 post_inc_proxy tmp = { { ptr } };
297 ++*this;
298 return tmp;
301 #if __cplusplus >= 201103L
302 template<typename U>
303 void operator,(const U&) const = delete;
305 void operator&() const = delete;
306 #else
307 private:
308 template<typename U>
309 void operator,(const U&) const;
311 void operator&() const;
312 #endif
315 #if __cplusplus >= 201103L
316 template<typename T, typename U>
317 void operator,(const T&, const input_iterator_wrapper<U>&) = delete;
318 #endif
321 * @brief forward_iterator wrapper for pointer
323 * This class takes a pointer and wraps it to provide exactly
324 * the requirements of a forward_iterator. It should not be
325 * instantiated directly, but generated from a test_container
327 template<class T>
328 struct forward_iterator_wrapper : public input_iterator_wrapper<T>
330 typedef BoundsContainer<T> ContainerType;
331 typedef std::forward_iterator_tag iterator_category;
333 forward_iterator_wrapper(T* _ptr, ContainerType* SharedInfo_in)
334 : input_iterator_wrapper<T>(_ptr, SharedInfo_in)
337 forward_iterator_wrapper()
340 #if __cplusplus >= 201103L
341 forward_iterator_wrapper(const forward_iterator_wrapper&) = default;
343 forward_iterator_wrapper&
344 operator=(const forward_iterator_wrapper&) = default;
345 #endif
348 operator*() const
350 ITERATOR_VERIFY(this->SharedInfo && this->ptr < this->SharedInfo->last);
351 return *(this->ptr);
355 operator->() const
356 { return &**this; }
358 forward_iterator_wrapper&
359 operator++()
361 ITERATOR_VERIFY(this->SharedInfo && this->ptr < this->SharedInfo->last);
362 this->ptr++;
363 return *this;
366 forward_iterator_wrapper
367 operator++(int)
369 forward_iterator_wrapper<T> tmp = *this;
370 ++*this;
371 return tmp;
374 #if __cplusplus >= 201402L
375 bool
376 operator==(const forward_iterator_wrapper& it) const noexcept
378 // Since C++14 value-initialized forward iterators are comparable.
379 if (this->SharedInfo == nullptr || it.SharedInfo == nullptr)
380 return this->SharedInfo == it.SharedInfo && this->ptr == it.ptr;
382 const input_iterator_wrapper<T>& base_this = *this;
383 const input_iterator_wrapper<T>& base_that = it;
384 return base_this == base_that;
387 bool
388 operator!=(const forward_iterator_wrapper& it) const noexcept
390 return !(*this == it);
392 #endif
396 * @brief bidirectional_iterator wrapper for pointer
398 * This class takes a pointer and wraps it to provide exactly
399 * the requirements of a bidirectional_iterator. It should not be
400 * instantiated directly, but generated from a test_container
402 template<class T>
403 struct bidirectional_iterator_wrapper : public forward_iterator_wrapper<T>
405 typedef BoundsContainer<T> ContainerType;
406 typedef std::bidirectional_iterator_tag iterator_category;
408 bidirectional_iterator_wrapper(T* _ptr, ContainerType* SharedInfo_in)
409 : forward_iterator_wrapper<T>(_ptr, SharedInfo_in)
412 bidirectional_iterator_wrapper()
413 : forward_iterator_wrapper<T>()
416 #if __cplusplus >= 201103L
417 bidirectional_iterator_wrapper(
418 const bidirectional_iterator_wrapper&) = default;
420 bidirectional_iterator_wrapper&
421 operator=(const bidirectional_iterator_wrapper&) = default;
422 #endif
424 bidirectional_iterator_wrapper&
425 operator++()
427 ITERATOR_VERIFY(this->SharedInfo && this->ptr < this->SharedInfo->last);
428 this->ptr++;
429 return *this;
432 bidirectional_iterator_wrapper
433 operator++(int)
435 bidirectional_iterator_wrapper<T> tmp = *this;
436 ++*this;
437 return tmp;
440 bidirectional_iterator_wrapper&
441 operator--()
443 ITERATOR_VERIFY(this->SharedInfo && this->ptr > this->SharedInfo->first);
444 this->ptr--;
445 return *this;
448 bidirectional_iterator_wrapper
449 operator--(int)
451 bidirectional_iterator_wrapper<T> tmp = *this;
452 --*this;
453 return tmp;
458 * @brief random_access_iterator wrapper for pointer
460 * This class takes a pointer and wraps it to provide exactly
461 * the requirements of a random_access_iterator. It should not be
462 * instantiated directly, but generated from a test_container
464 template<class T>
465 struct random_access_iterator_wrapper
466 : public bidirectional_iterator_wrapper<T>
468 typedef BoundsContainer<T> ContainerType;
469 typedef std::random_access_iterator_tag iterator_category;
471 random_access_iterator_wrapper(T* _ptr, ContainerType* SharedInfo_in)
472 : bidirectional_iterator_wrapper<T>(_ptr, SharedInfo_in)
475 random_access_iterator_wrapper()
476 : bidirectional_iterator_wrapper<T>()
479 #if __cplusplus >= 201103L
480 random_access_iterator_wrapper(
481 const random_access_iterator_wrapper&) = default;
483 random_access_iterator_wrapper&
484 operator=(const random_access_iterator_wrapper&) = default;
485 #endif
487 random_access_iterator_wrapper&
488 operator++()
490 ITERATOR_VERIFY(this->SharedInfo && this->ptr < this->SharedInfo->last);
491 this->ptr++;
492 return *this;
495 random_access_iterator_wrapper
496 operator++(int)
498 random_access_iterator_wrapper<T> tmp = *this;
499 ++*this;
500 return tmp;
503 random_access_iterator_wrapper&
504 operator--()
506 ITERATOR_VERIFY(this->SharedInfo && this->ptr > this->SharedInfo->first);
507 this->ptr--;
508 return *this;
511 random_access_iterator_wrapper
512 operator--(int)
514 random_access_iterator_wrapper<T> tmp = *this;
515 --*this;
516 return tmp;
519 random_access_iterator_wrapper&
520 operator+=(std::ptrdiff_t n)
522 if(n > 0)
524 ITERATOR_VERIFY(n <= this->SharedInfo->last - this->ptr);
525 this->ptr += n;
527 else
529 ITERATOR_VERIFY(-n <= this->ptr - this->SharedInfo->first);
530 this->ptr += n;
532 return *this;
535 random_access_iterator_wrapper&
536 operator-=(std::ptrdiff_t n)
537 { return *this += -n; }
539 random_access_iterator_wrapper
540 operator-(std::ptrdiff_t n) const
542 random_access_iterator_wrapper<T> tmp = *this;
543 return tmp -= n;
546 std::ptrdiff_t
547 operator-(const random_access_iterator_wrapper<T>& in) const
549 ITERATOR_VERIFY(this->SharedInfo == in.SharedInfo);
550 return this->ptr - in.ptr;
554 operator[](std::ptrdiff_t n) const
555 { return *(*this + n); }
557 bool
558 operator<(const random_access_iterator_wrapper<T>& in) const
560 ITERATOR_VERIFY(this->SharedInfo == in.SharedInfo);
561 return this->ptr < in.ptr;
564 bool
565 operator>(const random_access_iterator_wrapper<T>& in) const
567 return in < *this;
570 bool
571 operator>=(const random_access_iterator_wrapper<T>& in) const
573 return !(*this < in);
576 bool
577 operator<=(const random_access_iterator_wrapper<T>& in) const
579 return !(*this > in);
583 template<typename T>
584 random_access_iterator_wrapper<T>
585 operator+(random_access_iterator_wrapper<T> it, std::ptrdiff_t n)
586 { return it += n; }
588 template<typename T>
589 random_access_iterator_wrapper<T>
590 operator+(std::ptrdiff_t n, random_access_iterator_wrapper<T> it)
591 { return it += n; }
595 * @brief A container-type class for holding iterator wrappers
596 * test_container takes two parameters, a class T and an iterator
597 * wrapper templated by T (for example forward_iterator_wrapper<T>.
598 * It takes two pointers representing a range and presents them as
599 * a container of iterators.
601 template <class T, template<class TT> class ItType>
602 struct test_container
604 typename ItType<T>::ContainerType bounds;
606 test_container(T* _first, T* _last) : bounds(_first, _last)
609 #if __cplusplus >= 201103L
610 template<std::size_t N>
611 explicit
612 test_container(T (&arr)[N]) : test_container(arr, arr+N)
614 #endif
616 ItType<T>
617 it(int pos)
619 ITERATOR_VERIFY(pos >= 0 && (unsigned)pos <= size());
620 return ItType<T>(bounds.first + pos, &bounds);
623 ItType<T>
624 it(T* pos)
626 ITERATOR_VERIFY(pos >= bounds.first && pos <= bounds.last);
627 return ItType<T>(pos, &bounds);
630 const T&
631 val(int pos)
632 { return (bounds.first)[pos]; }
634 ItType<T>
635 begin()
636 { return it(bounds.first); }
638 ItType<T>
639 end()
640 { return it(bounds.last); }
642 std::size_t
643 size() const
644 { return bounds.size(); }
647 #if __cplusplus >= 201103L
648 template<typename T>
649 using output_container
650 = test_container<T, output_iterator_wrapper>;
652 template<typename T>
653 using input_container
654 = test_container<T, input_iterator_wrapper>;
656 template<typename T>
657 using forward_container
658 = test_container<T, forward_iterator_wrapper>;
660 template<typename T>
661 using bidirectional_container
662 = test_container<T, bidirectional_iterator_wrapper>;
664 template<typename T>
665 using random_access_container
666 = test_container<T, random_access_iterator_wrapper>;
667 #endif
669 #if __cplusplus > 201703L
670 template<typename T>
671 struct contiguous_iterator_wrapper
672 : random_access_iterator_wrapper<T>
674 using random_access_iterator_wrapper<T>::random_access_iterator_wrapper;
676 using iterator_concept = std::contiguous_iterator_tag;
678 contiguous_iterator_wrapper&
679 operator++()
681 random_access_iterator_wrapper<T>::operator++();
682 return *this;
685 contiguous_iterator_wrapper&
686 operator--()
688 random_access_iterator_wrapper<T>::operator--();
689 return *this;
692 contiguous_iterator_wrapper
693 operator++(int)
695 auto tmp = *this;
696 ++*this;
697 return tmp;
700 contiguous_iterator_wrapper
701 operator--(int)
703 auto tmp = *this;
704 --*this;
705 return tmp;
708 contiguous_iterator_wrapper&
709 operator+=(std::ptrdiff_t n)
711 random_access_iterator_wrapper<T>::operator+=(n);
712 return *this;
715 friend contiguous_iterator_wrapper
716 operator+(contiguous_iterator_wrapper iter, std::ptrdiff_t n)
717 { return iter += n; }
719 friend contiguous_iterator_wrapper
720 operator+(std::ptrdiff_t n, contiguous_iterator_wrapper iter)
721 { return iter += n; }
723 contiguous_iterator_wrapper&
724 operator-=(std::ptrdiff_t n)
725 { return *this += -n; }
727 friend contiguous_iterator_wrapper
728 operator-(contiguous_iterator_wrapper iter, std::ptrdiff_t n)
729 { return iter -= n; }
732 template<typename T>
733 using contiguous_container
734 = test_container<T, contiguous_iterator_wrapper>;
736 // A move-only input iterator type.
737 template<typename T>
738 struct input_iterator_wrapper_nocopy : input_iterator_wrapper<T>
740 using input_iterator_wrapper<T>::input_iterator_wrapper;
742 input_iterator_wrapper_nocopy()
743 : input_iterator_wrapper<T>(nullptr, nullptr)
746 input_iterator_wrapper_nocopy(const input_iterator_wrapper_nocopy&) = delete;
747 input_iterator_wrapper_nocopy&
748 operator=(const input_iterator_wrapper_nocopy&) = delete;
750 input_iterator_wrapper_nocopy(input_iterator_wrapper_nocopy&&) = default;
751 input_iterator_wrapper_nocopy&
752 operator=(input_iterator_wrapper_nocopy&&) = default;
754 using input_iterator_wrapper<T>::operator++;
756 input_iterator_wrapper_nocopy&
757 operator++()
759 input_iterator_wrapper<T>::operator++();
760 return *this;
764 // A type meeting the minimum std::range requirements
765 template<typename T, template<typename> class Iter>
766 class test_range
768 // Exposes the protected default constructor of Iter<T> if needed. This
769 // is needed only when Iter is input_iterator_wrapper or
770 // output_iterator_wrapper, because legacy forward iterators and beyond
771 // are already default constructible.
772 struct iterator : Iter<T>
774 using Iter<T>::Iter;
776 using Iter<T>::operator++;
778 iterator& operator++() { Iter<T>::operator++(); return *this; }
781 template<typename I>
782 struct sentinel
784 T* end;
786 friend bool operator==(const sentinel& s, const I& i) noexcept
787 { return s.end == i.ptr; }
789 friend auto operator-(const sentinel& s, const I& i) noexcept
790 requires std::random_access_iterator<I>
791 { return s.end - i.ptr; }
793 friend auto operator-(const I& i, const sentinel& s) noexcept
794 requires std::random_access_iterator<I>
795 { return i.ptr - s.end; }
798 protected:
799 auto
800 get_iterator(T* p)
802 if constexpr (std::default_initializable<Iter<T>>)
803 return Iter<T>(p, &bounds);
804 else
805 return iterator(p, &bounds);
808 public:
809 test_range(T* first, T* last) : bounds(first, last)
812 template<std::size_t N>
813 explicit
814 test_range(T (&arr)[N]) : test_range(arr, arr+N)
817 auto begin() & { return get_iterator(bounds.first); }
819 auto end() &
821 using I = decltype(get_iterator(bounds.last));
822 return sentinel<I>{bounds.last};
825 typename Iter<T>::ContainerType bounds;
828 template<typename T>
829 using test_contiguous_range
830 = test_range<T, contiguous_iterator_wrapper>;
831 template<typename T>
832 using test_random_access_range
833 = test_range<T, random_access_iterator_wrapper>;
834 template<typename T>
835 using test_bidirectional_range
836 = test_range<T, bidirectional_iterator_wrapper>;
837 template<typename T>
838 using test_forward_range
839 = test_range<T, forward_iterator_wrapper>;
840 template<typename T>
841 using test_input_range
842 = test_range<T, input_iterator_wrapper>;
843 template<typename T>
844 using test_output_range
845 = test_range<T, output_iterator_wrapper>;
847 // A type meeting the minimum std::sized_range requirements
848 template<typename T, template<typename> class Iter>
849 struct test_sized_range : test_range<T, Iter>
851 using test_range<T, Iter>::test_range;
853 std::size_t size() const noexcept
854 { return this->bounds.size(); }
857 template<typename T>
858 using test_contiguous_sized_range
859 = test_sized_range<T, contiguous_iterator_wrapper>;
860 template<typename T>
861 using test_random_access_sized_range
862 = test_sized_range<T, random_access_iterator_wrapper>;
863 template<typename T>
864 using test_bidirectional_sized_range
865 = test_sized_range<T, bidirectional_iterator_wrapper>;
866 template<typename T>
867 using test_forward_sized_range
868 = test_sized_range<T, forward_iterator_wrapper>;
869 template<typename T>
870 using test_input_sized_range
871 = test_sized_range<T, input_iterator_wrapper>;
872 template<typename T>
873 using test_output_sized_range
874 = test_sized_range<T, output_iterator_wrapper>;
876 // A type meeting the minimum std::sized_range requirements, and whose end()
877 // returns a sized sentinel.
878 template<typename T, template<typename> class Iter>
879 struct test_sized_range_sized_sent : test_sized_range<T, Iter>
881 using test_sized_range<T, Iter>::test_sized_range;
883 template<typename I>
884 struct sentinel
886 T* end;
888 friend bool operator==(const sentinel& s, const I& i) noexcept
889 { return s.end == i.ptr; }
891 friend std::iter_difference_t<I>
892 operator-(const sentinel& s, const I& i) noexcept
893 { return s.end - i.ptr; }
895 friend std::iter_difference_t<I>
896 operator-(const I& i, const sentinel& s) noexcept
897 { return i.ptr - s.end; }
900 auto end() &
902 using I = decltype(this->get_iterator(this->bounds.last));
903 return sentinel<I>{this->bounds.last};
907 // test_range and test_sized_range do not own their elements, so they model
908 // std::ranges::borrowed_range. This file does not define specializations of
909 // std::ranges::enable_borrowed_range, so that individual tests can decide
910 // whether or not to do so.
911 // This is also true for test_container, although only when it has forward
912 // iterators (because output_iterator_wrapper and input_iterator_wrapper are
913 // not default constructible so do not model std::input_or_output_iterator).
916 // Test for basic properties of C++20 16.3.3.6 [customization.point.object].
917 template<typename T>
918 constexpr bool
919 is_customization_point_object(T&) noexcept
921 // A [CPO] is a function object with a literal class type.
922 static_assert( std::is_class_v<T> || std::is_union_v<T> );
923 static_assert( __is_literal_type(T) );
924 // The type of a [CPO], ignoring cv-qualifiers, shall model semiregular.
925 static_assert( std::semiregular<std::remove_cv_t<T>> );
927 return true;
930 #endif // C++20
931 } // namespace __gnu_test
932 #endif // _TESTSUITE_ITERATORS