1 //===----------------------------------------------------------------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 #ifndef SUPPORT_TEST_ITERATORS_H
10 #define SUPPORT_TEST_ITERATORS_H
18 #include "test_macros.h"
20 // This iterator meets C++20's Cpp17OutputIterator requirements, as described
21 // in Table 90 ([output.iterators]).
23 class cpp17_output_iterator
27 template <class U
> friend class cpp17_output_iterator
;
29 typedef std::output_iterator_tag iterator_category
;
30 typedef void value_type
;
31 typedef typename
std::iterator_traits
<It
>::difference_type difference_type
;
33 typedef typename
std::iterator_traits
<It
>::reference reference
;
35 TEST_CONSTEXPR
explicit cpp17_output_iterator(It it
) : it_(std::move(it
)) {}
37 TEST_CONSTEXPR
cpp17_output_iterator(const cpp17_output_iterator
<U
>& u
) :it_(u
.it_
) {}
39 TEST_CONSTEXPR reference
operator*() const {return *it_
;}
41 TEST_CONSTEXPR_CXX14 cpp17_output_iterator
& operator++() {++it_
; return *this;}
42 TEST_CONSTEXPR_CXX14 cpp17_output_iterator
operator++(int) {return cpp17_output_iterator(it_
++);}
44 friend TEST_CONSTEXPR It
base(const cpp17_output_iterator
& i
) { return i
.it_
; }
47 void operator,(T
const &) = delete;
49 #if _LIBCPP_STD_VER > 17
50 static_assert(std::output_iterator
<cpp17_output_iterator
<int*>, int>);
53 // This iterator meets C++20's Cpp17InputIterator requirements, as described
54 // in Table 89 ([input.iterators]).
55 template <class It
, class ItTraits
= It
>
56 class cpp17_input_iterator
58 typedef std::iterator_traits
<ItTraits
> Traits
;
61 template <class U
, class T
> friend class cpp17_input_iterator
;
63 typedef std::input_iterator_tag iterator_category
;
64 typedef typename
Traits::value_type value_type
;
65 typedef typename
Traits::difference_type difference_type
;
67 typedef typename
Traits::reference reference
;
69 TEST_CONSTEXPR
explicit cpp17_input_iterator(It it
) : it_(it
) {}
70 template <class U
, class T
>
71 TEST_CONSTEXPR
cpp17_input_iterator(const cpp17_input_iterator
<U
, T
>& u
) : it_(u
.it_
) {}
73 TEST_CONSTEXPR reference
operator*() const {return *it_
;}
75 TEST_CONSTEXPR_CXX14 cpp17_input_iterator
& operator++() {++it_
; return *this;}
76 TEST_CONSTEXPR_CXX14 cpp17_input_iterator
operator++(int) {return cpp17_input_iterator(it_
++);}
78 friend TEST_CONSTEXPR
bool operator==(const cpp17_input_iterator
& x
, const cpp17_input_iterator
& y
) {return x
.it_
== y
.it_
;}
79 friend TEST_CONSTEXPR
bool operator!=(const cpp17_input_iterator
& x
, const cpp17_input_iterator
& y
) {return x
.it_
!= y
.it_
;}
81 friend TEST_CONSTEXPR It
base(const cpp17_input_iterator
& i
) { return i
.it_
; }
84 void operator,(T
const &) = delete;
86 #if _LIBCPP_STD_VER > 17
87 static_assert(std::input_iterator
<cpp17_input_iterator
<int*>>);
91 class forward_iterator
95 template <class U
> friend class forward_iterator
;
97 typedef std::forward_iterator_tag iterator_category
;
98 typedef typename
std::iterator_traits
<It
>::value_type value_type
;
99 typedef typename
std::iterator_traits
<It
>::difference_type difference_type
;
101 typedef typename
std::iterator_traits
<It
>::reference reference
;
103 TEST_CONSTEXPR
forward_iterator() : it_() {}
104 TEST_CONSTEXPR
explicit forward_iterator(It it
) : it_(it
) {}
106 TEST_CONSTEXPR
forward_iterator(const forward_iterator
<U
>& u
) : it_(u
.it_
) {}
108 TEST_CONSTEXPR reference
operator*() const {return *it_
;}
110 TEST_CONSTEXPR_CXX14 forward_iterator
& operator++() {++it_
; return *this;}
111 TEST_CONSTEXPR_CXX14 forward_iterator
operator++(int) {return forward_iterator(it_
++);}
113 friend TEST_CONSTEXPR
bool operator==(const forward_iterator
& x
, const forward_iterator
& y
) {return x
.it_
== y
.it_
;}
114 friend TEST_CONSTEXPR
bool operator!=(const forward_iterator
& x
, const forward_iterator
& y
) {return x
.it_
!= y
.it_
;}
116 friend TEST_CONSTEXPR It
base(const forward_iterator
& i
) { return i
.it_
; }
119 void operator,(T
const &) = delete;
123 class bidirectional_iterator
127 template <class U
> friend class bidirectional_iterator
;
129 typedef std::bidirectional_iterator_tag iterator_category
;
130 typedef typename
std::iterator_traits
<It
>::value_type value_type
;
131 typedef typename
std::iterator_traits
<It
>::difference_type difference_type
;
133 typedef typename
std::iterator_traits
<It
>::reference reference
;
135 TEST_CONSTEXPR
bidirectional_iterator() : it_() {}
136 TEST_CONSTEXPR
explicit bidirectional_iterator(It it
) : it_(it
) {}
138 TEST_CONSTEXPR
bidirectional_iterator(const bidirectional_iterator
<U
>& u
) : it_(u
.it_
) {}
140 TEST_CONSTEXPR reference
operator*() const {return *it_
;}
142 TEST_CONSTEXPR_CXX14 bidirectional_iterator
& operator++() {++it_
; return *this;}
143 TEST_CONSTEXPR_CXX14 bidirectional_iterator
& operator--() {--it_
; return *this;}
144 TEST_CONSTEXPR_CXX14 bidirectional_iterator
operator++(int) {return bidirectional_iterator(it_
++);}
145 TEST_CONSTEXPR_CXX14 bidirectional_iterator
operator--(int) {return bidirectional_iterator(it_
--);}
147 friend TEST_CONSTEXPR
bool operator==(const bidirectional_iterator
& x
, const bidirectional_iterator
& y
) {return x
.it_
== y
.it_
;}
148 friend TEST_CONSTEXPR
bool operator!=(const bidirectional_iterator
& x
, const bidirectional_iterator
& y
) {return x
.it_
!= y
.it_
;}
150 friend TEST_CONSTEXPR It
base(const bidirectional_iterator
& i
) { return i
.it_
; }
153 void operator,(T
const &) = delete;
157 class random_access_iterator
161 template <class U
> friend class random_access_iterator
;
163 typedef std::random_access_iterator_tag iterator_category
;
164 typedef typename
std::iterator_traits
<It
>::value_type value_type
;
165 typedef typename
std::iterator_traits
<It
>::difference_type difference_type
;
167 typedef typename
std::iterator_traits
<It
>::reference reference
;
169 TEST_CONSTEXPR
random_access_iterator() : it_() {}
170 TEST_CONSTEXPR
explicit random_access_iterator(It it
) : it_(it
) {}
172 TEST_CONSTEXPR
random_access_iterator(const random_access_iterator
<U
>& u
) : it_(u
.it_
) {}
174 TEST_CONSTEXPR_CXX14 reference
operator*() const {return *it_
;}
175 TEST_CONSTEXPR_CXX14 reference
operator[](difference_type n
) const {return it_
[n
];}
177 TEST_CONSTEXPR_CXX14 random_access_iterator
& operator++() {++it_
; return *this;}
178 TEST_CONSTEXPR_CXX14 random_access_iterator
& operator--() {--it_
; return *this;}
179 TEST_CONSTEXPR_CXX14 random_access_iterator
operator++(int) {return random_access_iterator(it_
++);}
180 TEST_CONSTEXPR_CXX14 random_access_iterator
operator--(int) {return random_access_iterator(it_
--);}
182 TEST_CONSTEXPR_CXX14 random_access_iterator
& operator+=(difference_type n
) {it_
+= n
; return *this;}
183 TEST_CONSTEXPR_CXX14 random_access_iterator
& operator-=(difference_type n
) {it_
-= n
; return *this;}
184 friend TEST_CONSTEXPR_CXX14 random_access_iterator
operator+(random_access_iterator x
, difference_type n
) {x
+= n
; return x
;}
185 friend TEST_CONSTEXPR_CXX14 random_access_iterator
operator+(difference_type n
, random_access_iterator x
) {x
+= n
; return x
;}
186 friend TEST_CONSTEXPR_CXX14 random_access_iterator
operator-(random_access_iterator x
, difference_type n
) {x
-= n
; return x
;}
187 friend TEST_CONSTEXPR difference_type
operator-(random_access_iterator x
, random_access_iterator y
) {return x
.it_
- y
.it_
;}
189 friend TEST_CONSTEXPR
bool operator==(const random_access_iterator
& x
, const random_access_iterator
& y
) {return x
.it_
== y
.it_
;}
190 friend TEST_CONSTEXPR
bool operator!=(const random_access_iterator
& x
, const random_access_iterator
& y
) {return x
.it_
!= y
.it_
;}
191 friend TEST_CONSTEXPR
bool operator< (const random_access_iterator
& x
, const random_access_iterator
& y
) {return x
.it_
< y
.it_
;}
192 friend TEST_CONSTEXPR
bool operator<=(const random_access_iterator
& x
, const random_access_iterator
& y
) {return x
.it_
<= y
.it_
;}
193 friend TEST_CONSTEXPR
bool operator> (const random_access_iterator
& x
, const random_access_iterator
& y
) {return x
.it_
> y
.it_
;}
194 friend TEST_CONSTEXPR
bool operator>=(const random_access_iterator
& x
, const random_access_iterator
& y
) {return x
.it_
>= y
.it_
;}
196 friend TEST_CONSTEXPR It
base(const random_access_iterator
& i
) { return i
.it_
; }
199 void operator,(T
const &) = delete;
202 #if TEST_STD_VER > 17
204 class contiguous_iterator
206 static_assert(std::is_pointer_v
<It
>, "Things probably break in this case");
210 template <class U
> friend class contiguous_iterator
;
212 typedef std::contiguous_iterator_tag iterator_category
;
213 typedef typename
std::iterator_traits
<It
>::value_type value_type
;
214 typedef typename
std::iterator_traits
<It
>::difference_type difference_type
;
216 typedef typename
std::iterator_traits
<It
>::reference reference
;
217 typedef typename
std::remove_pointer
<It
>::type element_type
;
219 TEST_CONSTEXPR_CXX14 It
base() const {return it_
;}
221 TEST_CONSTEXPR_CXX14
contiguous_iterator() : it_() {}
222 TEST_CONSTEXPR_CXX14
explicit contiguous_iterator(It it
) : it_(it
) {}
224 TEST_CONSTEXPR_CXX14
contiguous_iterator(const contiguous_iterator
<U
>& u
) : it_(u
.it_
) {}
226 TEST_CONSTEXPR reference
operator*() const {return *it_
;}
227 TEST_CONSTEXPR pointer
operator->() const {return it_
;}
228 TEST_CONSTEXPR reference
operator[](difference_type n
) const {return it_
[n
];}
230 TEST_CONSTEXPR_CXX14 contiguous_iterator
& operator++() {++it_
; return *this;}
231 TEST_CONSTEXPR_CXX14 contiguous_iterator
& operator--() {--it_
; return *this;}
232 TEST_CONSTEXPR_CXX14 contiguous_iterator
operator++(int) {return contiguous_iterator(it_
++);}
233 TEST_CONSTEXPR_CXX14 contiguous_iterator
operator--(int) {return contiguous_iterator(it_
--);}
235 TEST_CONSTEXPR_CXX14 contiguous_iterator
& operator+=(difference_type n
) {it_
+= n
; return *this;}
236 TEST_CONSTEXPR_CXX14 contiguous_iterator
& operator-=(difference_type n
) {it_
-= n
; return *this;}
237 friend TEST_CONSTEXPR_CXX14 contiguous_iterator
operator+(contiguous_iterator x
, difference_type n
) {x
+= n
; return x
;}
238 friend TEST_CONSTEXPR_CXX14 contiguous_iterator
operator+(difference_type n
, contiguous_iterator x
) {x
+= n
; return x
;}
239 friend TEST_CONSTEXPR_CXX14 contiguous_iterator
operator-(contiguous_iterator x
, difference_type n
) {x
-= n
; return x
;}
240 friend TEST_CONSTEXPR difference_type
operator-(contiguous_iterator x
, contiguous_iterator y
) {return x
.it_
- y
.it_
;}
242 friend TEST_CONSTEXPR
bool operator==(const contiguous_iterator
& x
, const contiguous_iterator
& y
) {return x
.it_
== y
.it_
;}
243 friend TEST_CONSTEXPR
bool operator!=(const contiguous_iterator
& x
, const contiguous_iterator
& y
) {return x
.it_
!= y
.it_
;}
244 friend TEST_CONSTEXPR
bool operator< (const contiguous_iterator
& x
, const contiguous_iterator
& y
) {return x
.it_
< y
.it_
;}
245 friend TEST_CONSTEXPR
bool operator<=(const contiguous_iterator
& x
, const contiguous_iterator
& y
) {return x
.it_
<= y
.it_
;}
246 friend TEST_CONSTEXPR
bool operator> (const contiguous_iterator
& x
, const contiguous_iterator
& y
) {return x
.it_
> y
.it_
;}
247 friend TEST_CONSTEXPR
bool operator>=(const contiguous_iterator
& x
, const contiguous_iterator
& y
) {return x
.it_
>= y
.it_
;}
249 friend TEST_CONSTEXPR It
base(const contiguous_iterator
& i
) { return i
.it_
; }
252 void operator,(T
const &) = delete;
256 class three_way_contiguous_iterator
258 static_assert(std::is_pointer_v
<It
>, "Things probably break in this case");
262 template <class U
> friend class three_way_contiguous_iterator
;
264 typedef std::contiguous_iterator_tag iterator_category
;
265 typedef typename
std::iterator_traits
<It
>::value_type value_type
;
266 typedef typename
std::iterator_traits
<It
>::difference_type difference_type
;
268 typedef typename
std::iterator_traits
<It
>::reference reference
;
269 typedef typename
std::remove_pointer
<It
>::type element_type
;
271 constexpr It
base() const {return it_
;}
273 constexpr three_way_contiguous_iterator() : it_() {}
274 constexpr explicit three_way_contiguous_iterator(It it
) : it_(it
) {}
276 constexpr three_way_contiguous_iterator(const three_way_contiguous_iterator
<U
>& u
) : it_(u
.it_
) {}
278 constexpr reference
operator*() const {return *it_
;}
279 constexpr pointer
operator->() const {return it_
;}
280 constexpr reference
operator[](difference_type n
) const {return it_
[n
];}
282 constexpr three_way_contiguous_iterator
& operator++() {++it_
; return *this;}
283 constexpr three_way_contiguous_iterator
& operator--() {--it_
; return *this;}
284 constexpr three_way_contiguous_iterator
operator++(int) {return three_way_contiguous_iterator(it_
++);}
285 constexpr three_way_contiguous_iterator
operator--(int) {return three_way_contiguous_iterator(it_
--);}
287 constexpr three_way_contiguous_iterator
& operator+=(difference_type n
) {it_
+= n
; return *this;}
288 constexpr three_way_contiguous_iterator
& operator-=(difference_type n
) {it_
-= n
; return *this;}
289 friend constexpr three_way_contiguous_iterator
operator+(three_way_contiguous_iterator x
, difference_type n
) {x
+= n
; return x
;}
290 friend constexpr three_way_contiguous_iterator
operator+(difference_type n
, three_way_contiguous_iterator x
) {x
+= n
; return x
;}
291 friend constexpr three_way_contiguous_iterator
operator-(three_way_contiguous_iterator x
, difference_type n
) {x
-= n
; return x
;}
292 friend constexpr difference_type
operator-(three_way_contiguous_iterator x
, three_way_contiguous_iterator y
) {return x
.it_
- y
.it_
;}
294 friend constexpr auto operator<=>(const three_way_contiguous_iterator
& x
, const three_way_contiguous_iterator
& y
) {return x
.it_
<=> y
.it_
;}
295 friend constexpr bool operator==(const three_way_contiguous_iterator
& x
, const three_way_contiguous_iterator
& y
) {return x
.it_
== y
.it_
;}
298 void operator,(T
const &) = delete;
300 #endif // TEST_STD_VER > 17
302 template <class Iter
> // ADL base() for everything else (including pointers)
303 TEST_CONSTEXPR Iter
base(Iter i
) { return i
; }
305 template <typename T
>
306 struct ThrowingIterator
{
307 typedef std::bidirectional_iterator_tag iterator_category
;
308 typedef ptrdiff_t difference_type
;
309 typedef const T value_type
;
310 typedef const T
* pointer
;
311 typedef const T
& reference
;
313 enum ThrowingAction
{ TAIncrement
, TADecrement
, TADereference
, TAAssignment
, TAComparison
};
315 TEST_CONSTEXPR
ThrowingIterator()
316 : begin_(nullptr), end_(nullptr), current_(nullptr), action_(TADereference
), index_(0) {}
317 TEST_CONSTEXPR
explicit ThrowingIterator(const T
* first
, const T
* last
, int index
= 0,
318 ThrowingAction action
= TADereference
)
319 : begin_(first
), end_(last
), current_(first
), action_(action
), index_(index
) {}
320 TEST_CONSTEXPR
ThrowingIterator(const ThrowingIterator
&rhs
)
321 : begin_(rhs
.begin_
), end_(rhs
.end_
), current_(rhs
.current_
), action_(rhs
.action_
), index_(rhs
.index_
) {}
323 TEST_CONSTEXPR_CXX14 ThrowingIterator
& operator=(const ThrowingIterator
& rhs
) {
324 if (action_
== TAAssignment
&& --index_
< 0) {
325 #ifndef TEST_HAS_NO_EXCEPTIONS
326 throw std::runtime_error("throw from iterator assignment");
333 current_
= rhs
.current_
;
334 action_
= rhs
.action_
;
339 TEST_CONSTEXPR_CXX14 reference
operator*() const {
340 if (action_
== TADereference
&& --index_
< 0) {
341 #ifndef TEST_HAS_NO_EXCEPTIONS
342 throw std::runtime_error("throw from iterator dereference");
350 TEST_CONSTEXPR_CXX14 ThrowingIterator
& operator++() {
351 if (action_
== TAIncrement
&& --index_
< 0) {
352 #ifndef TEST_HAS_NO_EXCEPTIONS
353 throw std::runtime_error("throw from iterator increment");
362 TEST_CONSTEXPR_CXX14 ThrowingIterator
operator++(int) {
363 ThrowingIterator temp
= *this;
368 TEST_CONSTEXPR_CXX14 ThrowingIterator
& operator--() {
369 if (action_
== TADecrement
&& --index_
< 0) {
370 #ifndef TEST_HAS_NO_EXCEPTIONS
371 throw std::runtime_error("throw from iterator decrement");
380 TEST_CONSTEXPR_CXX14 ThrowingIterator
operator--(int) {
381 ThrowingIterator temp
= *this;
386 TEST_CONSTEXPR_CXX14
friend bool operator==(const ThrowingIterator
& a
, const ThrowingIterator
& b
) {
387 if (a
.action_
== TAComparison
&& --a
.index_
< 0) {
388 #ifndef TEST_HAS_NO_EXCEPTIONS
389 throw std::runtime_error("throw from iterator comparison");
394 bool atEndL
= a
.current_
== a
.end_
;
395 bool atEndR
= b
.current_
== b
.end_
;
396 if (atEndL
!= atEndR
) return false; // one is at the end (or empty), the other is not.
397 if (atEndL
) return true; // both are at the end (or empty)
398 return a
.current_
== b
.current_
;
401 TEST_CONSTEXPR
friend bool operator!=(const ThrowingIterator
& a
, const ThrowingIterator
& b
) {
406 void operator,(T2
const &) = delete;
412 ThrowingAction action_
;
416 template <typename T
>
417 struct NonThrowingIterator
{
418 typedef std::bidirectional_iterator_tag iterator_category
;
419 typedef ptrdiff_t difference_type
;
420 typedef const T value_type
;
421 typedef const T
* pointer
;
422 typedef const T
& reference
;
424 NonThrowingIterator()
425 : begin_(nullptr), end_(nullptr), current_(nullptr) {}
426 explicit NonThrowingIterator(const T
*first
, const T
*last
)
427 : begin_(first
), end_(last
), current_(first
) {}
428 NonThrowingIterator(const NonThrowingIterator
& rhs
)
429 : begin_(rhs
.begin_
), end_(rhs
.end_
), current_(rhs
.current_
) {}
431 NonThrowingIterator
& operator=(const NonThrowingIterator
& rhs
) TEST_NOEXCEPT
{
434 current_
= rhs
.current_
;
438 reference
operator*() const TEST_NOEXCEPT
{
442 NonThrowingIterator
& operator++() TEST_NOEXCEPT
{
447 NonThrowingIterator
operator++(int) TEST_NOEXCEPT
{
448 NonThrowingIterator temp
= *this;
453 NonThrowingIterator
& operator--() TEST_NOEXCEPT
{
458 NonThrowingIterator
operator--(int) TEST_NOEXCEPT
{
459 NonThrowingIterator temp
= *this;
464 friend bool operator==(const NonThrowingIterator
& a
, const NonThrowingIterator
& b
) TEST_NOEXCEPT
{
465 bool atEndL
= a
.current_
== a
.end_
;
466 bool atEndR
= b
.current_
== b
.end_
;
467 if (atEndL
!= atEndR
) return false; // one is at the end (or empty), the other is not.
468 if (atEndL
) return true; // both are at the end (or empty)
469 return a
.current_
== b
.current_
;
472 friend bool operator!=(const NonThrowingIterator
& a
, const NonThrowingIterator
& b
) TEST_NOEXCEPT
{
477 void operator,(T2
const &) = delete;
485 #if TEST_STD_VER > 17
488 class cpp20_input_iterator
493 using value_type
= std::iter_value_t
<It
>;
494 using difference_type
= std::iter_difference_t
<It
>;
495 using iterator_concept
= std::input_iterator_tag
;
497 constexpr explicit cpp20_input_iterator(It it
) : it_(it
) {}
498 cpp20_input_iterator(cpp20_input_iterator
&&) = default;
499 cpp20_input_iterator
& operator=(cpp20_input_iterator
&&) = default;
500 constexpr decltype(auto) operator*() const { return *it_
; }
501 constexpr cpp20_input_iterator
& operator++() { ++it_
; return *this; }
502 constexpr void operator++(int) { ++it_
; }
504 friend constexpr It
base(const cpp20_input_iterator
& i
) { return i
.it_
; }
507 void operator,(T
const &) = delete;
510 template<std::input_or_output_iterator
>
511 struct iter_value_or_void
{ using type
= void; };
513 template<std::input_iterator I
>
514 struct iter_value_or_void
<I
> {
515 using type
= std::iter_value_t
<I
>;
518 // Iterator adaptor that counts the number of times the iterator has had a successor/predecessor
519 // operation called. Has two recorders:
520 // * `stride_count`, which records the total number of calls to an op++, op--, op+=, or op-=.
521 // * `stride_displacement`, which records the displacement of the calls. This means that both
522 // op++/op+= will increase the displacement counter by 1, and op--/op-= will decrease the
523 // displacement counter by 1.
525 class stride_counting_iterator
{
527 using value_type
= typename iter_value_or_void
<It
>::type
;
528 using difference_type
= std::iter_difference_t
<It
>;
529 using iterator_concept
=
530 std::conditional_t
<std::contiguous_iterator
<It
>, std::contiguous_iterator_tag
,
531 std::conditional_t
<std::random_access_iterator
<It
>, std::random_access_iterator_tag
,
532 std::conditional_t
<std::bidirectional_iterator
<It
>, std::bidirectional_iterator_tag
,
533 std::conditional_t
<std::forward_iterator
<It
>, std::forward_iterator_tag
,
534 std::conditional_t
<std::input_iterator
<It
>, std::input_iterator_tag
,
535 /* else */ std::output_iterator_tag
538 stride_counting_iterator() requires
std::default_initializable
<It
> = default;
540 constexpr explicit stride_counting_iterator(It
const& it
) : base_(base(it
)) { }
542 friend constexpr It
base(stride_counting_iterator
const& it
) { return It(it
.base_
); }
544 constexpr difference_type
stride_count() const { return stride_count_
; }
546 constexpr difference_type
stride_displacement() const { return stride_displacement_
; }
548 constexpr decltype(auto) operator*() const { return *It(base_
); }
550 constexpr decltype(auto) operator[](difference_type n
) const { return It(base_
)[n
]; }
552 constexpr stride_counting_iterator
& operator++() {
556 ++stride_displacement_
;
560 constexpr void operator++(int) { ++*this; }
562 constexpr stride_counting_iterator
operator++(int)
563 requires
std::forward_iterator
<It
>
570 constexpr stride_counting_iterator
& operator--()
571 requires
std::bidirectional_iterator
<It
>
576 --stride_displacement_
;
580 constexpr stride_counting_iterator
operator--(int)
581 requires
std::bidirectional_iterator
<It
>
588 constexpr stride_counting_iterator
& operator+=(difference_type
const n
)
589 requires
std::random_access_iterator
<It
>
592 base_
= base(tmp
+= n
);
594 ++stride_displacement_
;
598 constexpr stride_counting_iterator
& operator-=(difference_type
const n
)
599 requires
std::random_access_iterator
<It
>
602 base_
= base(tmp
-= n
);
604 --stride_displacement_
;
608 friend constexpr stride_counting_iterator
operator+(stride_counting_iterator it
, difference_type n
)
609 requires
std::random_access_iterator
<It
>
614 friend constexpr stride_counting_iterator
operator+(difference_type n
, stride_counting_iterator it
)
615 requires
std::random_access_iterator
<It
>
620 friend constexpr stride_counting_iterator
operator-(stride_counting_iterator it
, difference_type n
)
621 requires
std::random_access_iterator
<It
>
626 friend constexpr difference_type
operator-(stride_counting_iterator
const& x
, stride_counting_iterator
const& y
)
627 requires
std::sized_sentinel_for
<It
, It
>
629 return base(x
) - base(y
);
632 constexpr bool operator==(stride_counting_iterator
const& other
) const
633 requires
std::sentinel_for
<It
, It
>
635 return It(base_
) == It(other
.base_
);
638 friend constexpr bool operator<(stride_counting_iterator
const& x
, stride_counting_iterator
const& y
)
639 requires
std::random_access_iterator
<It
>
641 return It(x
.base_
) < It(y
.base_
);
644 friend constexpr bool operator>(stride_counting_iterator
const& x
, stride_counting_iterator
const& y
)
645 requires
std::random_access_iterator
<It
>
647 return It(x
.base_
) > It(y
.base_
);
650 friend constexpr bool operator<=(stride_counting_iterator
const& x
, stride_counting_iterator
const& y
)
651 requires
std::random_access_iterator
<It
>
653 return It(x
.base_
) <= It(y
.base_
);
656 friend constexpr bool operator>=(stride_counting_iterator
const& x
, stride_counting_iterator
const& y
)
657 requires
std::random_access_iterator
<It
>
659 return It(x
.base_
) >= It(y
.base_
);
663 void operator,(T
const &) = delete;
666 decltype(base(std::declval
<It
>())) base_
;
667 difference_type stride_count_
= 0;
668 difference_type stride_displacement_
= 0;
671 #endif // TEST_STD_VER > 17
673 #if TEST_STD_VER > 17
675 class sentinel_wrapper
{
677 explicit sentinel_wrapper() = default;
678 constexpr explicit sentinel_wrapper(const It
& it
) : base_(base(it
)) {}
679 constexpr bool operator==(const It
& other
) const { return base_
== base(other
); }
680 friend constexpr It
base(const sentinel_wrapper
& s
) { return It(s
.base_
); }
682 decltype(base(std::declval
<It
>())) base_
;
686 class sized_sentinel
{
688 explicit sized_sentinel() = default;
689 constexpr explicit sized_sentinel(const It
& it
) : base_(base(it
)) {}
690 constexpr bool operator==(const It
& other
) const { return base_
== base(other
); }
691 friend constexpr auto operator-(const sized_sentinel
& s
, const It
& i
) { return s
.base_
- base(i
); }
692 friend constexpr auto operator-(const It
& i
, const sized_sentinel
& s
) { return base(i
) - s
.base_
; }
693 friend constexpr It
base(const sized_sentinel
& s
) { return It(s
.base_
); }
695 decltype(base(std::declval
<It
>())) base_
;
697 #endif // TEST_STD_VER > 17
699 #endif // SUPPORT_TEST_ITERATORS_H