diff --git a/libcxx/include/__iterator/reverse_iterator.h b/libcxx/include/__iterator/reverse_iterator.h --- a/libcxx/include/__iterator/reverse_iterator.h +++ b/libcxx/include/__iterator/reverse_iterator.h @@ -70,9 +70,7 @@ typename iterator_traits<_Iter>::iterator_category>; using pointer = typename iterator_traits<_Iter>::pointer; #if _LIBCPP_STD_VER > 17 - using iterator_concept = _If<__is_cpp17_random_access_iterator<_Iter>::value, - random_access_iterator_tag, - bidirectional_iterator_tag>; + using iterator_concept = _If, random_access_iterator_tag, bidirectional_iterator_tag>; using value_type = iter_value_t<_Iter>; using difference_type = iter_difference_t<_Iter>; using reference = iter_reference_t<_Iter>; diff --git a/libcxx/test/std/iterators/predef.iterators/reverse.iterators/types.compile.pass.cpp b/libcxx/test/std/iterators/predef.iterators/reverse.iterators/types.compile.pass.cpp --- a/libcxx/test/std/iterators/predef.iterators/reverse.iterators/types.compile.pass.cpp +++ b/libcxx/test/std/iterators/predef.iterators/reverse.iterators/types.compile.pass.cpp @@ -116,6 +116,7 @@ test>(); static_assert(std::is_same_v>::iterator_concept, std::bidirectional_iterator_tag>); static_assert(std::is_same_v>::iterator_concept, std::random_access_iterator_tag>); + static_assert(std::is_same_v>::iterator_concept, std::random_access_iterator_tag>); static_assert(std::is_same_v>::iterator_concept, std::random_access_iterator_tag>); static_assert(std::is_same_v::iterator_concept, std::random_access_iterator_tag>); #endif 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 @@ -223,6 +223,96 @@ }; #if TEST_STD_VER > 17 + +template +class cpp20_random_access_iterator { + It it_; + + template + friend class cpp20_random_access_iterator; + +public: + using iterator_category = std::input_iterator_tag; + using iterator_concept = std::random_access_iterator_tag; + using value_type = typename std::iterator_traits::value_type; + using difference_type = typename std::iterator_traits::difference_type; + + constexpr cpp20_random_access_iterator() : it_() {} + constexpr explicit cpp20_random_access_iterator(It it) : it_(it) {} + + template + constexpr cpp20_random_access_iterator(const cpp20_random_access_iterator& u) : it_(u.it_) {} + + template + constexpr cpp20_random_access_iterator(cpp20_random_access_iterator&& u) : it_(u.it_) { + u.it_ = U(); + } + + constexpr decltype(auto) operator*() const { return *it_; } + constexpr decltype(auto) operator[](difference_type n) const { return it_[n]; } + + constexpr cpp20_random_access_iterator& operator++() { + ++it_; + return *this; + } + constexpr cpp20_random_access_iterator& operator--() { + --it_; + return *this; + } + constexpr cpp20_random_access_iterator operator++(int) { return cpp20_random_access_iterator(it_++); } + constexpr cpp20_random_access_iterator operator--(int) { return cpp20_random_access_iterator(it_--); } + + constexpr cpp20_random_access_iterator& operator+=(difference_type n) { + it_ += n; + return *this; + } + constexpr cpp20_random_access_iterator& operator-=(difference_type n) { + it_ -= n; + return *this; + } + friend constexpr cpp20_random_access_iterator operator+(cpp20_random_access_iterator x, difference_type n) { + x += n; + return x; + } + friend constexpr cpp20_random_access_iterator operator+(difference_type n, cpp20_random_access_iterator x) { + x += n; + return x; + } + friend constexpr cpp20_random_access_iterator operator-(cpp20_random_access_iterator x, difference_type n) { + x -= n; + return x; + } + friend constexpr difference_type operator-(cpp20_random_access_iterator x, cpp20_random_access_iterator y) { + return x.it_ - y.it_; + } + + friend constexpr bool operator==(const cpp20_random_access_iterator& x, const cpp20_random_access_iterator& y) { + return x.it_ == y.it_; + } + friend constexpr bool operator!=(const cpp20_random_access_iterator& x, const cpp20_random_access_iterator& y) { + return x.it_ != y.it_; + } + friend constexpr bool operator<(const cpp20_random_access_iterator& x, const cpp20_random_access_iterator& y) { + return x.it_ < y.it_; + } + friend constexpr bool operator<=(const cpp20_random_access_iterator& x, const cpp20_random_access_iterator& y) { + return x.it_ <= y.it_; + } + friend constexpr bool operator>(const cpp20_random_access_iterator& x, const cpp20_random_access_iterator& y) { + return x.it_ > y.it_; + } + friend constexpr bool operator>=(const cpp20_random_access_iterator& x, const cpp20_random_access_iterator& y) { + return x.it_ >= y.it_; + } + + friend constexpr It base(const cpp20_random_access_iterator& i) { return i.it_; } + + template + void operator,(T const&) = delete; +}; + +static_assert(std::random_access_iterator>); + template class contiguous_iterator { @@ -857,7 +947,7 @@ // on plain swap instead of ranges::iter_swap. // This class is useful for testing that if algorithms support proxy iterator // properly, i.e. calling ranges::iter_swap and ranges::iter_move instead of -// plain swap and std::move +// plain swap and std::move. template struct Proxy;