aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNikolas Klauser <nikolasklauser@berlin.de>2022-07-24 16:46:57 +0200
committerTom Stellard <tstellar@redhat.com>2022-08-02 21:48:48 -0700
commit36fb543094a5a39e099eae96ab8b213cd8288f1a (patch)
treee3ff6e8886a828eb53aff0d0d6fc01b4ffc6b048
parent3a55353fc6f941394e6532b8ef5e59924e1ba899 (diff)
[libc++] Fix reverse_iterator::iterator_concept
Fixes https://github.com/llvm/llvm-project/issues/56504 Reviewed By: ldionne, Mordante, huixie90, #libc Spies: libcxx-commits, hewillk Differential Revision: https://reviews.llvm.org/D129794 (cherry picked from commit 7912b1f8e7c845a97411cbfc176db56861cdf116)
-rw-r--r--libcxx/include/__iterator/reverse_iterator.h4
-rw-r--r--libcxx/test/std/iterators/predef.iterators/reverse.iterators/types.compile.pass.cpp1
-rw-r--r--libcxx/test/support/test_iterators.h92
3 files changed, 93 insertions, 4 deletions
diff --git a/libcxx/include/__iterator/reverse_iterator.h b/libcxx/include/__iterator/reverse_iterator.h
index 5c344c2ee310..abc8896c0adb 100644
--- a/libcxx/include/__iterator/reverse_iterator.h
+++ b/libcxx/include/__iterator/reverse_iterator.h
@@ -70,9 +70,7 @@ public:
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<_Iter>, 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
index f8c9ce72daa9..20c3a15e90df 100644
--- 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 @@ void test_all() {
test<contiguous_iterator<char*>>();
static_assert(std::is_same_v<typename std::reverse_iterator<bidirectional_iterator<char*>>::iterator_concept, std::bidirectional_iterator_tag>);
static_assert(std::is_same_v<typename std::reverse_iterator<random_access_iterator<char*>>::iterator_concept, std::random_access_iterator_tag>);
+ static_assert(std::is_same_v<typename std::reverse_iterator<cpp20_random_access_iterator<char*>>::iterator_concept, std::random_access_iterator_tag>);
static_assert(std::is_same_v<typename std::reverse_iterator<contiguous_iterator<char*>>::iterator_concept, std::random_access_iterator_tag>);
static_assert(std::is_same_v<typename std::reverse_iterator<char*>::iterator_concept, std::random_access_iterator_tag>);
#endif
diff --git a/libcxx/test/support/test_iterators.h b/libcxx/test/support/test_iterators.h
index a1eef1a2a10a..b98c35b1d0c6 100644
--- a/libcxx/test/support/test_iterators.h
+++ b/libcxx/test/support/test_iterators.h
@@ -223,6 +223,96 @@ public:
};
#if TEST_STD_VER > 17
+
+template <std::random_access_iterator It>
+class cpp20_random_access_iterator {
+ It it_;
+
+ template <std::random_access_iterator>
+ 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<It>::value_type;
+ using difference_type = typename std::iterator_traits<It>::difference_type;
+
+ constexpr cpp20_random_access_iterator() : it_() {}
+ constexpr explicit cpp20_random_access_iterator(It it) : it_(it) {}
+
+ template <class U>
+ constexpr cpp20_random_access_iterator(const cpp20_random_access_iterator<U>& u) : it_(u.it_) {}
+
+ template <class U>
+ constexpr cpp20_random_access_iterator(cpp20_random_access_iterator<U>&& 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 <class T>
+ void operator,(T const&) = delete;
+};
+
+static_assert(std::random_access_iterator<cpp20_random_access_iterator<int*>>);
+
template <class It>
class contiguous_iterator
{
@@ -857,7 +947,7 @@ class Iterator {
// 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 <class T>
struct Proxy;