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.
This commit is contained in:
parent
3737ccc424
commit
bd2420f8fa
@ -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):
|
||||
|
@ -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>
|
||||
|
@ -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)
|
||||
|
@ -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>
|
||||
|
@ -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
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
@ -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
|
||||
|
@ -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>
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
||||
|
@ -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();
|
||||
}
|
138
libstdc++-v3/testsuite/23_containers/forward_list/cmp_c++20.cc
Normal file
138
libstdc++-v3/testsuite/23_containers/forward_list/cmp_c++20.cc
Normal file
@ -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();
|
||||
}
|
138
libstdc++-v3/testsuite/23_containers/list/cmp_c++20.cc
Normal file
138
libstdc++-v3/testsuite/23_containers/list/cmp_c++20.cc
Normal file
@ -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();
|
||||
}
|
@ -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();
|
||||
}
|
161
libstdc++-v3/testsuite/23_containers/vector/cmp_c++20.cc
Normal file
161
libstdc++-v3/testsuite/23_containers/vector/cmp_c++20.cc
Normal file
@ -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();
|
||||
}
|
Loading…
Reference in New Issue
Block a user