public inbox for gcc-cvs@sourceware.org
help / color / mirror / Atom feed
* [gcc/devel/gccgo] libstdc++: Add comparison operators to sequence containers
@ 2020-07-12 17:18 Ian Lance Taylor
0 siblings, 0 replies; only message in thread
From: Ian Lance Taylor @ 2020-07-12 17:18 UTC (permalink / raw)
To: gcc-cvs, libstdc++-cvs
https://gcc.gnu.org/g:bd2420f8faaf4bb33310e82f7dd45c5e33476c87
commit bd2420f8faaf4bb33310e82f7dd45c5e33476c87
Author: Jonathan Wakely <jwakely@redhat.com>
Date: Fri Apr 17 23:41:04 2020 +0100
libstdc++: Add comparison operators to sequence containers
Some more C++20 changes from P1614R2, "The Mothership has Landed".
This implements <=> for sequence containers (and the __normal_iterator
and _Pointer_adapter class templates).
* include/bits/forward_list.h (forward_list): Define operator<=> and
remove redundant comparison operators for C++20.
* include/bits/stl_bvector.h (vector<bool, Alloc>): Likewise.
* include/bits/stl_deque.h (deque): Likewise.
* include/bits/stl_iterator.h (__normal_iterator): Likewise.
* include/bits/stl_list.h (list): Likewise.
* include/bits/stl_vector.h (vector): Likewise.
* include/debug/deque (__gnu_debug::deque): Likewise.
* include/debug/forward_list (__gnu_debug::forward_list): Likewise.
* include/debug/list (__gnu_debug::list): Likewise.
* include/debug/safe_iterator.h (__gnu_debug::_Safe_iterator):
Likewise.
* include/debug/vector (__gnu_debug::vector): Likewise.
* include/ext/pointer.h (__gnu_cxx::_Pointer_adapter): Define
operator<=> for C++20.
* testsuite/23_containers/deque/operators/cmp_c++20.cc: New test.
* testsuite/23_containers/forward_list/cmp_c++20.cc: New test.
* testsuite/23_containers/list/cmp_c++20.cc: New test.
* testsuite/23_containers/vector/bool/cmp_c++20.cc: New test.
* testsuite/23_containers/vector/cmp_c++20.cc: New test.
Diff:
---
libstdc++-v3/ChangeLog | 21 +++
libstdc++-v3/include/bits/forward_list.h | 28 +++-
libstdc++-v3/include/bits/stl_bvector.h | 13 +-
libstdc++-v3/include/bits/stl_deque.h | 57 +++++++-
libstdc++-v3/include/bits/stl_iterator.h | 37 ++---
libstdc++-v3/include/bits/stl_list.h | 26 ++++
libstdc++-v3/include/bits/stl_vector.h | 25 ++++
libstdc++-v3/include/debug/deque | 7 +
libstdc++-v3/include/debug/forward_list | 8 +
libstdc++-v3/include/debug/list | 7 +
libstdc++-v3/include/debug/safe_iterator.h | 21 +++
libstdc++-v3/include/debug/vector | 7 +
libstdc++-v3/include/ext/pointer.h | 8 +-
.../23_containers/deque/operators/cmp_c++20.cc | 161 +++++++++++++++++++++
.../23_containers/forward_list/cmp_c++20.cc | 138 ++++++++++++++++++
.../testsuite/23_containers/list/cmp_c++20.cc | 138 ++++++++++++++++++
.../23_containers/vector/bool/cmp_c++20.cc | 73 ++++++++++
.../testsuite/23_containers/vector/cmp_c++20.cc | 161 +++++++++++++++++++++
18 files changed, 908 insertions(+), 28 deletions(-)
diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog
index d24c757d00a..de9323bebe0 100644
--- a/libstdc++-v3/ChangeLog
+++ b/libstdc++-v3/ChangeLog
@@ -1,5 +1,26 @@
2020-04-17 Jonathan Wakely <jwakely@redhat.com>
+ * include/bits/forward_list.h (forward_list): Define operator<=> and
+ remove redundant comparison operators for C++20.
+ * include/bits/stl_bvector.h (vector<bool, Alloc>): Likewise.
+ * include/bits/stl_deque.h (deque): Likewise.
+ * include/bits/stl_iterator.h (__normal_iterator): Likewise.
+ * include/bits/stl_list.h (list): Likewise.
+ * include/bits/stl_vector.h (vector): Likewise.
+ * include/debug/deque (__gnu_debug::deque): Likewise.
+ * include/debug/forward_list (__gnu_debug::forward_list): Likewise.
+ * include/debug/list (__gnu_debug::list): Likewise.
+ * include/debug/safe_iterator.h (__gnu_debug::_Safe_iterator):
+ Likewise.
+ * include/debug/vector (__gnu_debug::vector): Likewise.
+ * include/ext/pointer.h (__gnu_cxx::_Pointer_adapter): Define
+ operator<=> for C++20.
+ * testsuite/23_containers/deque/operators/cmp_c++20.cc: New test.
+ * testsuite/23_containers/forward_list/cmp_c++20.cc: New test.
+ * testsuite/23_containers/list/cmp_c++20.cc: New test.
+ * testsuite/23_containers/vector/bool/cmp_c++20.cc: New test.
+ * testsuite/23_containers/vector/cmp_c++20.cc: New test.
+
* include/bits/basic_string.h (basic_string): Define operator<=> and
remove redundant comparison operators for C++20.
* include/bits/char_traits.h (__gnu_cxx::char_traits, char_traits):
diff --git a/libstdc++-v3/include/bits/forward_list.h b/libstdc++-v3/include/bits/forward_list.h
index b926d45f205..49b2a973718 100644
--- a/libstdc++-v3/include/bits/forward_list.h
+++ b/libstdc++-v3/include/bits/forward_list.h
@@ -180,13 +180,14 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
operator==(const _Self& __x, const _Self& __y) noexcept
{ return __x._M_node == __y._M_node; }
-
+#if __cpp_impl_three_way_comparison < 201907L
/**
* @brief Forward list iterator inequality comparison.
*/
friend bool
operator!=(const _Self& __x, const _Self& __y) noexcept
{ return __x._M_node != __y._M_node; }
+#endif
_Self
_M_next() const noexcept
@@ -258,12 +259,14 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
operator==(const _Self& __x, const _Self& __y) noexcept
{ return __x._M_node == __y._M_node; }
+#if __cpp_impl_three_way_comparison < 201907L
/**
* @brief Forward list const_iterator inequality comparison.
*/
friend bool
operator!=(const _Self& __x, const _Self& __y) noexcept
{ return __x._M_node != __y._M_node; }
+#endif
_Self
_M_next() const noexcept
@@ -1426,6 +1429,28 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
operator==(const forward_list<_Tp, _Alloc>& __lx,
const forward_list<_Tp, _Alloc>& __ly);
+#if __cpp_lib_three_way_comparison
+ /**
+ * @brief Forward list ordering relation.
+ * @param __x A `forward_list`.
+ * @param __y A `forward_list` of the same type as `__x`.
+ * @return A value indicating whether `__x` is less than, equal to,
+ * greater than, or incomparable with `__y`.
+ *
+ * See `std::lexicographical_compare_three_way()` for how the determination
+ * is made. This operator is used to synthesize relational operators like
+ * `<` and `>=` etc.
+ */
+ template<typename _Tp, typename _Alloc>
+ inline __detail::__synth3way_t<_Tp>
+ operator<=>(const forward_list<_Tp, _Alloc>& __x,
+ const forward_list<_Tp, _Alloc>& __y)
+ {
+ return std::lexicographical_compare_three_way(__x.begin(), __x.end(),
+ __y.begin(), __y.end(),
+ __detail::__synth3way);
+ }
+#else
/**
* @brief Forward list ordering relation.
* @param __lx A %forward_list.
@@ -1472,6 +1497,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
operator<=(const forward_list<_Tp, _Alloc>& __lx,
const forward_list<_Tp, _Alloc>& __ly)
{ return !(__ly < __lx); }
+#endif // three-way comparison
/// See std::forward_list::swap().
template<typename _Tp, typename _Alloc>
diff --git a/libstdc++-v3/include/bits/stl_bvector.h b/libstdc++-v3/include/bits/stl_bvector.h
index 1b16bc3b7d8..f245e52b25d 100644
--- a/libstdc++-v3/include/bits/stl_bvector.h
+++ b/libstdc++-v3/include/bits/stl_bvector.h
@@ -182,10 +182,20 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
_M_offset = static_cast<unsigned int>(__n);
}
- friend bool
+ friend _GLIBCXX20_CONSTEXPR bool
operator==(const _Bit_iterator_base& __x, const _Bit_iterator_base& __y)
{ return __x._M_p == __y._M_p && __x._M_offset == __y._M_offset; }
+#if __cpp_lib_three_way_comparison
+ friend constexpr strong_ordering
+ operator<=>(const _Bit_iterator_base& __x, const _Bit_iterator_base& __y)
+ noexcept
+ {
+ if (const auto __cmp = __x._M_p <=> __y._M_p; __cmp != 0)
+ return __cmp;
+ return __x._M_offset <=> __y._M_offset;
+ }
+#else
friend bool
operator<(const _Bit_iterator_base& __x, const _Bit_iterator_base& __y)
{
@@ -208,6 +218,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
friend bool
operator>=(const _Bit_iterator_base& __x, const _Bit_iterator_base& __y)
{ return !(__x < __y); }
+#endif // three-way comparison
friend ptrdiff_t
operator-(const _Bit_iterator_base& __x, const _Bit_iterator_base& __y)
diff --git a/libstdc++-v3/include/bits/stl_deque.h b/libstdc++-v3/include/bits/stl_deque.h
index c1af637f67b..3959dd7899d 100644
--- a/libstdc++-v3/include/bits/stl_deque.h
+++ b/libstdc++-v3/include/bits/stl_deque.h
@@ -63,6 +63,9 @@
#include <initializer_list>
#include <bits/stl_uninitialized.h> // for __is_bitwise_relocatable
#endif
+#if __cplusplus > 201703L
+# include <compare>
+#endif
#include <debug/assertions.h>
@@ -266,14 +269,24 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
{ return __x._M_cur == __y._M_cur; }
// Note: we also provide overloads whose operands are of the same type in
- // order to avoid ambiguous overload resolution when std::rel_ops operators
- // are in scope (for additional details, see libstdc++/3628)
+ // order to avoid ambiguous overload resolution when std::rel_ops
+ // operators are in scope (for additional details, see libstdc++/3628)
template<typename _RefR, typename _PtrR>
friend bool
operator==(const _Self& __x,
- const _Deque_iterator<_Tp, _RefR, _PtrR>& __y) _GLIBCXX_NOEXCEPT
+ const _Deque_iterator<_Tp, _RefR, _PtrR>& __y)
+ _GLIBCXX_NOEXCEPT
{ return __x._M_cur == __y._M_cur; }
+#if __cpp_lib_three_way_comparison
+ friend strong_ordering
+ operator<=>(const _Self& __x, const _Self& __y) noexcept
+ {
+ if (const auto __cmp = __x._M_node <=> __y._M_node; __cmp != 0)
+ return __cmp;
+ return __x._M_cur <=> __y._M_cur;
+ }
+#else
friend bool
operator!=(const _Self& __x, const _Self& __y) _GLIBCXX_NOEXCEPT
{ return !(__x == __y); }
@@ -281,7 +294,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
template<typename _RefR, typename _PtrR>
friend bool
operator!=(const _Self& __x,
- const _Deque_iterator<_Tp, _RefR, _PtrR>& __y) _GLIBCXX_NOEXCEPT
+ const _Deque_iterator<_Tp, _RefR, _PtrR>& __y)
+ _GLIBCXX_NOEXCEPT
{ return !(__x == __y); }
friend bool
@@ -294,7 +308,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
template<typename _RefR, typename _PtrR>
friend bool
operator<(const _Self& __x,
- const _Deque_iterator<_Tp, _RefR, _PtrR>& __y) _GLIBCXX_NOEXCEPT
+ const _Deque_iterator<_Tp, _RefR, _PtrR>& __y)
+ _GLIBCXX_NOEXCEPT
{
return (__x._M_node == __y._M_node)
? (__x._M_cur < __y._M_cur) : (__x._M_node < __y._M_node);
@@ -307,7 +322,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
template<typename _RefR, typename _PtrR>
friend bool
operator>(const _Self& __x,
- const _Deque_iterator<_Tp, _RefR, _PtrR>& __y) _GLIBCXX_NOEXCEPT
+ const _Deque_iterator<_Tp, _RefR, _PtrR>& __y)
+ _GLIBCXX_NOEXCEPT
{ return __y < __x; }
friend bool
@@ -317,7 +333,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
template<typename _RefR, typename _PtrR>
friend bool
operator<=(const _Self& __x,
- const _Deque_iterator<_Tp, _RefR, _PtrR>& __y) _GLIBCXX_NOEXCEPT
+ const _Deque_iterator<_Tp, _RefR, _PtrR>& __y)
+ _GLIBCXX_NOEXCEPT
{ return !(__y < __x); }
friend bool
@@ -327,8 +344,10 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
template<typename _RefR, typename _PtrR>
friend bool
operator>=(const _Self& __x,
- const _Deque_iterator<_Tp, _RefR, _PtrR>& __y) _GLIBCXX_NOEXCEPT
+ const _Deque_iterator<_Tp, _RefR, _PtrR>& __y)
+ _GLIBCXX_NOEXCEPT
{ return !(__x < __y); }
+#endif // three-way comparison
friend difference_type
operator-(const _Self& __x, const _Self& __y) _GLIBCXX_NOEXCEPT
@@ -2223,6 +2242,27 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
{ return __x.size() == __y.size()
&& std::equal(__x.begin(), __x.end(), __y.begin()); }
+#if __cpp_lib_three_way_comparison
+ /**
+ * @brief Deque ordering relation.
+ * @param __x A `deque`.
+ * @param __y A `deque` of the same type as `__x`.
+ * @return A value indicating whether `__x` is less than, equal to,
+ * greater than, or incomparable with `__y`.
+ *
+ * See `std::lexicographical_compare_three_way()` for how the determination
+ * is made. This operator is used to synthesize relational operators like
+ * `<` and `>=` etc.
+ */
+ template<typename _Tp, typename _Alloc>
+ inline __detail::__synth3way_t<_Tp>
+ operator<=>(const deque<_Tp, _Alloc>& __x, const deque<_Tp, _Alloc>& __y)
+ {
+ return std::lexicographical_compare_three_way(__x.begin(), __x.end(),
+ __y.begin(), __y.end(),
+ __detail::__synth3way);
+ }
+#else
/**
* @brief Deque ordering relation.
* @param __x A %deque.
@@ -2263,6 +2303,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
inline bool
operator>=(const deque<_Tp, _Alloc>& __x, const deque<_Tp, _Alloc>& __y)
{ return !(__x < __y); }
+#endif // three-way comparison
/// See std::deque::swap().
template<typename _Tp, typename _Alloc>
diff --git a/libstdc++-v3/include/bits/stl_iterator.h b/libstdc++-v3/include/bits/stl_iterator.h
index d7972b71998..5bfdce6af2d 100644
--- a/libstdc++-v3/include/bits/stl_iterator.h
+++ b/libstdc++-v3/include/bits/stl_iterator.h
@@ -1037,7 +1037,25 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
// provide overloads whose operands are of the same type. Can someone
// remind me what generic programming is about? -- Gaby
- // Forward iterator requirements
+#if __cpp_lib_three_way_comparison
+ template<typename _IteratorL, typename _IteratorR, typename _Container>
+ requires requires (_IteratorL __lhs, _IteratorR __rhs)
+ { { __lhs == __rhs } -> std::convertible_to<bool>; }
+ constexpr bool
+ operator==(const __normal_iterator<_IteratorL, _Container>& __lhs,
+ const __normal_iterator<_IteratorR, _Container>& __rhs)
+ noexcept(noexcept(__lhs.base() == __rhs.base()))
+ { return __lhs.base() == __rhs.base(); }
+
+ template<typename _IteratorL, typename _IteratorR, typename _Container>
+ constexpr auto
+ operator<=>(const __normal_iterator<_IteratorL, _Container>& __lhs,
+ const __normal_iterator<_IteratorR, _Container>& __rhs)
+ noexcept(noexcept(__lhs.base() <=> __rhs.base()))
+ -> decltype(__lhs.base() <=> __rhs.base())
+ { return __lhs.base() <=> __rhs.base(); }
+#else
+ // Forward iterator requirements
template<typename _IteratorL, typename _IteratorR, typename _Container>
_GLIBCXX20_CONSTEXPR
inline bool
@@ -1072,11 +1090,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
// Random access iterator requirements
template<typename _IteratorL, typename _IteratorR, typename _Container>
-#if __cplusplus > 201703L
- constexpr auto
-#else
inline bool
-#endif
operator<(const __normal_iterator<_IteratorL, _Container>& __lhs,
const __normal_iterator<_IteratorR, _Container>& __rhs)
_GLIBCXX_NOEXCEPT
@@ -1091,11 +1105,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{ return __lhs.base() < __rhs.base(); }
template<typename _IteratorL, typename _IteratorR, typename _Container>
-#if __cplusplus > 201703L
- constexpr auto
-#else
inline bool
-#endif
operator>(const __normal_iterator<_IteratorL, _Container>& __lhs,
const __normal_iterator<_IteratorR, _Container>& __rhs)
_GLIBCXX_NOEXCEPT
@@ -1110,11 +1120,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{ return __lhs.base() > __rhs.base(); }
template<typename _IteratorL, typename _IteratorR, typename _Container>
-#if __cplusplus > 201703L
- constexpr auto
-#else
inline bool
-#endif
operator<=(const __normal_iterator<_IteratorL, _Container>& __lhs,
const __normal_iterator<_IteratorR, _Container>& __rhs)
_GLIBCXX_NOEXCEPT
@@ -1129,11 +1135,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{ return __lhs.base() <= __rhs.base(); }
template<typename _IteratorL, typename _IteratorR, typename _Container>
-#if __cplusplus > 201703L
- constexpr auto
-#else
inline bool
-#endif
operator>=(const __normal_iterator<_IteratorL, _Container>& __lhs,
const __normal_iterator<_IteratorR, _Container>& __rhs)
_GLIBCXX_NOEXCEPT
@@ -1146,6 +1148,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
const __normal_iterator<_Iterator, _Container>& __rhs)
_GLIBCXX_NOEXCEPT
{ return __lhs.base() >= __rhs.base(); }
+#endif // three-way comparison
// _GLIBCXX_RESOLVE_LIB_DEFECTS
// According to the resolution of DR179 not only the various comparison
diff --git a/libstdc++-v3/include/bits/stl_list.h b/libstdc++-v3/include/bits/stl_list.h
index 97b8fb549b5..e7135e3e7ed 100644
--- a/libstdc++-v3/include/bits/stl_list.h
+++ b/libstdc++-v3/include/bits/stl_list.h
@@ -247,9 +247,11 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
operator==(const _Self& __x, const _Self& __y) _GLIBCXX_NOEXCEPT
{ return __x._M_node == __y._M_node; }
+#if __cpp_impl_three_way_comparison < 201907L
friend bool
operator!=(const _Self& __x, const _Self& __y) _GLIBCXX_NOEXCEPT
{ return __x._M_node != __y._M_node; }
+#endif
// The only member points to the %list element.
__detail::_List_node_base* _M_node;
@@ -331,9 +333,11 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
operator==(const _Self& __x, const _Self& __y) _GLIBCXX_NOEXCEPT
{ return __x._M_node == __y._M_node; }
+#if __cpp_impl_three_way_comparison < 201907L
friend bool
operator!=(const _Self& __x, const _Self& __y) _GLIBCXX_NOEXCEPT
{ return __x._M_node != __y._M_node; }
+#endif
// The only member points to the %list element.
const __detail::_List_node_base* _M_node;
@@ -2009,6 +2013,27 @@ _GLIBCXX_END_NAMESPACE_CXX11
return __i1 == __end1 && __i2 == __end2;
}
+#if __cpp_lib_three_way_comparison
+/**
+ * @brief List ordering relation.
+ * @param __x A `list`.
+ * @param __y A `list` of the same type as `__x`.
+ * @return A value indicating whether `__x` is less than, equal to,
+ * greater than, or incomparable with `__y`.
+ *
+ * See `std::lexicographical_compare_three_way()` for how the determination
+ * is made. This operator is used to synthesize relational operators like
+ * `<` and `>=` etc.
+ */
+ template<typename _Tp, typename _Alloc>
+ inline __detail::__synth3way_t<_Tp>
+ operator<=>(const list<_Tp, _Alloc>& __x, const list<_Tp, _Alloc>& __y)
+ {
+ return std::lexicographical_compare_three_way(__x.begin(), __x.end(),
+ __y.begin(), __y.end(),
+ __detail::__synth3way);
+ }
+#else
/**
* @brief List ordering relation.
* @param __x A %list.
@@ -2049,6 +2074,7 @@ _GLIBCXX_END_NAMESPACE_CXX11
inline bool
operator>=(const list<_Tp, _Alloc>& __x, const list<_Tp, _Alloc>& __y)
{ return !(__x < __y); }
+#endif // three-way comparison
/// See std::list::swap().
template<typename _Tp, typename _Alloc>
diff --git a/libstdc++-v3/include/bits/stl_vector.h b/libstdc++-v3/include/bits/stl_vector.h
index 14308a37770..d3f1b1fae5c 100644
--- a/libstdc++-v3/include/bits/stl_vector.h
+++ b/libstdc++-v3/include/bits/stl_vector.h
@@ -62,6 +62,9 @@
#if __cplusplus >= 201103L
#include <initializer_list>
#endif
+#if __cplusplus > 201703L
+# include <compare>
+#endif
#include <debug/assertions.h>
@@ -1890,6 +1893,27 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
{ return (__x.size() == __y.size()
&& std::equal(__x.begin(), __x.end(), __y.begin())); }
+#if __cpp_lib_three_way_comparison
+ /**
+ * @brief Vector ordering relation.
+ * @param __x A `vector`.
+ * @param __y A `vector` of the same type as `__x`.
+ * @return A value indicating whether `__x` is less than, equal to,
+ * greater than, or incomparable with `__y`.
+ *
+ * See `std::lexicographical_compare_three_way()` for how the determination
+ * is made. This operator is used to synthesize relational operators like
+ * `<` and `>=` etc.
+ */
+ template<typename _Tp, typename _Alloc>
+ inline __detail::__synth3way_t<_Tp>
+ operator<=>(const vector<_Tp, _Alloc>& __x, const vector<_Tp, _Alloc>& __y)
+ {
+ return std::lexicographical_compare_three_way(__x.begin(), __x.end(),
+ __y.begin(), __y.end(),
+ __detail::__synth3way);
+ }
+#else
/**
* @brief Vector ordering relation.
* @param __x A %vector.
@@ -1930,6 +1954,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
inline bool
operator>=(const vector<_Tp, _Alloc>& __x, const vector<_Tp, _Alloc>& __y)
{ return !(__x < __y); }
+#endif // three-way comparison
/// See std::vector::swap().
template<typename _Tp, typename _Alloc>
diff --git a/libstdc++-v3/include/debug/deque b/libstdc++-v3/include/debug/deque
index 8c6b4d14c2b..4d525bfc0aa 100644
--- a/libstdc++-v3/include/debug/deque
+++ b/libstdc++-v3/include/debug/deque
@@ -648,6 +648,12 @@ namespace __debug
const deque<_Tp, _Alloc>& __rhs)
{ return __lhs._M_base() == __rhs._M_base(); }
+#if __cpp_lib_three_way_comparison
+ template<typename _Tp, typename _Alloc>
+ constexpr __detail::__synth3way_t<_Tp>
+ operator<=>(const deque<_Tp, _Alloc>& __x, const deque<_Tp, _Alloc>& __y)
+ { return __x._M_base() <=> __y._M_base(); }
+#else
template<typename _Tp, typename _Alloc>
inline bool
operator!=(const deque<_Tp, _Alloc>& __lhs,
@@ -677,6 +683,7 @@ namespace __debug
operator>(const deque<_Tp, _Alloc>& __lhs,
const deque<_Tp, _Alloc>& __rhs)
{ return __lhs._M_base() > __rhs._M_base(); }
+#endif // three-way comparison
template<typename _Tp, typename _Alloc>
inline void
diff --git a/libstdc++-v3/include/debug/forward_list b/libstdc++-v3/include/debug/forward_list
index f0ff62c8cb1..2fd03e70499 100644
--- a/libstdc++-v3/include/debug/forward_list
+++ b/libstdc++-v3/include/debug/forward_list
@@ -838,6 +838,13 @@ namespace __debug
const forward_list<_Tp, _Alloc>& __ly)
{ return __lx._M_base() == __ly._M_base(); }
+#if __cpp_lib_three_way_comparison
+ template<typename _Tp, typename _Alloc>
+ constexpr __detail::__synth3way_t<_Tp>
+ operator<=>(const forward_list<_Tp, _Alloc>& __x,
+ const forward_list<_Tp, _Alloc>& __y)
+ { return __x._M_base() <=> __y._M_base(); }
+#else
template<typename _Tp, typename _Alloc>
inline bool
operator<(const forward_list<_Tp, _Alloc>& __lx,
@@ -870,6 +877,7 @@ namespace __debug
operator<=(const forward_list<_Tp, _Alloc>& __lx,
const forward_list<_Tp, _Alloc>& __ly)
{ return !(__ly < __lx); }
+#endif // three-way comparison
/// See std::forward_list::swap().
template<typename _Tp, typename _Alloc>
diff --git a/libstdc++-v3/include/debug/list b/libstdc++-v3/include/debug/list
index ee54ef27e57..6dd85741f81 100644
--- a/libstdc++-v3/include/debug/list
+++ b/libstdc++-v3/include/debug/list
@@ -864,6 +864,12 @@ namespace __debug
const list<_Tp, _Alloc>& __rhs)
{ return __lhs._M_base() == __rhs._M_base(); }
+#if __cpp_lib_three_way_comparison
+ template<typename _Tp, typename _Alloc>
+ constexpr __detail::__synth3way_t<_Tp>
+ operator<=>(const list<_Tp, _Alloc>& __x, const list<_Tp, _Alloc>& __y)
+ { return __x._M_base() <=> __y._M_base(); }
+#else
template<typename _Tp, typename _Alloc>
inline bool
operator!=(const list<_Tp, _Alloc>& __lhs,
@@ -893,6 +899,7 @@ namespace __debug
operator>(const list<_Tp, _Alloc>& __lhs,
const list<_Tp, _Alloc>& __rhs)
{ return __lhs._M_base() > __rhs._M_base(); }
+#endif // three-way comparison
template<typename _Tp, typename _Alloc>
inline void
diff --git a/libstdc++-v3/include/debug/safe_iterator.h b/libstdc++-v3/include/debug/safe_iterator.h
index f746cca5fb3..687b844fd75 100644
--- a/libstdc++-v3/include/debug/safe_iterator.h
+++ b/libstdc++-v3/include/debug/safe_iterator.h
@@ -35,6 +35,9 @@
#include <debug/safe_base.h>
#include <bits/stl_pair.h>
#include <ext/type_traits.h>
+#if __cplusplus > 201703L
+# include <compare>
+#endif
#define _GLIBCXX_DEBUG_VERIFY_OPERANDS(_Lhs, _Rhs, _BadMsgId, _DiffMsgId) \
_GLIBCXX_DEBUG_VERIFY(!_Lhs._M_singular() && !_Rhs._M_singular(), \
@@ -469,6 +472,7 @@ namespace __gnu_debug
return __lhs.base() == __rhs.base();
}
+#if ! __cpp_lib_three_way_comparison
friend bool
operator!=(const _Self& __lhs, const _Self& __rhs) _GLIBCXX_NOEXCEPT
{
@@ -485,6 +489,7 @@ namespace __gnu_debug
_GLIBCXX_DEBUG_VERIFY_EQ_OPERANDS(__lhs, __rhs);
return __lhs.base() != __rhs.base();
}
+#endif // three-way comparison
};
template<typename _Iterator, typename _Sequence>
@@ -805,6 +810,21 @@ namespace __gnu_debug
return *this;
}
+#if __cpp_lib_three_way_comparison
+ friend auto
+ operator<=>(const _Self& __lhs, const _Self& __rhs) noexcept
+ {
+ _GLIBCXX_DEBUG_VERIFY_REL_OPERANDS(__lhs, __rhs);
+ return __lhs.base() <=> __rhs.base();
+ }
+
+ friend auto
+ operator<=>(const _Self& __lhs, const _OtherSelf& __rhs) noexcept
+ {
+ _GLIBCXX_DEBUG_VERIFY_REL_OPERANDS(__lhs, __rhs);
+ return __lhs.base() <=> __rhs.base();
+ }
+#else
friend bool
operator<(const _Self& __lhs, const _Self& __rhs) _GLIBCXX_NOEXCEPT
{
@@ -860,6 +880,7 @@ namespace __gnu_debug
_GLIBCXX_DEBUG_VERIFY_REL_OPERANDS(__lhs, __rhs);
return __lhs.base() >= __rhs.base();
}
+#endif // three-way comparison
// _GLIBCXX_RESOLVE_LIB_DEFECTS
// According to the resolution of DR179 not only the various comparison
diff --git a/libstdc++-v3/include/debug/vector b/libstdc++-v3/include/debug/vector
index 96772f72643..4c08ab61ce8 100644
--- a/libstdc++-v3/include/debug/vector
+++ b/libstdc++-v3/include/debug/vector
@@ -731,6 +731,12 @@ namespace __debug
const vector<_Tp, _Alloc>& __rhs)
{ return __lhs._M_base() == __rhs._M_base(); }
+#if __cpp_lib_three_way_comparison
+ template<typename _Tp, typename _Alloc>
+ constexpr __detail::__synth3way_t<_Tp>
+ operator<=>(const vector<_Tp, _Alloc>& __x, const vector<_Tp, _Alloc>& __y)
+ { return __x._M_base() <=> __y._M_base(); }
+#else
template<typename _Tp, typename _Alloc>
inline bool
operator!=(const vector<_Tp, _Alloc>& __lhs,
@@ -760,6 +766,7 @@ namespace __debug
operator>(const vector<_Tp, _Alloc>& __lhs,
const vector<_Tp, _Alloc>& __rhs)
{ return __lhs._M_base() > __rhs._M_base(); }
+#endif // three-way comparison
template<typename _Tp, typename _Alloc>
inline void
diff --git a/libstdc++-v3/include/ext/pointer.h b/libstdc++-v3/include/ext/pointer.h
index aef622e2e23..a0ade4a677e 100644
--- a/libstdc++-v3/include/ext/pointer.h
+++ b/libstdc++-v3/include/ext/pointer.h
@@ -479,7 +479,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_Storage_policy::set(_Storage_policy::get() - 1);
return __tmp;
}
-
+
+#if __cpp_lib_three_way_comparison
+ friend std::strong_ordering
+ operator<=>(const _Pointer_adapter& __lhs, const _Pointer_adapter& __rhs)
+ noexcept
+ { return __lhs.get() <=> __rhs.get(); }
+#endif
}; // class _Pointer_adapter
diff --git a/libstdc++-v3/testsuite/23_containers/deque/operators/cmp_c++20.cc b/libstdc++-v3/testsuite/23_containers/deque/operators/cmp_c++20.cc
new file mode 100644
index 00000000000..77668fcd1f6
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/deque/operators/cmp_c++20.cc
@@ -0,0 +1,161 @@
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++2a" }
+// { dg-do run { target c++2a } }
+
+#include <deque>
+#include <testsuite_hooks.h>
+
+void
+test01()
+{
+ std::deque<int> c1{ 1, 2, 3 }, c2{ 1, 2, 3, 4 }, c3{ 1, 2, 4 };
+ VERIFY( c1 == c1 );
+ VERIFY( std::is_eq(c1 <=> c1) );
+ VERIFY( c1 < c2 );
+ VERIFY( std::is_lt(c1 <=> c2) );
+ VERIFY( c1 < c3 );
+ VERIFY( std::is_lt(c1 <=> c3) );
+ VERIFY( c2 < c3 );
+ VERIFY( std::is_lt(c2 <=> c3) );
+
+ static_assert( std::totally_ordered<std::deque<int>> );
+
+ static_assert( std::three_way_comparable<std::deque<int>,
+ std::strong_ordering> );
+ static_assert( ! std::three_way_comparable<std::deque<float>,
+ std::strong_ordering> );
+ static_assert( ! std::three_way_comparable<std::deque<float>,
+ std::weak_ordering> );
+ static_assert( std::three_way_comparable<std::deque<float>,
+ std::partial_ordering> );
+
+ struct E
+ {
+ bool operator==(E) { return true; }
+ };
+ static_assert( ! std::totally_ordered<std::deque<E>> );
+ static_assert( ! std::three_way_comparable<E> );
+ static_assert( ! std::three_way_comparable<std::deque<E>> );
+}
+
+void
+test02()
+{
+ struct W
+ {
+ int value = 0;
+
+ bool operator==(W rhs) const noexcept
+ { return (value | 1) == (rhs.value | 1); }
+
+ std::weak_ordering
+ operator<=>(W rhs) const noexcept
+ { return (value | 1) <=> (rhs.value | 1); }
+ };
+
+ static_assert( std::totally_ordered<std::deque<W>> );
+
+ std::deque<W> c1{ {1}, {2}, {3} }, c2{ {0}, {3}, {3} };
+ static_assert( std::same_as<decltype(c1 <=> c1), std::weak_ordering> );
+ VERIFY( c1 == c2 );
+ VERIFY( std::is_eq(c1 <=> c2) );
+}
+
+void
+test03()
+{
+ struct P
+ {
+ int value = 0;
+
+ bool operator==(P rhs) const noexcept
+ {
+ if (value < 0 || rhs.value < 0)
+ return false;
+ return value == rhs.value;
+ }
+
+ std::partial_ordering
+ operator<=>(P rhs) const noexcept
+ {
+ if (value < 0 || rhs.value < 0)
+ return std::partial_ordering::unordered;
+ return value <=> rhs.value;
+ }
+ };
+
+ static_assert( std::totally_ordered<std::deque<P>> );
+
+ std::deque<P> c{ {1}, {2}, {-3} };
+ static_assert( std::three_way_comparable<P> );
+ static_assert( std::same_as<decltype(c <=> c), std::partial_ordering> );
+ VERIFY( (c <=> c) == std::partial_ordering::unordered );
+}
+
+void
+test04()
+{
+ struct L
+ {
+ int value = 0;
+
+ bool operator<(L rhs) const noexcept { return value < rhs.value; }
+ };
+
+ static_assert( std::totally_ordered<std::deque<L>> );
+
+ std::deque<L> c{ {1}, {2}, {3} }, d{ {1}, {2}, {3}, {4} };
+ static_assert( std::same_as<decltype(c <=> c), std::weak_ordering> );
+ VERIFY( std::is_lt(c <=> d) );
+}
+
+void
+test05()
+{
+ // deque iterators are random access, so should support <=>
+
+ std::deque<int> c{ 1, 2, 3 };
+ VERIFY( c.begin() == c.cbegin() );
+ VERIFY( std::is_eq(c.begin() <=> c.cbegin()) );
+
+ VERIFY( c.begin() < c.end() );
+ VERIFY( std::is_lt(c.begin() <=> c.end()) );
+
+ VERIFY( c.begin() < c.cend() );
+ VERIFY( std::is_lt(c.begin() <=> c.cend()) );
+
+ VERIFY( c.crbegin() == c.rbegin() );
+ VERIFY( std::is_eq(c.crbegin() <=> c.rbegin()) );
+
+ VERIFY( c.rend() > c.rbegin() );
+ VERIFY( std::is_gt(c.rend() <=> c.rbegin()) );
+
+ static_assert( std::same_as<decltype(c.begin() <=> c.begin()),
+ std::strong_ordering> );
+}
+
+int
+main()
+{
+ test01();
+ test02();
+ test03();
+ test04();
+ test05();
+}
diff --git a/libstdc++-v3/testsuite/23_containers/forward_list/cmp_c++20.cc b/libstdc++-v3/testsuite/23_containers/forward_list/cmp_c++20.cc
new file mode 100644
index 00000000000..5a26d497ea6
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/forward_list/cmp_c++20.cc
@@ -0,0 +1,138 @@
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++2a" }
+// { dg-do run { target c++2a } }
+
+#include <forward_list>
+#include <testsuite_hooks.h>
+
+void
+test01()
+{
+ std::forward_list<int> c1{ 1, 2, 3 }, c2{ 1, 2, 3, 4 }, c3{ 1, 2, 4 };
+ VERIFY( c1 == c1 );
+ VERIFY( std::is_eq(c1 <=> c1) );
+ VERIFY( c1 < c2 );
+ VERIFY( std::is_lt(c1 <=> c2) );
+ VERIFY( c1 < c3 );
+ VERIFY( std::is_lt(c1 <=> c3) );
+ VERIFY( c2 < c3 );
+ VERIFY( std::is_lt(c2 <=> c3) );
+
+ static_assert( std::totally_ordered<std::forward_list<int>> );
+
+ static_assert( std::three_way_comparable<std::forward_list<int>,
+ std::strong_ordering> );
+ static_assert( ! std::three_way_comparable<std::forward_list<float>,
+ std::strong_ordering> );
+ static_assert( ! std::three_way_comparable<std::forward_list<float>,
+ std::weak_ordering> );
+ static_assert( std::three_way_comparable<std::forward_list<float>,
+ std::partial_ordering> );
+
+ struct E
+ {
+ bool operator==(E) { return true; }
+ };
+ static_assert( ! std::totally_ordered<std::forward_list<E>> );
+ static_assert( ! std::three_way_comparable<E> );
+ static_assert( ! std::three_way_comparable<std::forward_list<E>> );
+}
+
+void
+test02()
+{
+ struct W
+ {
+ int value = 0;
+
+ bool operator==(W rhs) const noexcept
+ { return (value | 1) == (rhs.value | 1); }
+
+ std::weak_ordering
+ operator<=>(W rhs) const noexcept
+ { return (value | 1) <=> (rhs.value | 1); }
+ };
+
+ static_assert( std::totally_ordered<std::forward_list<W>> );
+
+ std::forward_list<W> c1{ {1}, {2}, {3} }, c2{ {0}, {3}, {3} };
+ static_assert( std::same_as<decltype(c1 <=> c1), std::weak_ordering> );
+ VERIFY( c1 == c2 );
+ VERIFY( std::is_eq(c1 <=> c2) );
+}
+
+void
+test03()
+{
+ struct P
+ {
+ int value = 0;
+
+ bool operator==(P rhs) const noexcept
+ {
+ if (value < 0 || rhs.value < 0)
+ return false;
+ return value == rhs.value;
+ }
+
+ std::partial_ordering
+ operator<=>(P rhs) const noexcept
+ {
+ if (value < 0 || rhs.value < 0)
+ return std::partial_ordering::unordered;
+ return value <=> rhs.value;
+ }
+ };
+
+ static_assert( std::totally_ordered<std::forward_list<P>> );
+
+ std::forward_list<P> c{ {1}, {2}, {-3} };
+ static_assert( std::three_way_comparable<P> );
+ static_assert( std::same_as<decltype(c <=> c), std::partial_ordering> );
+ VERIFY( (c <=> c) == std::partial_ordering::unordered );
+}
+
+void
+test04()
+{
+ struct L
+ {
+ int value = 0;
+
+ bool operator<(L rhs) const noexcept { return value < rhs.value; }
+ };
+
+ static_assert( std::totally_ordered<std::forward_list<L>> );
+
+ std::forward_list<L> c{ {1}, {2}, {3} }, d{ {1}, {2}, {3}, {4} };
+ static_assert( std::same_as<decltype(c <=> c), std::weak_ordering> );
+ VERIFY( std::is_lt(c <=> d) );
+}
+
+static_assert( ! std::totally_ordered<std::forward_list<int>::iterator> );
+static_assert( ! std::three_way_comparable<std::forward_list<int>::iterator> );
+
+int
+main()
+{
+ test01();
+ test02();
+ test03();
+ test04();
+}
diff --git a/libstdc++-v3/testsuite/23_containers/list/cmp_c++20.cc b/libstdc++-v3/testsuite/23_containers/list/cmp_c++20.cc
new file mode 100644
index 00000000000..a5b9f8f5459
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/list/cmp_c++20.cc
@@ -0,0 +1,138 @@
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++2a" }
+// { dg-do run { target c++2a } }
+
+#include <list>
+#include <testsuite_hooks.h>
+
+void
+test01()
+{
+ std::list<int> c1{ 1, 2, 3 }, c2{ 1, 2, 3, 4 }, c3{ 1, 2, 4 };
+ VERIFY( c1 == c1 );
+ VERIFY( std::is_eq(c1 <=> c1) );
+ VERIFY( c1 < c2 );
+ VERIFY( std::is_lt(c1 <=> c2) );
+ VERIFY( c1 < c3 );
+ VERIFY( std::is_lt(c1 <=> c3) );
+ VERIFY( c2 < c3 );
+ VERIFY( std::is_lt(c2 <=> c3) );
+
+ static_assert( std::totally_ordered<std::list<int>> );
+
+ static_assert( std::three_way_comparable<std::list<int>,
+ std::strong_ordering> );
+ static_assert( ! std::three_way_comparable<std::list<float>,
+ std::strong_ordering> );
+ static_assert( ! std::three_way_comparable<std::list<float>,
+ std::weak_ordering> );
+ static_assert( std::three_way_comparable<std::list<float>,
+ std::partial_ordering> );
+
+ struct E
+ {
+ bool operator==(E) { return true; }
+ };
+ static_assert( ! std::totally_ordered<std::list<E>> );
+ static_assert( ! std::three_way_comparable<E> );
+ static_assert( ! std::three_way_comparable<std::list<E>> );
+}
+
+void
+test02()
+{
+ struct W
+ {
+ int value = 0;
+
+ bool operator==(W rhs) const noexcept
+ { return (value | 1) == (rhs.value | 1); }
+
+ std::weak_ordering
+ operator<=>(W rhs) const noexcept
+ { return (value | 1) <=> (rhs.value | 1); }
+ };
+
+ static_assert( std::totally_ordered<std::list<W>> );
+
+ std::list<W> c1{ {1}, {2}, {3} }, c2{ {0}, {3}, {3} };
+ static_assert( std::same_as<decltype(c1 <=> c1), std::weak_ordering> );
+ VERIFY( c1 == c2 );
+ VERIFY( std::is_eq(c1 <=> c2) );
+}
+
+void
+test03()
+{
+ struct P
+ {
+ int value = 0;
+
+ bool operator==(P rhs) const noexcept
+ {
+ if (value < 0 || rhs.value < 0)
+ return false;
+ return value == rhs.value;
+ }
+
+ std::partial_ordering
+ operator<=>(P rhs) const noexcept
+ {
+ if (value < 0 || rhs.value < 0)
+ return std::partial_ordering::unordered;
+ return value <=> rhs.value;
+ }
+ };
+
+ static_assert( std::totally_ordered<std::list<P>> );
+
+ std::list<P> c{ {1}, {2}, {-3} };
+ static_assert( std::three_way_comparable<P> );
+ static_assert( std::same_as<decltype(c <=> c), std::partial_ordering> );
+ VERIFY( (c <=> c) == std::partial_ordering::unordered );
+}
+
+void
+test04()
+{
+ struct L
+ {
+ int value = 0;
+
+ bool operator<(L rhs) const noexcept { return value < rhs.value; }
+ };
+
+ static_assert( std::totally_ordered<std::list<L>> );
+
+ std::list<L> c{ {1}, {2}, {3} }, d{ {1}, {2}, {3}, {4} };
+ static_assert( std::same_as<decltype(c <=> c), std::weak_ordering> );
+ VERIFY( std::is_lt(c <=> d) );
+}
+
+static_assert( ! std::totally_ordered<std::list<int>::iterator> );
+static_assert( ! std::three_way_comparable<std::list<int>::iterator> );
+
+int
+main()
+{
+ test01();
+ test02();
+ test03();
+ test04();
+}
diff --git a/libstdc++-v3/testsuite/23_containers/vector/bool/cmp_c++20.cc b/libstdc++-v3/testsuite/23_containers/vector/bool/cmp_c++20.cc
new file mode 100644
index 00000000000..a586ab65cd7
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/vector/bool/cmp_c++20.cc
@@ -0,0 +1,73 @@
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++2a" }
+// { dg-do run { target c++2a } }
+
+#include <vector>
+#include <testsuite_hooks.h>
+
+void
+test01()
+{
+ std::vector<bool> c1{ 1, 0, 1 }, c2{ 1, 0, 1, 0 }, c3{ 1, 1, 1 };
+ VERIFY( c1 == c1 );
+ VERIFY( std::is_eq(c1 <=> c1) );
+ VERIFY( c1 < c2 );
+ VERIFY( std::is_lt(c1 <=> c2) );
+ VERIFY( c1 < c3 );
+ VERIFY( std::is_lt(c1 <=> c3) );
+ VERIFY( c2 < c3 );
+ VERIFY( std::is_lt(c2 <=> c3) );
+
+ static_assert( std::totally_ordered<std::vector<bool>> );
+
+ static_assert( std::three_way_comparable<std::vector<bool>,
+ std::strong_ordering> );
+}
+
+void
+test05()
+{
+ // vector<bool> iterators are random access, so should support <=>
+
+ std::vector<bool> c{ 1, 1, 1 };
+ VERIFY( c.begin() == c.cbegin() );
+ VERIFY( std::is_eq(c.begin() <=> c.cbegin()) );
+
+ VERIFY( c.begin() < c.end() );
+ VERIFY( std::is_lt(c.begin() <=> c.end()) );
+
+ VERIFY( c.begin() < c.cend() );
+ VERIFY( std::is_lt(c.begin() <=> c.cend()) );
+
+ VERIFY( c.crbegin() == c.rbegin() );
+ VERIFY( std::is_eq(c.crbegin() <=> c.rbegin()) );
+
+ VERIFY( c.rend() > c.rbegin() );
+ VERIFY( std::is_gt(c.rend() <=> c.rbegin()) );
+
+ static_assert( std::same_as<decltype(c.begin() <=> c.begin()),
+ std::strong_ordering> );
+}
+
+int
+main()
+{
+ test01();
+ test05();
+}
diff --git a/libstdc++-v3/testsuite/23_containers/vector/cmp_c++20.cc b/libstdc++-v3/testsuite/23_containers/vector/cmp_c++20.cc
new file mode 100644
index 00000000000..ca6a4f43e22
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/vector/cmp_c++20.cc
@@ -0,0 +1,161 @@
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++2a" }
+// { dg-do run { target c++2a } }
+
+#include <vector>
+#include <testsuite_hooks.h>
+
+void
+test01()
+{
+ std::vector<int> c1{ 1, 2, 3 }, c2{ 1, 2, 3, 4 }, c3{ 1, 2, 4 };
+ VERIFY( c1 == c1 );
+ VERIFY( std::is_eq(c1 <=> c1) );
+ VERIFY( c1 < c2 );
+ VERIFY( std::is_lt(c1 <=> c2) );
+ VERIFY( c1 < c3 );
+ VERIFY( std::is_lt(c1 <=> c3) );
+ VERIFY( c2 < c3 );
+ VERIFY( std::is_lt(c2 <=> c3) );
+
+ static_assert( std::totally_ordered<std::vector<int>> );
+
+ static_assert( std::three_way_comparable<std::vector<int>,
+ std::strong_ordering> );
+ static_assert( ! std::three_way_comparable<std::vector<float>,
+ std::strong_ordering> );
+ static_assert( ! std::three_way_comparable<std::vector<float>,
+ std::weak_ordering> );
+ static_assert( std::three_way_comparable<std::vector<float>,
+ std::partial_ordering> );
+
+ struct E
+ {
+ bool operator==(E) { return true; }
+ };
+ static_assert( ! std::totally_ordered<std::vector<E>> );
+ static_assert( ! std::three_way_comparable<E> );
+ static_assert( ! std::three_way_comparable<std::vector<E>> );
+}
+
+void
+test02()
+{
+ struct W
+ {
+ int value = 0;
+
+ bool operator==(W rhs) const noexcept
+ { return (value | 1) == (rhs.value | 1); }
+
+ std::weak_ordering
+ operator<=>(W rhs) const noexcept
+ { return (value | 1) <=> (rhs.value | 1); }
+ };
+
+ static_assert( std::totally_ordered<std::vector<W>> );
+
+ std::vector<W> c1{ {1}, {2}, {3} }, c2{ {0}, {3}, {3} };
+ static_assert( std::same_as<decltype(c1 <=> c1), std::weak_ordering> );
+ VERIFY( c1 == c2 );
+ VERIFY( std::is_eq(c1 <=> c2) );
+}
+
+void
+test03()
+{
+ struct P
+ {
+ int value = 0;
+
+ bool operator==(P rhs) const noexcept
+ {
+ if (value < 0 || rhs.value < 0)
+ return false;
+ return value == rhs.value;
+ }
+
+ std::partial_ordering
+ operator<=>(P rhs) const noexcept
+ {
+ if (value < 0 || rhs.value < 0)
+ return std::partial_ordering::unordered;
+ return value <=> rhs.value;
+ }
+ };
+
+ static_assert( std::totally_ordered<std::vector<P>> );
+
+ std::vector<P> c{ {1}, {2}, {-3} };
+ static_assert( std::three_way_comparable<P> );
+ static_assert( std::same_as<decltype(c <=> c), std::partial_ordering> );
+ VERIFY( (c <=> c) == std::partial_ordering::unordered );
+}
+
+void
+test04()
+{
+ struct L
+ {
+ int value = 0;
+
+ bool operator<(L rhs) const noexcept { return value < rhs.value; }
+ };
+
+ static_assert( std::totally_ordered<std::vector<L>> );
+
+ std::vector<L> c{ {1}, {2}, {3} }, d{ {1}, {2}, {3}, {4} };
+ static_assert( std::same_as<decltype(c <=> c), std::weak_ordering> );
+ VERIFY( std::is_lt(c <=> d) );
+}
+
+void
+test05()
+{
+ // vector iterators are random access, so should support <=>
+
+ std::vector<int> c{ 1, 2, 3 };
+ VERIFY( c.begin() == c.cbegin() );
+ VERIFY( std::is_eq(c.begin() <=> c.cbegin()) );
+
+ VERIFY( c.begin() < c.end() );
+ VERIFY( std::is_lt(c.begin() <=> c.end()) );
+
+ VERIFY( c.begin() < c.cend() );
+ VERIFY( std::is_lt(c.begin() <=> c.cend()) );
+
+ VERIFY( c.crbegin() == c.rbegin() );
+ VERIFY( std::is_eq(c.crbegin() <=> c.rbegin()) );
+
+ VERIFY( c.rend() > c.rbegin() );
+ VERIFY( std::is_gt(c.rend() <=> c.rbegin()) );
+
+ static_assert( std::same_as<decltype(c.begin() <=> c.begin()),
+ std::strong_ordering> );
+}
+
+int
+main()
+{
+ test01();
+ test02();
+ test03();
+ test04();
+ test05();
+}
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2020-07-12 17:18 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-07-12 17:18 [gcc/devel/gccgo] libstdc++: Add comparison operators to sequence containers Ian Lance Taylor
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).