From 93843da69772d271a7247ab2536280646086a5ce Mon Sep 17 00:00:00 2001 From: Jonathan Wakely Date: Mon, 20 Apr 2020 17:50:10 +0100 Subject: [PATCH] libstdc++: Add comparison operators to associative containers The last C++20 changes from P1614R2, "The Mothership has Landed" * include/bits/stl_map.h (map): Define operator<=> and remove operator< for C++20. * include/bits/stl_multimap.h (multimap): Likewise. * include/bits/stl_multiset.h (multiset): Likewise. * include/bits/stl_set.h (set): Likewise. * include/bits/stl_tree.h (_Rb_tree): Likewise. (_Rb_tree_iterator, _Rb_tree_const_iterator): Remove redundant operator!= for C++20. * include/debug/map.h (__gnu_debug::map): Define operator<=> for C++20. * include/debug/multimap.h (__gnu_debug::multimap): Likewise. * include/debug/multiset.h (__gnu_debug::multiset): Likewise. * include/debug/set.h (__gnu_debug::set): Likewise. * testsuite/23_containers/map/operators/cmp_c++20.cc: New test. * testsuite/23_containers/multimap/operators/cmp_c++20.cc: New test. * testsuite/23_containers/multiset/operators/cmp_c++20.cc: New test. * testsuite/23_containers/set/operators/cmp_c++20.cc: New test. --- libstdc++-v3/ChangeLog | 19 +++ libstdc++-v3/include/bits/stl_map.h | 31 ++++- libstdc++-v3/include/bits/stl_multimap.h | 31 ++++- libstdc++-v3/include/bits/stl_multiset.h | 31 ++++- libstdc++-v3/include/bits/stl_set.h | 30 ++++- libstdc++-v3/include/bits/stl_tree.h | 15 +++ libstdc++-v3/include/debug/map.h | 10 +- libstdc++-v3/include/debug/multimap.h | 8 ++ libstdc++-v3/include/debug/multiset.h | 10 +- libstdc++-v3/include/debug/set.h | 10 +- .../23_containers/map/operators/cmp_c++20.cc | 111 ++++++++++++++++++ .../multimap/operators/cmp_c++20.cc | 111 ++++++++++++++++++ .../multiset/operators/cmp_c++20.cc | 107 +++++++++++++++++ .../23_containers/set/operators/cmp_c++20.cc | 107 +++++++++++++++++ 14 files changed, 624 insertions(+), 7 deletions(-) create mode 100644 libstdc++-v3/testsuite/23_containers/map/operators/cmp_c++20.cc create mode 100644 libstdc++-v3/testsuite/23_containers/multimap/operators/cmp_c++20.cc create mode 100644 libstdc++-v3/testsuite/23_containers/multiset/operators/cmp_c++20.cc create mode 100644 libstdc++-v3/testsuite/23_containers/set/operators/cmp_c++20.cc diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index b30b1d096e8..3d0ddf5f36e 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,22 @@ +2020-04-20 Jonathan Wakely + + * include/bits/stl_map.h (map): Define operator<=> and remove + operator< for C++20. + * include/bits/stl_multimap.h (multimap): Likewise. + * include/bits/stl_multiset.h (multiset): Likewise. + * include/bits/stl_set.h (set): Likewise. + * include/bits/stl_tree.h (_Rb_tree): Likewise. + (_Rb_tree_iterator, _Rb_tree_const_iterator): Remove redundant + operator!= for C++20. + * include/debug/map.h (__gnu_debug::map): Define operator<=> for C++20. + * include/debug/multimap.h (__gnu_debug::multimap): Likewise. + * include/debug/multiset.h (__gnu_debug::multiset): Likewise. + * include/debug/set.h (__gnu_debug::set): Likewise. + * testsuite/23_containers/map/operators/cmp_c++20.cc: New test. + * testsuite/23_containers/multimap/operators/cmp_c++20.cc: New test. + * testsuite/23_containers/multiset/operators/cmp_c++20.cc: New test. + * testsuite/23_containers/set/operators/cmp_c++20.cc: New test. + 2020-04-20 Matthias Kretz * testsuite/lib/libstdc++.exp: Avoid illegal argument to verbose. diff --git a/libstdc++-v3/include/bits/stl_map.h b/libstdc++-v3/include/bits/stl_map.h index fe930c15757..5039efd86b7 100644 --- a/libstdc++-v3/include/bits/stl_map.h +++ b/libstdc++-v3/include/bits/stl_map.h @@ -1400,10 +1400,17 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER operator==(const map<_K1, _T1, _C1, _A1>&, const map<_K1, _T1, _C1, _A1>&); +#if __cpp_lib_three_way_comparison + template + friend __detail::__synth3way_t> + operator<=>(const map<_K1, _T1, _C1, _A1>&, + const map<_K1, _T1, _C1, _A1>&); +#else template friend bool operator<(const map<_K1, _T1, _C1, _A1>&, const map<_K1, _T1, _C1, _A1>&); +#endif }; @@ -1440,7 +1447,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER map(initializer_list>, _Allocator) -> map<_Key, _Tp, less<_Key>, _Allocator>; -#endif +#endif // deduction guides /** * @brief Map equality comparison. @@ -1458,6 +1465,27 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER const map<_Key, _Tp, _Compare, _Alloc>& __y) { return __x._M_t == __y._M_t; } +#if __cpp_lib_three_way_comparison + /** + * @brief Map ordering relation. + * @param __x A `map`. + * @param __y A `map` of the same type as `x`. + * @return A value indicating whether `__x` is less than, equal to, + * greater than, or incomparable with `__y`. + * + * This is a total ordering relation. It is linear in the size of the + * maps. The elements must be comparable with @c <. + * + * See `std::lexicographical_compare_three_way()` for how the determination + * is made. This operator is used to synthesize relational operators like + * `<` and `>=` etc. + */ + template + inline __detail::__synth3way_t> + operator<=>(const map<_Key, _Tp, _Compare, _Alloc>& __x, + const map<_Key, _Tp, _Compare, _Alloc>& __y) + { return __x._M_t <=> __y._M_t; } +#else /** * @brief Map ordering relation. * @param __x A %map. @@ -1502,6 +1530,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER operator>=(const map<_Key, _Tp, _Compare, _Alloc>& __x, const map<_Key, _Tp, _Compare, _Alloc>& __y) { return !(__x < __y); } +#endif // three-way comparison /// See std::map::swap(). template diff --git a/libstdc++-v3/include/bits/stl_multimap.h b/libstdc++-v3/include/bits/stl_multimap.h index d38f530e123..65f4d0117a4 100644 --- a/libstdc++-v3/include/bits/stl_multimap.h +++ b/libstdc++-v3/include/bits/stl_multimap.h @@ -1065,10 +1065,17 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER operator==(const multimap<_K1, _T1, _C1, _A1>&, const multimap<_K1, _T1, _C1, _A1>&); +#if __cpp_lib_three_way_comparison + template + friend __detail::__synth3way_t> + operator<=>(const multimap<_K1, _T1, _C1, _A1>&, + const multimap<_K1, _T1, _C1, _A1>&); +#else template friend bool operator<(const multimap<_K1, _T1, _C1, _A1>&, const multimap<_K1, _T1, _C1, _A1>&); +#endif }; #if __cpp_deduction_guides >= 201606 @@ -1104,7 +1111,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER multimap(initializer_list>, _Allocator) -> multimap<_Key, _Tp, less<_Key>, _Allocator>; -#endif +#endif // deduction guides /** * @brief Multimap equality comparison. @@ -1122,6 +1129,27 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER const multimap<_Key, _Tp, _Compare, _Alloc>& __y) { return __x._M_t == __y._M_t; } +#if __cpp_lib_three_way_comparison + /** + * @brief Multimap ordering relation. + * @param __x A `multimap`. + * @param __y A `multimap` of the same type as `x`. + * @return A value indicating whether `__x` is less than, equal to, + * greater than, or incomparable with `__y`. + * + * This is a total ordering relation. It is linear in the size of the + * maps. The elements must be comparable with @c <. + * + * See `std::lexicographical_compare_three_way()` for how the determination + * is made. This operator is used to synthesize relational operators like + * `<` and `>=` etc. + */ + template + inline __detail::__synth3way_t> + operator<=>(const multimap<_Key, _Tp, _Compare, _Alloc>& __x, + const multimap<_Key, _Tp, _Compare, _Alloc>& __y) + { return __x._M_t <=> __y._M_t; } +#else /** * @brief Multimap ordering relation. * @param __x A %multimap. @@ -1166,6 +1194,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER operator>=(const multimap<_Key, _Tp, _Compare, _Alloc>& __x, const multimap<_Key, _Tp, _Compare, _Alloc>& __y) { return !(__x < __y); } +#endif // three-way comparison /// See std::multimap::swap(). template diff --git a/libstdc++-v3/include/bits/stl_multiset.h b/libstdc++-v3/include/bits/stl_multiset.h index ab62df1e508..bf6ae7de095 100644 --- a/libstdc++-v3/include/bits/stl_multiset.h +++ b/libstdc++-v3/include/bits/stl_multiset.h @@ -903,10 +903,17 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER operator==(const multiset<_K1, _C1, _A1>&, const multiset<_K1, _C1, _A1>&); +#if __cpp_lib_three_way_comparison + template + friend __detail::__synth3way_t<_K1> + operator<=>(const multiset<_K1, _C1, _A1>&, + const multiset<_K1, _C1, _A1>&); +#else template friend bool operator< (const multiset<_K1, _C1, _A1>&, const multiset<_K1, _C1, _A1>&); +#endif }; #if __cpp_deduction_guides >= 201606 @@ -946,7 +953,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER multiset(initializer_list<_Key>, _Allocator) -> multiset<_Key, less<_Key>, _Allocator>; -#endif +#endif // deduction guides /** * @brief Multiset equality comparison. @@ -965,6 +972,27 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER const multiset<_Key, _Compare, _Alloc>& __y) { return __x._M_t == __y._M_t; } +#if __cpp_lib_three_way_comparison + /** + * @brief Multiset ordering relation. + * @param __x A `multiset`. + * @param __y A `multiset` of the same type as `x`. + * @return A value indicating whether `__x` is less than, equal to, + * greater than, or incomparable with `__y`. + * + * This is a total ordering relation. It is linear in the size of the + * maps. The elements must be comparable with @c <. + * + * See `std::lexicographical_compare_three_way()` for how the determination + * is made. This operator is used to synthesize relational operators like + * `<` and `>=` etc. + */ + template + inline __detail::__synth3way_t<_Key> + operator<=>(const multiset<_Key, _Compare, _Alloc>& __x, + const multiset<_Key, _Compare, _Alloc>& __y) + { return __x._M_t <=> __y._M_t; } +#else /** * @brief Multiset ordering relation. * @param __x A %multiset. @@ -1009,6 +1037,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER operator>=(const multiset<_Key, _Compare, _Alloc>& __x, const multiset<_Key, _Compare, _Alloc>& __y) { return !(__x < __y); } +#endif // three-way comparison /// See std::multiset::swap(). template diff --git a/libstdc++-v3/include/bits/stl_set.h b/libstdc++-v3/include/bits/stl_set.h index 4f8d631bb3b..da426650815 100644 --- a/libstdc++-v3/include/bits/stl_set.h +++ b/libstdc++-v3/include/bits/stl_set.h @@ -921,9 +921,15 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER friend bool operator==(const set<_K1, _C1, _A1>&, const set<_K1, _C1, _A1>&); +#if __cpp_lib_three_way_comparison + template + friend __detail::__synth3way_t<_K1> + operator<=>(const set<_K1, _C1, _A1>&, const set<_K1, _C1, _A1>&); +#else template friend bool operator<(const set<_K1, _C1, _A1>&, const set<_K1, _C1, _A1>&); +#endif }; #if __cpp_deduction_guides >= 201606 @@ -962,7 +968,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER set(initializer_list<_Key>, _Allocator) -> set<_Key, less<_Key>, _Allocator>; -#endif +#endif // deduction guides /** * @brief Set equality comparison. @@ -980,6 +986,27 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER const set<_Key, _Compare, _Alloc>& __y) { return __x._M_t == __y._M_t; } +#if __cpp_lib_three_way_comparison + /** + * @brief Set ordering relation. + * @param __x A `set`. + * @param __y A `set` of the same type as `x`. + * @return A value indicating whether `__x` is less than, equal to, + * greater than, or incomparable with `__y`. + * + * This is a total ordering relation. It is linear in the size of the + * maps. The elements must be comparable with @c <. + * + * See `std::lexicographical_compare_three_way()` for how the determination + * is made. This operator is used to synthesize relational operators like + * `<` and `>=` etc. + */ + template + inline __detail::__synth3way_t<_Key> + operator<=>(const set<_Key, _Compare, _Alloc>& __x, + const set<_Key, _Compare, _Alloc>& __y) + { return __x._M_t <=> __y._M_t; } +#else /** * @brief Set ordering relation. * @param __x A %set. @@ -1024,6 +1051,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER operator>=(const set<_Key, _Compare, _Alloc>& __x, const set<_Key, _Compare, _Alloc>& __y) { return !(__x < __y); } +#endif // three-way comparison /// See std::set::swap(). template diff --git a/libstdc++-v3/include/bits/stl_tree.h b/libstdc++-v3/include/bits/stl_tree.h index 9339011e872..5be15afa257 100644 --- a/libstdc++-v3/include/bits/stl_tree.h +++ b/libstdc++-v3/include/bits/stl_tree.h @@ -315,9 +315,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION operator==(const _Self& __x, const _Self& __y) _GLIBCXX_NOEXCEPT { return __x._M_node == __y._M_node; } +#if ! __cpp_lib_three_way_comparison friend bool operator!=(const _Self& __x, const _Self& __y) _GLIBCXX_NOEXCEPT { return __x._M_node != __y._M_node; } +#endif _Base_ptr _M_node; }; @@ -394,9 +396,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION operator==(const _Self& __x, const _Self& __y) _GLIBCXX_NOEXCEPT { return __x._M_node == __y._M_node; } +#if ! __cpp_lib_three_way_comparison friend bool operator!=(const _Self& __x, const _Self& __y) _GLIBCXX_NOEXCEPT { return __x._M_node != __y._M_node; } +#endif _Base_ptr _M_node; }; @@ -1610,6 +1614,16 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION && std::equal(__x.begin(), __x.end(), __y.begin()); } +#if __cpp_lib_three_way_comparison + friend auto + operator<=>(const _Rb_tree& __x, const _Rb_tree& __y) + { + if constexpr (requires { typename __detail::__synth3way_t<_Val>; }) + return std::lexicographical_compare_three_way(__x.begin(), __x.end(), + __y.begin(), __y.end(), + __detail::__synth3way); + } +#else friend bool operator<(const _Rb_tree& __x, const _Rb_tree& __y) { @@ -1632,6 +1646,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION friend bool _GLIBCXX_DEPRECATED operator>=(const _Rb_tree& __x, const _Rb_tree& __y) { return !(__x < __y); } +#endif }; template>, _Allocator) -> map<_Key, _Tp, less<_Key>, _Allocator>; -#endif +#endif // deduction guides template @@ -740,6 +740,13 @@ namespace __debug const map<_Key, _Tp, _Compare, _Allocator>& __rhs) { return __lhs._M_base() == __rhs._M_base(); } +#if __cpp_lib_three_way_comparison + template + inline __detail::__synth3way_t> + operator<=>(const map<_Key, _Tp, _Compare, _Alloc>& __lhs, + const map<_Key, _Tp, _Compare, _Alloc>& __rhs) + { return __lhs._M_base() <=> __rhs._M_base(); } +#else template inline bool @@ -774,6 +781,7 @@ namespace __debug operator>(const map<_Key, _Tp, _Compare, _Allocator>& __lhs, const map<_Key, _Tp, _Compare, _Allocator>& __rhs) { return __lhs._M_base() > __rhs._M_base(); } +#endif // three-way comparison template diff --git a/libstdc++-v3/include/debug/multimap.h b/libstdc++-v3/include/debug/multimap.h index 83de49e87e2..6cba52d35dc 100644 --- a/libstdc++-v3/include/debug/multimap.h +++ b/libstdc++-v3/include/debug/multimap.h @@ -621,6 +621,13 @@ namespace __debug const multimap<_Key, _Tp, _Compare, _Allocator>& __rhs) { return __lhs._M_base() == __rhs._M_base(); } +#if __cpp_lib_three_way_comparison + template + inline __detail::__synth3way_t> + operator<=>(const multimap<_Key, _Tp, _Compare, _Alloc>& __lhs, + const multimap<_Key, _Tp, _Compare, _Alloc>& __rhs) + { return __lhs._M_base() <=> __rhs._M_base(); } +#else template inline bool @@ -655,6 +662,7 @@ namespace __debug operator>(const multimap<_Key, _Tp, _Compare, _Allocator>& __lhs, const multimap<_Key, _Tp, _Compare, _Allocator>& __rhs) { return __lhs._M_base() > __rhs._M_base(); } +#endif // three-way comparison template diff --git a/libstdc++-v3/include/debug/multiset.h b/libstdc++-v3/include/debug/multiset.h index fcbba339478..a2d5e717b34 100644 --- a/libstdc++-v3/include/debug/multiset.h +++ b/libstdc++-v3/include/debug/multiset.h @@ -584,7 +584,7 @@ namespace __debug multiset(initializer_list<_Key>, _Allocator) -> multiset<_Key, less<_Key>, _Allocator>; -#endif +#endif // deduction guides template inline bool @@ -592,6 +592,13 @@ namespace __debug const multiset<_Key, _Compare, _Allocator>& __rhs) { return __lhs._M_base() == __rhs._M_base(); } +#if __cpp_lib_three_way_comparison + template + inline __detail::__synth3way_t<_Key> + operator<=>(const multiset<_Key, _Compare, _Alloc>& __lhs, + const multiset<_Key, _Compare, _Alloc>& __rhs) + { return __lhs._M_base() <=> __rhs._M_base(); } +#else template inline bool operator!=(const multiset<_Key, _Compare, _Allocator>& __lhs, @@ -621,6 +628,7 @@ namespace __debug operator>(const multiset<_Key, _Compare, _Allocator>& __lhs, const multiset<_Key, _Compare, _Allocator>& __rhs) { return __lhs._M_base() > __rhs._M_base(); } +#endif // three-way comparison template void diff --git a/libstdc++-v3/include/debug/set.h b/libstdc++-v3/include/debug/set.h index 093ff129f3e..210186623df 100644 --- a/libstdc++-v3/include/debug/set.h +++ b/libstdc++-v3/include/debug/set.h @@ -595,7 +595,7 @@ namespace __debug set(initializer_list<_Key>, _Allocator) -> set<_Key, less<_Key>, _Allocator>; -#endif +#endif // deduction guides template inline bool @@ -603,6 +603,13 @@ namespace __debug const set<_Key, _Compare, _Allocator>& __rhs) { return __lhs._M_base() == __rhs._M_base(); } +#if __cpp_lib_three_way_comparison + template + inline __detail::__synth3way_t<_Key> + operator<=>(const set<_Key, _Compare, _Alloc>& __lhs, + const set<_Key, _Compare, _Alloc>& __rhs) + { return __lhs._M_base() <=> __rhs._M_base(); } +#else template inline bool operator!=(const set<_Key, _Compare, _Allocator>& __lhs, @@ -632,6 +639,7 @@ namespace __debug operator>(const set<_Key, _Compare, _Allocator>& __lhs, const set<_Key, _Compare, _Allocator>& __rhs) { return __lhs._M_base() > __rhs._M_base(); } +#endif // three-way comparison template void diff --git a/libstdc++-v3/testsuite/23_containers/map/operators/cmp_c++20.cc b/libstdc++-v3/testsuite/23_containers/map/operators/cmp_c++20.cc new file mode 100644 index 00000000000..a586a6df648 --- /dev/null +++ b/libstdc++-v3/testsuite/23_containers/map/operators/cmp_c++20.cc @@ -0,0 +1,111 @@ +// 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 +// . + +// { dg-options "-std=gnu++2a" } +// { dg-do run { target c++2a } } + +#include +#include + +void +test01() +{ + std::map c1{ {1,1}, {2,1}, {3,1} }; + std::map c2{ {1,1}, {2,1}, {3,1}, {4,1} }; + std::map c3{ {1,1}, {2,1}, {3,2} }; + 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> ); + + static_assert( std::three_way_comparable, + std::strong_ordering> ); + static_assert( ! std::three_way_comparable, + std::strong_ordering> ); + static_assert( ! std::three_way_comparable, + std::weak_ordering> ); + static_assert( std::three_way_comparable, + std::partial_ordering> ); + + struct E + { + bool operator==(E) { return true; } + }; + static_assert( ! std::totally_ordered> ); + static_assert( ! std::three_way_comparable ); + static_assert( ! std::three_way_comparable> ); +} + +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> ); + + using P = std::pair; + std::map c1{ P{1,1}, P{2,2}, P{3,3} }, c2{ P{1,0}, P{3,2}, P{3,3} }; + static_assert( std::same_as c1), std::weak_ordering> ); + VERIFY( c1 == c2 ); + VERIFY( std::is_eq(c1 <=> c2) ); +} + +void +test04() +{ + struct L + { + int value = 0; + + bool operator<(L rhs) const noexcept { return value < rhs.value; } + }; + + static_assert( std::totally_ordered> ); + + using P = std::pair; + std::map c{ P{1,1}, P{2,2}, P{3,3} }, d{ P{1,1}, P{2,2}, P{3,4} }; + static_assert( std::same_as c), std::weak_ordering> ); + VERIFY( std::is_lt(c <=> d) ); +} + +// Associative container iterators are not random access +static_assert( ! std::totally_ordered::iterator> ); +static_assert( ! std::three_way_comparable::iterator> ); + +int +main() +{ + test01(); + test02(); + test04(); +} diff --git a/libstdc++-v3/testsuite/23_containers/multimap/operators/cmp_c++20.cc b/libstdc++-v3/testsuite/23_containers/multimap/operators/cmp_c++20.cc new file mode 100644 index 00000000000..350ed3e6a15 --- /dev/null +++ b/libstdc++-v3/testsuite/23_containers/multimap/operators/cmp_c++20.cc @@ -0,0 +1,111 @@ +// 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 +// . + +// { dg-options "-std=gnu++2a" } +// { dg-do run { target c++2a } } + +#include +#include + +void +test01() +{ + std::multimap c1{ {1,1}, {2,1}, {3,1} }; + std::multimap c2{ {1,1}, {2,1}, {3,1}, {4,1} }; + std::multimap c3{ {1,1}, {2,1}, {3,2} }; + 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> ); + + static_assert( std::three_way_comparable, + std::strong_ordering> ); + static_assert( ! std::three_way_comparable, + std::strong_ordering> ); + static_assert( ! std::three_way_comparable, + std::weak_ordering> ); + static_assert( std::three_way_comparable, + std::partial_ordering> ); + + struct E + { + bool operator==(E) { return true; } + }; + static_assert( ! std::totally_ordered> ); + static_assert( ! std::three_way_comparable ); + static_assert( ! std::three_way_comparable> ); +} + +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> ); + + using P = std::pair; + std::multimap c1{ P{1,1}, P{2,2}, P{3,3} }, c2{ P{1,0}, P{3,2}, P{3,3} }; + static_assert( std::same_as c1), std::weak_ordering> ); + VERIFY( c1 == c2 ); + VERIFY( std::is_eq(c1 <=> c2) ); +} + +void +test04() +{ + struct L + { + int value = 0; + + bool operator<(L rhs) const noexcept { return value < rhs.value; } + }; + + static_assert( std::totally_ordered> ); + + using P = std::pair; + std::multimap c{ P{1,1}, P{2,2}, P{3,3} }, d{ P{1,1}, P{2,2}, P{3,4} }; + static_assert( std::same_as c), std::weak_ordering> ); + VERIFY( std::is_lt(c <=> d) ); +} + +// Associative container iterators are not random access +static_assert( ! std::totally_ordered::iterator> ); +static_assert( ! std::three_way_comparable::iterator> ); + +int +main() +{ + test01(); + test02(); + test04(); +} diff --git a/libstdc++-v3/testsuite/23_containers/multiset/operators/cmp_c++20.cc b/libstdc++-v3/testsuite/23_containers/multiset/operators/cmp_c++20.cc new file mode 100644 index 00000000000..94cb7991891 --- /dev/null +++ b/libstdc++-v3/testsuite/23_containers/multiset/operators/cmp_c++20.cc @@ -0,0 +1,107 @@ +// 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 +// . + +// { dg-options "-std=gnu++2a" } +// { dg-do run { target c++2a } } + +#include +#include + +void +test01() +{ + std::multiset 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> ); + + static_assert( std::three_way_comparable, + std::strong_ordering> ); + static_assert( ! std::three_way_comparable, + std::strong_ordering> ); + static_assert( ! std::three_way_comparable, + std::weak_ordering> ); + static_assert( std::three_way_comparable, + std::partial_ordering> ); + + struct E + { + bool operator==(E) { return true; } + }; + static_assert( ! std::totally_ordered> ); + static_assert( ! std::three_way_comparable ); + static_assert( ! std::three_way_comparable> ); +} + +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::multiset c1{ {1}, {2}, {3} }, c2{ {0}, {3}, {3} }; + static_assert( std::same_as c1), std::weak_ordering> ); + VERIFY( c1 == c2 ); + VERIFY( std::is_eq(c1 <=> c2) ); +} + +void +test04() +{ + struct L + { + int value = 0; + + bool operator<(L rhs) const noexcept { return value < rhs.value; } + }; + + static_assert( std::totally_ordered> ); + + std::multiset c{ {1}, {2}, {3} }, d{ {1}, {2}, {3}, {4} }; + static_assert( std::same_as c), std::weak_ordering> ); + VERIFY( std::is_lt(c <=> d) ); +} + +// Associative container iterators are not random access +static_assert( ! std::totally_ordered::iterator> ); +static_assert( ! std::three_way_comparable::iterator> ); + +int +main() +{ + test01(); + test02(); + test04(); +} diff --git a/libstdc++-v3/testsuite/23_containers/set/operators/cmp_c++20.cc b/libstdc++-v3/testsuite/23_containers/set/operators/cmp_c++20.cc new file mode 100644 index 00000000000..fbc95c4c6f0 --- /dev/null +++ b/libstdc++-v3/testsuite/23_containers/set/operators/cmp_c++20.cc @@ -0,0 +1,107 @@ +// 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 +// . + +// { dg-options "-std=gnu++2a" } +// { dg-do run { target c++2a } } + +#include +#include + +void +test01() +{ + std::set 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> ); + + static_assert( std::three_way_comparable, + std::strong_ordering> ); + static_assert( ! std::three_way_comparable, + std::strong_ordering> ); + static_assert( ! std::three_way_comparable, + std::weak_ordering> ); + static_assert( std::three_way_comparable, + std::partial_ordering> ); + + struct E + { + bool operator==(E) { return true; } + }; + static_assert( ! std::totally_ordered> ); + static_assert( ! std::three_way_comparable ); + static_assert( ! std::three_way_comparable> ); +} + +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::set c1{ {1}, {2}, {3} }, c2{ {0}, {3}, {3} }; + static_assert( std::same_as c1), std::weak_ordering> ); + VERIFY( c1 == c2 ); + VERIFY( std::is_eq(c1 <=> c2) ); +} + +void +test04() +{ + struct L + { + int value = 0; + + bool operator<(L rhs) const noexcept { return value < rhs.value; } + }; + + static_assert( std::totally_ordered> ); + + std::set c{ {1}, {2}, {3} }, d{ {1}, {2}, {3}, {4} }; + static_assert( std::same_as c), std::weak_ordering> ); + VERIFY( std::is_lt(c <=> d) ); +} + +// Associative container iterators are not random access +static_assert( ! std::totally_ordered::iterator> ); +static_assert( ! std::three_way_comparable::iterator> ); + +int +main() +{ + test01(); + test02(); + test04(); +} -- 2.30.2