diff --git a/libcxx/test/std/iterators/iterator.primitives/range.iter.ops/range.iter.ops.advance/iterator_sentinel.pass.cpp b/libcxx/test/std/iterators/iterator.primitives/range.iter.ops/range.iter.ops.advance/iterator_sentinel.pass.cpp --- a/libcxx/test/std/iterators/iterator.primitives/range.iter.ops/range.iter.ops.advance/iterator_sentinel.pass.cpp +++ b/libcxx/test/std/iterators/iterator.primitives/range.iter.ops/range.iter.ops.advance/iterator_sentinel.pass.cpp @@ -35,7 +35,7 @@ auto it = stride_counting_iterator(It(first)); auto sent = assignable_sentinel(stride_counting_iterator(It(last))); std::ranges::advance(it, sent); - assert(base(it.base()) == expected); + assert(base(base(it)) == expected); assert(it.stride_count() == 0); // because we got here by assigning from last, not by incrementing } } diff --git a/libcxx/test/std/ranges/range.adaptors/range.drop/begin.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.drop/begin.pass.cpp --- a/libcxx/test/std/ranges/range.adaptors/range.drop/begin.pass.cpp +++ b/libcxx/test/std/ranges/range.adaptors/range.drop/begin.pass.cpp @@ -76,9 +76,9 @@ CountedView view8; std::ranges::drop_view dropView8(view8, 5); - assert(dropView8.begin().base().base() == globalBuff + 5); + assert(base(base(dropView8.begin())) == globalBuff + 5); assert(dropView8.begin().stride_count() == 5); - assert(dropView8.begin().base().base() == globalBuff + 5); + assert(base(base(dropView8.begin())) == globalBuff + 5); assert(dropView8.begin().stride_count() == 5); static_assert(!BeginInvocable); diff --git a/libcxx/test/support/test_iterators.h b/libcxx/test/support/test_iterators.h --- a/libcxx/test/support/test_iterators.h +++ b/libcxx/test/support/test_iterators.h @@ -10,6 +10,7 @@ #define SUPPORT_TEST_ITERATORS_H #include +#include #include #include #include @@ -646,39 +647,6 @@ void operator,(T const &) = delete; }; -template -struct iterator_concept { - using type = std::output_iterator_tag; -}; - -template -struct iterator_concept { - using type = std::input_iterator_tag; -}; - -template -struct iterator_concept { - using type = std::forward_iterator_tag; -}; - -template -struct iterator_concept { - using type = std::bidirectional_iterator_tag; -}; - -template -struct iterator_concept { - using type = std::random_access_iterator_tag; -}; - -template -struct iterator_concept { - using type = std::contiguous_iterator_tag; -}; - -template -using iterator_concept_t = typename iterator_concept::type; - template struct iter_value_or_void { using type = void; }; @@ -693,31 +661,37 @@ // * `stride_displacement`, which records the displacement of the calls. This means that both // op++/op+= will increase the displacement counter by 1, and op--/op-= will decrease the // displacement counter by 1. -template +template class stride_counting_iterator { public: - using value_type = typename iter_value_or_void::type; - using difference_type = std::iter_difference_t; - using iterator_concept = iterator_concept_t; - - stride_counting_iterator() = default; + using value_type = typename iter_value_or_void::type; + using difference_type = std::iter_difference_t; + using iterator_concept = + std::conditional_t, std::contiguous_iterator_tag, + std::conditional_t, std::random_access_iterator_tag, + std::conditional_t, std::bidirectional_iterator_tag, + std::conditional_t, std::forward_iterator_tag, + std::conditional_t, std::input_iterator_tag, + /* else */ std::output_iterator_tag + >>>>>; - constexpr explicit stride_counting_iterator(I current) : base_(std::move(current)) {} + stride_counting_iterator() requires std::default_initializable = default; - constexpr const I& base() const& { return base_; } + constexpr explicit stride_counting_iterator(It const& it) : base_(base(it)) { } - constexpr I base() && { return std::move(base_); } + friend constexpr It base(stride_counting_iterator const& it) { return It(it.base_); } constexpr difference_type stride_count() const { return stride_count_; } constexpr difference_type stride_displacement() const { return stride_displacement_; } - constexpr decltype(auto) operator*() const { return *base_; } + constexpr decltype(auto) operator*() const { return *It(base_); } - constexpr decltype(auto) operator[](difference_type const n) const { return base_[n]; } + constexpr decltype(auto) operator[](difference_type n) const { return It(base_)[n]; } constexpr stride_counting_iterator& operator++() { - ++base_; + It tmp(base_); + base_ = base(++tmp); ++stride_count_; ++stride_displacement_; return *this; @@ -726,7 +700,7 @@ constexpr void operator++(int) { ++*this; } constexpr stride_counting_iterator operator++(int) - requires std::forward_iterator + requires std::forward_iterator { auto temp = *this; ++*this; @@ -734,16 +708,17 @@ } constexpr stride_counting_iterator& operator--() - requires std::bidirectional_iterator + requires std::bidirectional_iterator { - --base_; + It tmp(base_); + base_ = base(--tmp); ++stride_count_; --stride_displacement_; return *this; } constexpr stride_counting_iterator operator--(int) - requires std::bidirectional_iterator + requires std::bidirectional_iterator { auto temp = *this; --*this; @@ -751,88 +726,84 @@ } constexpr stride_counting_iterator& operator+=(difference_type const n) - requires std::random_access_iterator + requires std::random_access_iterator { - base_ += n; + It tmp(base_); + base_ = base(tmp += n); ++stride_count_; ++stride_displacement_; return *this; } constexpr stride_counting_iterator& operator-=(difference_type const n) - requires std::random_access_iterator + requires std::random_access_iterator { - base_ -= n; + It tmp(base_); + base_ = base(tmp -= n); ++stride_count_; --stride_displacement_; return *this; } - friend constexpr stride_counting_iterator operator+(stride_counting_iterator i, difference_type const n) - requires std::random_access_iterator + friend constexpr stride_counting_iterator operator+(stride_counting_iterator it, difference_type n) + requires std::random_access_iterator { - return i += n; + return it += n; } - friend constexpr stride_counting_iterator operator+(difference_type const n, stride_counting_iterator i) - requires std::random_access_iterator + friend constexpr stride_counting_iterator operator+(difference_type n, stride_counting_iterator it) + requires std::random_access_iterator { - return i += n; + return it += n; } - friend constexpr stride_counting_iterator operator-(stride_counting_iterator i, difference_type const n) - requires std::random_access_iterator + friend constexpr stride_counting_iterator operator-(stride_counting_iterator it, difference_type n) + requires std::random_access_iterator { - return i -= n; + return it -= n; } friend constexpr difference_type operator-(stride_counting_iterator const& x, stride_counting_iterator const& y) - requires std::sized_sentinel_for + requires std::sized_sentinel_for { - return x.base() - y.base(); + return base(x) - base(y); } constexpr bool operator==(stride_counting_iterator const& other) const - requires std::sentinel_for + requires std::sentinel_for { - return base_ == other.base_; - } - - template S> - constexpr bool operator==(S const last) const - { - return base_ == last; + return It(base_) == It(other.base_); } friend constexpr bool operator<(stride_counting_iterator const& x, stride_counting_iterator const& y) - requires std::random_access_iterator + requires std::random_access_iterator { - return x.base_ < y.base_; + return It(x.base_) < It(y.base_); } friend constexpr bool operator>(stride_counting_iterator const& x, stride_counting_iterator const& y) - requires std::random_access_iterator + requires std::random_access_iterator { - return y < x; + return It(x.base_) > It(y.base_); } friend constexpr bool operator<=(stride_counting_iterator const& x, stride_counting_iterator const& y) - requires std::random_access_iterator + requires std::random_access_iterator { - return !(y < x); + return It(x.base_) <= It(y.base_); } friend constexpr bool operator>=(stride_counting_iterator const& x, stride_counting_iterator const& y) - requires std::random_access_iterator + requires std::random_access_iterator { - return !(x < y); + return It(x.base_) >= It(y.base_); } template void operator,(T const &) = delete; private: - I base_; + decltype(base(std::declval())) base_; difference_type stride_count_ = 0; difference_type stride_displacement_ = 0; };