2 // Iterator Wrappers for the C++ library testsuite.
4 // Copyright (C) 2004-2024 Free Software Foundation, Inc.
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)
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>
37 #ifndef _TESTSUITE_ITERATORS
38 #define _TESTSUITE_ITERATORS
40 #ifdef DISABLE_ITERATOR_DEBUG
41 #define ITERATOR_VERIFY(x)
43 #define ITERATOR_VERIFY(x) VERIFY(x)
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.
55 struct BoundsContainer
60 BoundsContainer(T
* _first
, T
* _last
) : first(_first
), last(_last
)
63 std::size_t size() const { return last
- first
; }
66 // Simple container for holding state of a set of output iterators.
68 struct OutputContainer
: public BoundsContainer
<T
>
73 OutputContainer(T
* _first
, T
* _last
)
74 : BoundsContainer
<T
>(_first
, _last
), incrementedto(_first
),
75 writtento(new bool[this->size()]())
79 { delete[] writtento
; }
82 // Produced by output_iterator to allow limited writing to pointer
89 OutputContainer
<T
>* SharedInfo
;
91 WritableObject(T
* ptr_in
, OutputContainer
<T
>* SharedInfo_in
):
92 ptr(ptr_in
), SharedInfo(SharedInfo_in
)
95 #if __cplusplus >= 201103L
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
);
107 operator=(const U
& new_val
)
109 ITERATOR_VERIFY(SharedInfo
->writtento
[ptr
- SharedInfo
->first
] == 0);
110 SharedInfo
->writtento
[ptr
- SharedInfo
->first
] = 1;
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
124 struct output_iterator_wrapper
127 output_iterator_wrapper() : ptr(0), SharedInfo(0)
131 typedef std::output_iterator_tag iterator_category
;
132 typedef T value_type
;
133 typedef std::ptrdiff_t difference_type
;
135 typedef T
& reference
;
137 typedef OutputContainer
<T
> ContainerType
;
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;
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
&
165 ITERATOR_VERIFY(SharedInfo
&& ptr
< SharedInfo
->last
);
166 ITERATOR_VERIFY(ptr
>=SharedInfo
->incrementedto
);
168 SharedInfo
->incrementedto
=ptr
;
172 output_iterator_wrapper
175 output_iterator_wrapper
<T
> tmp
= *this;
180 #if __cplusplus >= 201103L
182 void operator,(const U
&) const = delete;
184 void operator&() const = delete;
188 void operator,(const U
&) const;
190 void operator&() const;
194 #if __cplusplus >= 201103L
195 template<typename T
, typename U
>
196 void operator,(const T
&, const output_iterator_wrapper
<U
>&) = delete;
199 #if __cplusplus >= 201103L
200 using std::remove_cv
;
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
; };
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
216 class input_iterator_wrapper
218 struct post_inc_proxy
223 operator const T
&() const { return *ptr
; }
226 deref_proxy
operator*() const { return p
; }
230 input_iterator_wrapper() : ptr(0), SharedInfo(0)
234 typedef std::input_iterator_tag iterator_category
;
235 typedef typename remove_cv
<T
>::type value_type
;
236 typedef std::ptrdiff_t difference_type
;
238 typedef T
& reference
;
240 typedef BoundsContainer
<T
> ContainerType
;
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;
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
;
264 operator!=(const input_iterator_wrapper
& in
) const
266 return !(*this == in
);
272 ITERATOR_VERIFY(SharedInfo
&& ptr
< SharedInfo
->last
);
273 ITERATOR_VERIFY(ptr
>= SharedInfo
->first
);
283 input_iterator_wrapper
&
286 ITERATOR_VERIFY(SharedInfo
&& ptr
< SharedInfo
->last
);
287 ITERATOR_VERIFY(ptr
>=SharedInfo
->first
);
289 SharedInfo
->first
=ptr
;
296 post_inc_proxy tmp
= { { ptr
} };
301 #if __cplusplus >= 201103L
303 void operator,(const U
&) const = delete;
305 void operator&() const = delete;
309 void operator,(const U
&) const;
311 void operator&() const;
315 #if __cplusplus >= 201103L
316 template<typename T
, typename U
>
317 void operator,(const T
&, const input_iterator_wrapper
<U
>&) = delete;
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
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;
350 ITERATOR_VERIFY(this->SharedInfo
&& this->ptr
< this->SharedInfo
->last
);
358 forward_iterator_wrapper
&
361 ITERATOR_VERIFY(this->SharedInfo
&& this->ptr
< this->SharedInfo
->last
);
366 forward_iterator_wrapper
369 forward_iterator_wrapper
<T
> tmp
= *this;
374 #if __cplusplus >= 201402L
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
;
388 operator!=(const forward_iterator_wrapper
& it
) const noexcept
390 return !(*this == it
);
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
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;
424 bidirectional_iterator_wrapper
&
427 ITERATOR_VERIFY(this->SharedInfo
&& this->ptr
< this->SharedInfo
->last
);
432 bidirectional_iterator_wrapper
435 bidirectional_iterator_wrapper
<T
> tmp
= *this;
440 bidirectional_iterator_wrapper
&
443 ITERATOR_VERIFY(this->SharedInfo
&& this->ptr
> this->SharedInfo
->first
);
448 bidirectional_iterator_wrapper
451 bidirectional_iterator_wrapper
<T
> tmp
= *this;
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
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;
487 random_access_iterator_wrapper
&
490 ITERATOR_VERIFY(this->SharedInfo
&& this->ptr
< this->SharedInfo
->last
);
495 random_access_iterator_wrapper
498 random_access_iterator_wrapper
<T
> tmp
= *this;
503 random_access_iterator_wrapper
&
506 ITERATOR_VERIFY(this->SharedInfo
&& this->ptr
> this->SharedInfo
->first
);
511 random_access_iterator_wrapper
514 random_access_iterator_wrapper
<T
> tmp
= *this;
519 random_access_iterator_wrapper
&
520 operator+=(std::ptrdiff_t n
)
524 ITERATOR_VERIFY(n
<= this->SharedInfo
->last
- this->ptr
);
529 ITERATOR_VERIFY(-n
<= this->ptr
- this->SharedInfo
->first
);
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;
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
); }
558 operator<(const random_access_iterator_wrapper
<T
>& in
) const
560 ITERATOR_VERIFY(this->SharedInfo
== in
.SharedInfo
);
561 return this->ptr
< in
.ptr
;
565 operator>(const random_access_iterator_wrapper
<T
>& in
) const
571 operator>=(const random_access_iterator_wrapper
<T
>& in
) const
573 return !(*this < in
);
577 operator<=(const random_access_iterator_wrapper
<T
>& in
) const
579 return !(*this > in
);
584 random_access_iterator_wrapper
<T
>
585 operator+(random_access_iterator_wrapper
<T
> it
, std::ptrdiff_t n
)
589 random_access_iterator_wrapper
<T
>
590 operator+(std::ptrdiff_t n
, random_access_iterator_wrapper
<T
> it
)
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
>
612 test_container(T (&arr
)[N
]) : test_container(arr
, arr
+N
)
619 ITERATOR_VERIFY(pos
>= 0 && (unsigned)pos
<= size());
620 return ItType
<T
>(bounds
.first
+ pos
, &bounds
);
626 ITERATOR_VERIFY(pos
>= bounds
.first
&& pos
<= bounds
.last
);
627 return ItType
<T
>(pos
, &bounds
);
632 { return (bounds
.first
)[pos
]; }
636 { return it(bounds
.first
); }
640 { return it(bounds
.last
); }
644 { return bounds
.size(); }
647 #if __cplusplus >= 201103L
649 using output_container
650 = test_container
<T
, output_iterator_wrapper
>;
653 using input_container
654 = test_container
<T
, input_iterator_wrapper
>;
657 using forward_container
658 = test_container
<T
, forward_iterator_wrapper
>;
661 using bidirectional_container
662 = test_container
<T
, bidirectional_iterator_wrapper
>;
665 using random_access_container
666 = test_container
<T
, random_access_iterator_wrapper
>;
669 #if __cplusplus > 201703L
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
&
681 random_access_iterator_wrapper
<T
>::operator++();
685 contiguous_iterator_wrapper
&
688 random_access_iterator_wrapper
<T
>::operator--();
692 contiguous_iterator_wrapper
700 contiguous_iterator_wrapper
708 contiguous_iterator_wrapper
&
709 operator+=(std::ptrdiff_t n
)
711 random_access_iterator_wrapper
<T
>::operator+=(n
);
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
; }
733 using contiguous_container
734 = test_container
<T
, contiguous_iterator_wrapper
>;
736 // A move-only input iterator type.
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
&
759 input_iterator_wrapper
<T
>::operator++();
764 // A type meeting the minimum std::range requirements
765 template<typename T
, template<typename
> class Iter
>
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
>
776 using Iter
<T
>::operator++;
778 iterator
& operator++() { Iter
<T
>::operator++(); return *this; }
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
; }
802 if constexpr (std::default_initializable
<Iter
<T
>>)
803 return Iter
<T
>(p
, &bounds
);
805 return iterator(p
, &bounds
);
809 test_range(T
* first
, T
* last
) : bounds(first
, last
)
812 template<std::size_t N
>
814 test_range(T (&arr
)[N
]) : test_range(arr
, arr
+N
)
817 auto begin() & { return get_iterator(bounds
.first
); }
821 using I
= decltype(get_iterator(bounds
.last
));
822 return sentinel
<I
>{bounds
.last
};
825 typename Iter
<T
>::ContainerType bounds
;
829 using test_contiguous_range
830 = test_range
<T
, contiguous_iterator_wrapper
>;
832 using test_random_access_range
833 = test_range
<T
, random_access_iterator_wrapper
>;
835 using test_bidirectional_range
836 = test_range
<T
, bidirectional_iterator_wrapper
>;
838 using test_forward_range
839 = test_range
<T
, forward_iterator_wrapper
>;
841 using test_input_range
842 = test_range
<T
, input_iterator_wrapper
>;
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(); }
858 using test_contiguous_sized_range
859 = test_sized_range
<T
, contiguous_iterator_wrapper
>;
861 using test_random_access_sized_range
862 = test_sized_range
<T
, random_access_iterator_wrapper
>;
864 using test_bidirectional_sized_range
865 = test_sized_range
<T
, bidirectional_iterator_wrapper
>;
867 using test_forward_sized_range
868 = test_sized_range
<T
, forward_iterator_wrapper
>;
870 using test_input_sized_range
871 = test_sized_range
<T
, input_iterator_wrapper
>;
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
;
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
; }
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].
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
>> );
931 } // namespace __gnu_test
932 #endif // _TESTSUITE_ITERATORS