[libcxx-commits] [libcxx] [libc++][test] Test `flat_meow` with proper underlying iterators (PR #131290)
A. Jiang via libcxx-commits
libcxx-commits at lists.llvm.org
Mon Apr 7 00:27:40 PDT 2025
https://github.com/frederick-vs-ja updated https://github.com/llvm/llvm-project/pull/131290
>From 7d17dedc3e716bcfb2819da01268a1dccb617fdf Mon Sep 17 00:00:00 2001
From: "A. Jiang" <de34 at live.cn>
Date: Mon, 7 Apr 2025 15:27:20 +0800
Subject: [PATCH] [libc++][test] Test `flat_meow` with proper underlying
iterators
Flat container adaptors require the iterators of underlying containers
to be random access, and it is required that random access container
iterators must support three-way comparison
([container.reqmts]/39 - /41).
As a result, we should at least avoid testing "containers" with random
access but not three-way comparable iterators for flat container
adaptors.
This patch adds a new class template `three_way_random_access_iterator`
to `test_iterators.h` and fixes some usages of `MinSequenceContainer`
with the new iterators.
---
.../iterator_comparison.pass.cpp | 55 ++++----
.../iterator_comparison.pass.cpp | 55 ++++----
.../iterator_comparison.pass.cpp | 55 ++++----
.../iterator_comparison.pass.cpp | 55 ++++----
libcxx/test/support/MinSequenceContainer.h | 4 +-
libcxx/test/support/test_iterators.h | 129 ++++++++++++++++++
6 files changed, 236 insertions(+), 117 deletions(-)
diff --git a/libcxx/test/std/containers/container.adaptors/flat.map/flat.map.iterators/iterator_comparison.pass.cpp b/libcxx/test/std/containers/container.adaptors/flat.map/flat.map.iterators/iterator_comparison.pass.cpp
index 1975d0ed86cc8..d31daa84924fa 100644
--- a/libcxx/test/std/containers/container.adaptors/flat.map/flat.map.iterators/iterator_comparison.pass.cpp
+++ b/libcxx/test/std/containers/container.adaptors/flat.map/flat.map.iterators/iterator_comparison.pass.cpp
@@ -28,7 +28,6 @@ void test() {
using Key = typename KeyContainer::value_type;
using Value = typename ValueContainer::value_type;
using M = std::flat_map<Key, Value, std::less<Key>, KeyContainer, ValueContainer>;
- using KI = typename KeyContainer::iterator;
using I = M::iterator;
using CI = M::const_iterator;
using RI = M::reverse_iterator;
@@ -115,34 +114,32 @@ void test() {
assert(cri2 >= cri2);
assert(!(cri1 >= cri2));
- if constexpr (std::three_way_comparable<KI>) {
- static_assert(std::three_way_comparable<I>); // ...of course the wrapped iterators still support <=>.
- static_assert(std::three_way_comparable<CI>);
- static_assert(std::three_way_comparable<RI>);
- static_assert(std::three_way_comparable<CRI>);
- static_assert(std::same_as<decltype(I() <=> I()), std::strong_ordering>);
- static_assert(std::same_as<decltype(I() <=> CI()), std::strong_ordering>);
- static_assert(std::same_as<decltype(CI() <=> CI()), std::strong_ordering>);
- static_assert(std::same_as<decltype(RI() <=> RI()), std::strong_ordering>);
- static_assert(std::same_as<decltype(RI() <=> CRI()), std::strong_ordering>);
- static_assert(std::same_as<decltype(CRI() <=> CRI()), std::strong_ordering>);
-
- assert(i1 <=> i1 == std::strong_ordering::equivalent);
- assert(i1 <=> i2 == std::strong_ordering::less);
- assert(i2 <=> i1 == std::strong_ordering::greater);
-
- assert(ci1 <=> ci1 == std::strong_ordering::equivalent);
- assert(ci1 <=> ci2 == std::strong_ordering::less);
- assert(ci2 <=> ci1 == std::strong_ordering::greater);
-
- assert(ri1 <=> ri1 == std::strong_ordering::equivalent);
- assert(ri1 <=> ri2 == std::strong_ordering::less);
- assert(ri2 <=> ri1 == std::strong_ordering::greater);
-
- assert(cri1 <=> cri1 == std::strong_ordering::equivalent);
- assert(cri1 <=> cri2 == std::strong_ordering::less);
- assert(cri2 <=> cri1 == std::strong_ordering::greater);
- }
+ static_assert(std::three_way_comparable<I>); // ...of course the wrapped iterators still support <=>.
+ static_assert(std::three_way_comparable<CI>);
+ static_assert(std::three_way_comparable<RI>);
+ static_assert(std::three_way_comparable<CRI>);
+ static_assert(std::same_as<decltype(I() <=> I()), std::strong_ordering>);
+ static_assert(std::same_as<decltype(I() <=> CI()), std::strong_ordering>);
+ static_assert(std::same_as<decltype(CI() <=> CI()), std::strong_ordering>);
+ static_assert(std::same_as<decltype(RI() <=> RI()), std::strong_ordering>);
+ static_assert(std::same_as<decltype(RI() <=> CRI()), std::strong_ordering>);
+ static_assert(std::same_as<decltype(CRI() <=> CRI()), std::strong_ordering>);
+
+ assert(i1 <=> i1 == std::strong_ordering::equivalent);
+ assert(i1 <=> i2 == std::strong_ordering::less);
+ assert(i2 <=> i1 == std::strong_ordering::greater);
+
+ assert(ci1 <=> ci1 == std::strong_ordering::equivalent);
+ assert(ci1 <=> ci2 == std::strong_ordering::less);
+ assert(ci2 <=> ci1 == std::strong_ordering::greater);
+
+ assert(ri1 <=> ri1 == std::strong_ordering::equivalent);
+ assert(ri1 <=> ri2 == std::strong_ordering::less);
+ assert(ri2 <=> ri1 == std::strong_ordering::greater);
+
+ assert(cri1 <=> cri1 == std::strong_ordering::equivalent);
+ assert(cri1 <=> cri2 == std::strong_ordering::less);
+ assert(cri2 <=> cri1 == std::strong_ordering::greater);
}
int main(int, char**) {
diff --git a/libcxx/test/std/containers/container.adaptors/flat.multimap/flat.multimap.iterators/iterator_comparison.pass.cpp b/libcxx/test/std/containers/container.adaptors/flat.multimap/flat.multimap.iterators/iterator_comparison.pass.cpp
index f1b2cad743e23..c2f4f608ba18a 100644
--- a/libcxx/test/std/containers/container.adaptors/flat.multimap/flat.multimap.iterators/iterator_comparison.pass.cpp
+++ b/libcxx/test/std/containers/container.adaptors/flat.multimap/flat.multimap.iterators/iterator_comparison.pass.cpp
@@ -28,7 +28,6 @@ void test() {
using Key = typename KeyContainer::value_type;
using Value = typename ValueContainer::value_type;
using M = std::flat_multimap<Key, Value, std::less<Key>, KeyContainer, ValueContainer>;
- using KI = typename KeyContainer::iterator;
using I = M::iterator;
using CI = M::const_iterator;
using RI = M::reverse_iterator;
@@ -115,34 +114,32 @@ void test() {
assert(cri2 >= cri2);
assert(!(cri1 >= cri2));
- if constexpr (std::three_way_comparable<KI>) {
- static_assert(std::three_way_comparable<I>); // ...of course the wrapped iterators still support <=>.
- static_assert(std::three_way_comparable<CI>);
- static_assert(std::three_way_comparable<RI>);
- static_assert(std::three_way_comparable<CRI>);
- static_assert(std::same_as<decltype(I() <=> I()), std::strong_ordering>);
- static_assert(std::same_as<decltype(I() <=> CI()), std::strong_ordering>);
- static_assert(std::same_as<decltype(CI() <=> CI()), std::strong_ordering>);
- static_assert(std::same_as<decltype(RI() <=> RI()), std::strong_ordering>);
- static_assert(std::same_as<decltype(RI() <=> CRI()), std::strong_ordering>);
- static_assert(std::same_as<decltype(CRI() <=> CRI()), std::strong_ordering>);
-
- assert(i1 <=> i1 == std::strong_ordering::equivalent);
- assert(i1 <=> i2 == std::strong_ordering::less);
- assert(i2 <=> i1 == std::strong_ordering::greater);
-
- assert(ci1 <=> ci1 == std::strong_ordering::equivalent);
- assert(ci1 <=> ci2 == std::strong_ordering::less);
- assert(ci2 <=> ci1 == std::strong_ordering::greater);
-
- assert(ri1 <=> ri1 == std::strong_ordering::equivalent);
- assert(ri1 <=> ri2 == std::strong_ordering::less);
- assert(ri2 <=> ri1 == std::strong_ordering::greater);
-
- assert(cri1 <=> cri1 == std::strong_ordering::equivalent);
- assert(cri1 <=> cri2 == std::strong_ordering::less);
- assert(cri2 <=> cri1 == std::strong_ordering::greater);
- }
+ static_assert(std::three_way_comparable<I>); // ...of course the wrapped iterators still support <=>.
+ static_assert(std::three_way_comparable<CI>);
+ static_assert(std::three_way_comparable<RI>);
+ static_assert(std::three_way_comparable<CRI>);
+ static_assert(std::same_as<decltype(I() <=> I()), std::strong_ordering>);
+ static_assert(std::same_as<decltype(I() <=> CI()), std::strong_ordering>);
+ static_assert(std::same_as<decltype(CI() <=> CI()), std::strong_ordering>);
+ static_assert(std::same_as<decltype(RI() <=> RI()), std::strong_ordering>);
+ static_assert(std::same_as<decltype(RI() <=> CRI()), std::strong_ordering>);
+ static_assert(std::same_as<decltype(CRI() <=> CRI()), std::strong_ordering>);
+
+ assert(i1 <=> i1 == std::strong_ordering::equivalent);
+ assert(i1 <=> i2 == std::strong_ordering::less);
+ assert(i2 <=> i1 == std::strong_ordering::greater);
+
+ assert(ci1 <=> ci1 == std::strong_ordering::equivalent);
+ assert(ci1 <=> ci2 == std::strong_ordering::less);
+ assert(ci2 <=> ci1 == std::strong_ordering::greater);
+
+ assert(ri1 <=> ri1 == std::strong_ordering::equivalent);
+ assert(ri1 <=> ri2 == std::strong_ordering::less);
+ assert(ri2 <=> ri1 == std::strong_ordering::greater);
+
+ assert(cri1 <=> cri1 == std::strong_ordering::equivalent);
+ assert(cri1 <=> cri2 == std::strong_ordering::less);
+ assert(cri2 <=> cri1 == std::strong_ordering::greater);
}
int main(int, char**) {
diff --git a/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.iterators/iterator_comparison.pass.cpp b/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.iterators/iterator_comparison.pass.cpp
index d26e3446072ef..cbf69d6e04904 100644
--- a/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.iterators/iterator_comparison.pass.cpp
+++ b/libcxx/test/std/containers/container.adaptors/flat.multiset/flat.multiset.iterators/iterator_comparison.pass.cpp
@@ -27,7 +27,6 @@ template <class KeyContainer>
void test_one() {
using Key = typename KeyContainer::value_type;
using M = std::flat_multiset<Key, std::less<Key>, KeyContainer>;
- using KI = typename KeyContainer::iterator;
using I = M::iterator;
using CI = M::const_iterator;
using RI = M::reverse_iterator;
@@ -114,34 +113,32 @@ void test_one() {
assert(cri2 >= cri2);
assert(!(cri1 >= cri2));
- if constexpr (std::three_way_comparable<KI>) {
- static_assert(std::three_way_comparable<I>); // ...of course the wrapped iterators still support <=>.
- static_assert(std::three_way_comparable<CI>);
- static_assert(std::three_way_comparable<RI>);
- static_assert(std::three_way_comparable<CRI>);
- static_assert(std::same_as<decltype(I() <=> I()), std::strong_ordering>);
- static_assert(std::same_as<decltype(I() <=> CI()), std::strong_ordering>);
- static_assert(std::same_as<decltype(CI() <=> CI()), std::strong_ordering>);
- static_assert(std::same_as<decltype(RI() <=> RI()), std::strong_ordering>);
- static_assert(std::same_as<decltype(RI() <=> CRI()), std::strong_ordering>);
- static_assert(std::same_as<decltype(CRI() <=> CRI()), std::strong_ordering>);
-
- assert(i1 <=> i1 == std::strong_ordering::equivalent);
- assert(i1 <=> i2 == std::strong_ordering::less);
- assert(i2 <=> i1 == std::strong_ordering::greater);
-
- assert(ci1 <=> ci1 == std::strong_ordering::equivalent);
- assert(ci1 <=> ci2 == std::strong_ordering::less);
- assert(ci2 <=> ci1 == std::strong_ordering::greater);
-
- assert(ri1 <=> ri1 == std::strong_ordering::equivalent);
- assert(ri1 <=> ri2 == std::strong_ordering::less);
- assert(ri2 <=> ri1 == std::strong_ordering::greater);
-
- assert(cri1 <=> cri1 == std::strong_ordering::equivalent);
- assert(cri1 <=> cri2 == std::strong_ordering::less);
- assert(cri2 <=> cri1 == std::strong_ordering::greater);
- }
+ static_assert(std::three_way_comparable<I>); // ...of course the wrapped iterators still support <=>.
+ static_assert(std::three_way_comparable<CI>);
+ static_assert(std::three_way_comparable<RI>);
+ static_assert(std::three_way_comparable<CRI>);
+ static_assert(std::same_as<decltype(I() <=> I()), std::strong_ordering>);
+ static_assert(std::same_as<decltype(I() <=> CI()), std::strong_ordering>);
+ static_assert(std::same_as<decltype(CI() <=> CI()), std::strong_ordering>);
+ static_assert(std::same_as<decltype(RI() <=> RI()), std::strong_ordering>);
+ static_assert(std::same_as<decltype(RI() <=> CRI()), std::strong_ordering>);
+ static_assert(std::same_as<decltype(CRI() <=> CRI()), std::strong_ordering>);
+
+ assert(i1 <=> i1 == std::strong_ordering::equivalent);
+ assert(i1 <=> i2 == std::strong_ordering::less);
+ assert(i2 <=> i1 == std::strong_ordering::greater);
+
+ assert(ci1 <=> ci1 == std::strong_ordering::equivalent);
+ assert(ci1 <=> ci2 == std::strong_ordering::less);
+ assert(ci2 <=> ci1 == std::strong_ordering::greater);
+
+ assert(ri1 <=> ri1 == std::strong_ordering::equivalent);
+ assert(ri1 <=> ri2 == std::strong_ordering::less);
+ assert(ri2 <=> ri1 == std::strong_ordering::greater);
+
+ assert(cri1 <=> cri1 == std::strong_ordering::equivalent);
+ assert(cri1 <=> cri2 == std::strong_ordering::less);
+ assert(cri2 <=> cri1 == std::strong_ordering::greater);
}
void test() {
diff --git a/libcxx/test/std/containers/container.adaptors/flat.set/flat.set.iterators/iterator_comparison.pass.cpp b/libcxx/test/std/containers/container.adaptors/flat.set/flat.set.iterators/iterator_comparison.pass.cpp
index 3027cdd4076ee..ad1bc8facc92e 100644
--- a/libcxx/test/std/containers/container.adaptors/flat.set/flat.set.iterators/iterator_comparison.pass.cpp
+++ b/libcxx/test/std/containers/container.adaptors/flat.set/flat.set.iterators/iterator_comparison.pass.cpp
@@ -27,7 +27,6 @@ template <class KeyContainer>
void test_one() {
using Key = typename KeyContainer::value_type;
using M = std::flat_set<Key, std::less<Key>, KeyContainer>;
- using KI = typename KeyContainer::iterator;
using I = M::iterator;
using CI = M::const_iterator;
using RI = M::reverse_iterator;
@@ -114,34 +113,32 @@ void test_one() {
assert(cri2 >= cri2);
assert(!(cri1 >= cri2));
- if constexpr (std::three_way_comparable<KI>) {
- static_assert(std::three_way_comparable<I>); // ...of course the wrapped iterators still support <=>.
- static_assert(std::three_way_comparable<CI>);
- static_assert(std::three_way_comparable<RI>);
- static_assert(std::three_way_comparable<CRI>);
- static_assert(std::same_as<decltype(I() <=> I()), std::strong_ordering>);
- static_assert(std::same_as<decltype(I() <=> CI()), std::strong_ordering>);
- static_assert(std::same_as<decltype(CI() <=> CI()), std::strong_ordering>);
- static_assert(std::same_as<decltype(RI() <=> RI()), std::strong_ordering>);
- static_assert(std::same_as<decltype(RI() <=> CRI()), std::strong_ordering>);
- static_assert(std::same_as<decltype(CRI() <=> CRI()), std::strong_ordering>);
-
- assert(i1 <=> i1 == std::strong_ordering::equivalent);
- assert(i1 <=> i2 == std::strong_ordering::less);
- assert(i2 <=> i1 == std::strong_ordering::greater);
-
- assert(ci1 <=> ci1 == std::strong_ordering::equivalent);
- assert(ci1 <=> ci2 == std::strong_ordering::less);
- assert(ci2 <=> ci1 == std::strong_ordering::greater);
-
- assert(ri1 <=> ri1 == std::strong_ordering::equivalent);
- assert(ri1 <=> ri2 == std::strong_ordering::less);
- assert(ri2 <=> ri1 == std::strong_ordering::greater);
-
- assert(cri1 <=> cri1 == std::strong_ordering::equivalent);
- assert(cri1 <=> cri2 == std::strong_ordering::less);
- assert(cri2 <=> cri1 == std::strong_ordering::greater);
- }
+ static_assert(std::three_way_comparable<I>); // ...of course the wrapped iterators still support <=>.
+ static_assert(std::three_way_comparable<CI>);
+ static_assert(std::three_way_comparable<RI>);
+ static_assert(std::three_way_comparable<CRI>);
+ static_assert(std::same_as<decltype(I() <=> I()), std::strong_ordering>);
+ static_assert(std::same_as<decltype(I() <=> CI()), std::strong_ordering>);
+ static_assert(std::same_as<decltype(CI() <=> CI()), std::strong_ordering>);
+ static_assert(std::same_as<decltype(RI() <=> RI()), std::strong_ordering>);
+ static_assert(std::same_as<decltype(RI() <=> CRI()), std::strong_ordering>);
+ static_assert(std::same_as<decltype(CRI() <=> CRI()), std::strong_ordering>);
+
+ assert(i1 <=> i1 == std::strong_ordering::equivalent);
+ assert(i1 <=> i2 == std::strong_ordering::less);
+ assert(i2 <=> i1 == std::strong_ordering::greater);
+
+ assert(ci1 <=> ci1 == std::strong_ordering::equivalent);
+ assert(ci1 <=> ci2 == std::strong_ordering::less);
+ assert(ci2 <=> ci1 == std::strong_ordering::greater);
+
+ assert(ri1 <=> ri1 == std::strong_ordering::equivalent);
+ assert(ri1 <=> ri2 == std::strong_ordering::less);
+ assert(ri2 <=> ri1 == std::strong_ordering::greater);
+
+ assert(cri1 <=> cri1 == std::strong_ordering::equivalent);
+ assert(cri1 <=> cri2 == std::strong_ordering::less);
+ assert(cri2 <=> cri1 == std::strong_ordering::greater);
}
void test() {
diff --git a/libcxx/test/support/MinSequenceContainer.h b/libcxx/test/support/MinSequenceContainer.h
index 7fee4dd0fbdc1..6e61aff06344b 100644
--- a/libcxx/test/support/MinSequenceContainer.h
+++ b/libcxx/test/support/MinSequenceContainer.h
@@ -14,7 +14,9 @@
#include "test_iterators.h"
-template <class T, class Iterator = random_access_iterator<T*>, class ConstIterator = random_access_iterator<const T*>>
+template <class T,
+ class Iterator = three_way_random_access_iterator<T*>,
+ class ConstIterator = three_way_random_access_iterator<const T*>>
struct MinSequenceContainer {
using value_type = T;
using difference_type = int;
diff --git a/libcxx/test/support/test_iterators.h b/libcxx/test/support/test_iterators.h
index 702b82b9e15a7..0335a4c561017 100644
--- a/libcxx/test/support/test_iterators.h
+++ b/libcxx/test/support/test_iterators.h
@@ -267,6 +267,135 @@ template <class It>
random_access_iterator(It) -> random_access_iterator<It>;
#endif
+// Since C++20, a container iterator type that is random access is also required to support three-way comparison.
+// See C++20 [tab:container.req], C++23 [container.reqmts]/39 - /41.
+template <class It>
+class three_way_random_access_iterator {
+ It it_;
+ support::double_move_tracker tracker_;
+
+ template <class U>
+ friend class three_way_random_access_iterator;
+
+public:
+ typedef std::random_access_iterator_tag iterator_category;
+ typedef typename std::iterator_traits<It>::value_type value_type;
+ typedef typename std::iterator_traits<It>::difference_type difference_type;
+ typedef It pointer;
+ typedef typename std::iterator_traits<It>::reference reference;
+
+ TEST_CONSTEXPR three_way_random_access_iterator() : it_() {}
+ TEST_CONSTEXPR explicit three_way_random_access_iterator(It it) : it_(it) {}
+
+ template <class U>
+ TEST_CONSTEXPR three_way_random_access_iterator(const three_way_random_access_iterator<U>& u)
+ : it_(u.it_), tracker_(u.tracker_) {}
+
+ template <class U, class = typename std::enable_if<std::is_default_constructible<U>::value>::type>
+ TEST_CONSTEXPR_CXX14 three_way_random_access_iterator(three_way_random_access_iterator<U>&& u)
+ : it_(std::move(u.it_)), tracker_(std::move(u.tracker_)) {
+ u.it_ = U();
+ }
+
+ TEST_CONSTEXPR_CXX14 reference operator*() const { return *it_; }
+ TEST_CONSTEXPR_CXX14 reference operator[](difference_type n) const { return it_[n]; }
+
+ TEST_CONSTEXPR_CXX14 three_way_random_access_iterator& operator++() {
+ ++it_;
+ return *this;
+ }
+ TEST_CONSTEXPR_CXX14 three_way_random_access_iterator& operator--() {
+ --it_;
+ return *this;
+ }
+ TEST_CONSTEXPR_CXX14 three_way_random_access_iterator operator++(int) {
+ return three_way_random_access_iterator(it_++);
+ }
+ TEST_CONSTEXPR_CXX14 three_way_random_access_iterator operator--(int) {
+ return three_way_random_access_iterator(it_--);
+ }
+
+ TEST_CONSTEXPR_CXX14 three_way_random_access_iterator& operator+=(difference_type n) {
+ it_ += n;
+ return *this;
+ }
+ TEST_CONSTEXPR_CXX14 three_way_random_access_iterator& operator-=(difference_type n) {
+ it_ -= n;
+ return *this;
+ }
+ friend TEST_CONSTEXPR_CXX14 three_way_random_access_iterator
+ operator+(three_way_random_access_iterator x, difference_type n) {
+ x += n;
+ return x;
+ }
+ friend TEST_CONSTEXPR_CXX14 three_way_random_access_iterator
+ operator+(difference_type n, three_way_random_access_iterator x) {
+ x += n;
+ return x;
+ }
+ friend TEST_CONSTEXPR_CXX14 three_way_random_access_iterator
+ operator-(three_way_random_access_iterator x, difference_type n) {
+ x -= n;
+ return x;
+ }
+ friend TEST_CONSTEXPR difference_type
+ operator-(three_way_random_access_iterator x, three_way_random_access_iterator y) {
+ return x.it_ - y.it_;
+ }
+
+ friend TEST_CONSTEXPR bool
+ operator==(const three_way_random_access_iterator& x, const three_way_random_access_iterator& y) {
+ return x.it_ == y.it_;
+ }
+#if TEST_STD_VER < 20
+ friend TEST_CONSTEXPR bool
+ operator!=(const three_way_random_access_iterator& x, const three_way_random_access_iterator& y) {
+ return x.it_ != y.it_;
+ }
+#endif
+ friend TEST_CONSTEXPR bool
+ operator<(const three_way_random_access_iterator& x, const three_way_random_access_iterator& y) {
+ return x.it_ < y.it_;
+ }
+ friend TEST_CONSTEXPR bool
+ operator<=(const three_way_random_access_iterator& x, const three_way_random_access_iterator& y) {
+ return x.it_ <= y.it_;
+ }
+ friend TEST_CONSTEXPR bool
+ operator>(const three_way_random_access_iterator& x, const three_way_random_access_iterator& y) {
+ return x.it_ > y.it_;
+ }
+ friend TEST_CONSTEXPR bool
+ operator>=(const three_way_random_access_iterator& x, const three_way_random_access_iterator& y) {
+ return x.it_ >= y.it_;
+ }
+#if TEST_STD_VER >= 20
+ friend constexpr std::strong_ordering
+ operator<=>(const three_way_random_access_iterator& x, const three_way_random_access_iterator& y) {
+ if constexpr (std::three_way_comparable<It>) {
+ return x.it_ <=> y.it_;
+ } else {
+ if (x.it_ < y.it_) {
+ return std::strong_ordering::less;
+ } else if (y.it_ < x.it_) {
+ return std::strong_ordering::greater;
+ } else {
+ return std::strong_ordering::equal;
+ }
+ }
+ }
+#endif
+
+ friend TEST_CONSTEXPR It base(const three_way_random_access_iterator& i) { return i.it_; }
+
+ template <class T>
+ void operator,(T const&) = delete;
+};
+#if TEST_STD_VER > 14
+template <class It>
+three_way_random_access_iterator(It) -> three_way_random_access_iterator<It>;
+#endif
+
#if TEST_STD_VER > 17
template <std::random_access_iterator It>
More information about the libcxx-commits
mailing list