mirror of
https://github.com/intel/llvm.git
synced 2026-01-16 05:32:28 +08:00
[libc++][ranges] Implement LWG-3865 Sorting a range of pairs
Reviewed By: Mordante, philnik, ldionne, #libc Differential Revision: https://reviews.llvm.org/D144262
This commit is contained in:
@@ -294,7 +294,7 @@
|
||||
"`3843 <https://wg21.link/LWG3843>`__","``std::expected<T,E>::value() &`` assumes ``E`` is copy constructible","February 2023","","",""
|
||||
"`3847 <https://wg21.link/LWG3847>`__","``ranges::to`` can still return views","February 2023","","","|ranges|"
|
||||
"`3862 <https://wg21.link/LWG3862>`__","``basic_const_iterator``'s ``common_type`` specialization is underconstrained","February 2023","","",""
|
||||
"`3865 <https://wg21.link/LWG3865>`__","Sorting a range of ``pairs``","February 2023","","","|ranges|"
|
||||
"`3865 <https://wg21.link/LWG3865>`__","Sorting a range of ``pairs``","February 2023","|Complete|","17.0","|ranges|"
|
||||
"`3869 <https://wg21.link/LWG3869>`__","Deprecate ``std::errc`` constants related to UNIX STREAMS","February 2023","","",""
|
||||
"`3870 <https://wg21.link/LWG3870>`__","Remove ``voidify``","February 2023","","",""
|
||||
"`3871 <https://wg21.link/LWG3871>`__","Adjust note about ``terminate``","February 2023","","",""
|
||||
|
||||
|
@@ -424,22 +424,22 @@ pair(_T1, _T2) -> pair<_T1, _T2>;
|
||||
|
||||
// [pairs.spec], specialized algorithms
|
||||
|
||||
template <class _T1, class _T2>
|
||||
template <class _T1, class _T2, class _U1, class _U2>
|
||||
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14
|
||||
bool
|
||||
operator==(const pair<_T1,_T2>& __x, const pair<_T1,_T2>& __y)
|
||||
operator==(const pair<_T1,_T2>& __x, const pair<_U1,_U2>& __y)
|
||||
{
|
||||
return __x.first == __y.first && __x.second == __y.second;
|
||||
}
|
||||
|
||||
#if _LIBCPP_STD_VER >= 20
|
||||
|
||||
template <class _T1, class _T2>
|
||||
template <class _T1, class _T2, class _U1, class _U2>
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr
|
||||
common_comparison_category_t<
|
||||
__synth_three_way_result<_T1>,
|
||||
__synth_three_way_result<_T2> >
|
||||
operator<=>(const pair<_T1,_T2>& __x, const pair<_T1,_T2>& __y)
|
||||
__synth_three_way_result<_T1, _U1>,
|
||||
__synth_three_way_result<_T2, _U2> >
|
||||
operator<=>(const pair<_T1,_T2>& __x, const pair<_U1,_U2>& __y)
|
||||
{
|
||||
if (auto __c = std::__synth_three_way(__x.first, __y.first); __c != 0) {
|
||||
return __c;
|
||||
@@ -449,42 +449,42 @@ operator<=>(const pair<_T1,_T2>& __x, const pair<_T1,_T2>& __y)
|
||||
|
||||
#else // _LIBCPP_STD_VER >= 20
|
||||
|
||||
template <class _T1, class _T2>
|
||||
template <class _T1, class _T2, class _U1, class _U2>
|
||||
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14
|
||||
bool
|
||||
operator!=(const pair<_T1,_T2>& __x, const pair<_T1,_T2>& __y)
|
||||
operator!=(const pair<_T1,_T2>& __x, const pair<_U1,_U2>& __y)
|
||||
{
|
||||
return !(__x == __y);
|
||||
}
|
||||
|
||||
template <class _T1, class _T2>
|
||||
template <class _T1, class _T2, class _U1, class _U2>
|
||||
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14
|
||||
bool
|
||||
operator< (const pair<_T1,_T2>& __x, const pair<_T1,_T2>& __y)
|
||||
operator< (const pair<_T1,_T2>& __x, const pair<_U1,_U2>& __y)
|
||||
{
|
||||
return __x.first < __y.first || (!(__y.first < __x.first) && __x.second < __y.second);
|
||||
}
|
||||
|
||||
template <class _T1, class _T2>
|
||||
template <class _T1, class _T2, class _U1, class _U2>
|
||||
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14
|
||||
bool
|
||||
operator> (const pair<_T1,_T2>& __x, const pair<_T1,_T2>& __y)
|
||||
operator> (const pair<_T1,_T2>& __x, const pair<_U1,_U2>& __y)
|
||||
{
|
||||
return __y < __x;
|
||||
}
|
||||
|
||||
template <class _T1, class _T2>
|
||||
template <class _T1, class _T2, class _U1, class _U2>
|
||||
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14
|
||||
bool
|
||||
operator>=(const pair<_T1,_T2>& __x, const pair<_T1,_T2>& __y)
|
||||
operator>=(const pair<_T1,_T2>& __x, const pair<_U1,_U2>& __y)
|
||||
{
|
||||
return !(__x < __y);
|
||||
}
|
||||
|
||||
template <class _T1, class _T2>
|
||||
template <class _T1, class _T2, class _U1, class _U2>
|
||||
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14
|
||||
bool
|
||||
operator<=(const pair<_T1,_T2>& __x, const pair<_T1,_T2>& __y)
|
||||
operator<=(const pair<_T1,_T2>& __x, const pair<_U1,_U2>& __y)
|
||||
{
|
||||
return !(__y < __x);
|
||||
}
|
||||
|
||||
@@ -117,22 +117,22 @@ struct common_type<pair<T1, T2>, pair<U1, U2>>;
|
||||
|
||||
template<class T1, class T2> pair(T1, T2) -> pair<T1, T2>;
|
||||
|
||||
template <class T1, class T2>
|
||||
bool operator==(const pair<T1,T2>&, const pair<T1,T2>&); // constexpr in C++14
|
||||
template <class T1, class T2>
|
||||
bool operator!=(const pair<T1,T2>&, const pair<T1,T2>&); // constexpr in C++14, removed in C++20
|
||||
template <class T1, class T2>
|
||||
bool operator< (const pair<T1,T2>&, const pair<T1,T2>&); // constexpr in C++14, removed in C++20
|
||||
template <class T1, class T2>
|
||||
bool operator> (const pair<T1,T2>&, const pair<T1,T2>&); // constexpr in C++14, removed in C++20
|
||||
template <class T1, class T2>
|
||||
bool operator>=(const pair<T1,T2>&, const pair<T1,T2>&); // constexpr in C++14, removed in C++20
|
||||
template <class T1, class T2>
|
||||
bool operator<=(const pair<T1,T2>&, const pair<T1,T2>&); // constexpr in C++14, removed in C++20
|
||||
template <class T1, class T2>
|
||||
constexpr common_comparison_type_t<synth-three-way-result<T1>,
|
||||
synth-three-way-result<T2>>
|
||||
operator<=>(const pair<T1,T2>&, const pair<T1,T2>&); // C++20
|
||||
template <class T1, class T2, class U1, class U2>
|
||||
bool operator==(const pair<T1,T2>&, const pair<U1,U2>&); // constexpr in C++14
|
||||
template <class T1, class T2, class U1, class U2>
|
||||
bool operator!=(const pair<T1,T2>&, const pair<U1,U2>&); // constexpr in C++14, removed in C++20
|
||||
template <class T1, class T2, class U1, class U2>
|
||||
bool operator< (const pair<T1,T2>&, const pair<U1,U2>&); // constexpr in C++14, removed in C++20
|
||||
template <class T1, class T2, class U1, class U2>
|
||||
bool operator> (const pair<T1,T2>&, const pair<U1,U2>&); // constexpr in C++14, removed in C++20
|
||||
template <class T1, class T2, class U1, class U2>
|
||||
bool operator>=(const pair<T1,T2>&, const pair<U1,U2>&); // constexpr in C++14, removed in C++20
|
||||
template <class T1, class T2, class U1, class U2>
|
||||
bool operator<=(const pair<T1,T2>&, const pair<U1,U2>&); // constexpr in C++14, removed in C++20
|
||||
template <class T1, class T2, class U1, class U2>
|
||||
constexpr common_comparison_type_t<synth-three-way-result<T1,U1>,
|
||||
synth-three-way-result<T2,U2>>
|
||||
operator<=>(const pair<T1,T2>&, const pair<U1,U2>&); // C++20
|
||||
|
||||
template <class T1, class T2> pair<V1, V2> make_pair(T1&&, T2&&); // constexpr in C++14
|
||||
template <class T1, class T2>
|
||||
|
||||
@@ -61,12 +61,6 @@ constexpr bool do_constexpr_test(Tuple&& tup) {
|
||||
return std::make_from_tuple<Tp>(std::forward<Tuple>(tup)).args == tup;
|
||||
}
|
||||
|
||||
// Needed by do_forwarding_test() since it compares pairs of different types.
|
||||
template <class T1, class T2, class U1, class U2>
|
||||
inline bool operator==(const std::pair<T1, T2>& lhs, const std::pair<U1, U2>& rhs) {
|
||||
return lhs.first == rhs.first && lhs.second == rhs.second;
|
||||
}
|
||||
|
||||
template <class ...ExpectTypes, class Tuple>
|
||||
bool do_forwarding_test(Tuple&& tup) {
|
||||
using RawTuple = std::decay_t<Tuple>;
|
||||
|
||||
@@ -10,12 +10,12 @@
|
||||
|
||||
// template <class T1, class T2> struct pair
|
||||
|
||||
// template <class T1, class T2> bool operator==(const pair<T1,T2>&, const pair<T1,T2>&);
|
||||
// template <class T1, class T2> bool operator!=(const pair<T1,T2>&, const pair<T1,T2>&);
|
||||
// template <class T1, class T2> bool operator< (const pair<T1,T2>&, const pair<T1,T2>&);
|
||||
// template <class T1, class T2> bool operator> (const pair<T1,T2>&, const pair<T1,T2>&);
|
||||
// template <class T1, class T2> bool operator>=(const pair<T1,T2>&, const pair<T1,T2>&);
|
||||
// template <class T1, class T2> bool operator<=(const pair<T1,T2>&, const pair<T1,T2>&);
|
||||
// template <class T1, class T2, class U1, class U2> bool operator==(const pair<T1,T2>&, const pair<U1,U2>&);
|
||||
// template <class T1, class T2, class U1, class U2> bool operator!=(const pair<T1,T2>&, const pair<U1,U2>&);
|
||||
// template <class T1, class T2, class U1, class U2> bool operator< (const pair<T1,T2>&, const pair<U1,U2>&);
|
||||
// template <class T1, class T2, class U1, class U2> bool operator> (const pair<T1,T2>&, const pair<U1,U2>&);
|
||||
// template <class T1, class T2, class U1, class U2> bool operator>=(const pair<T1,T2>&, const pair<U1,U2>&);
|
||||
// template <class T1, class T2, class U1, class U2> bool operator<=(const pair<T1,T2>&, const pair<U1,U2>&);
|
||||
|
||||
#include <utility>
|
||||
#include <cassert>
|
||||
@@ -24,6 +24,18 @@
|
||||
|
||||
int main(int, char**)
|
||||
{
|
||||
{
|
||||
typedef std::pair<int, short> P1;
|
||||
typedef std::pair<long, long> P2;
|
||||
P1 p1(3, static_cast<short>(4));
|
||||
P2 p2(3, 4);
|
||||
assert( (p1 == p2));
|
||||
assert(!(p1 != p2));
|
||||
assert(!(p1 < p2));
|
||||
assert( (p1 <= p2));
|
||||
assert(!(p1 > p2));
|
||||
assert( (p1 >= p2));
|
||||
}
|
||||
{
|
||||
typedef std::pair<int, short> P;
|
||||
P p1(3, static_cast<short>(4));
|
||||
|
||||
@@ -10,7 +10,9 @@
|
||||
|
||||
// template <class T1, class T2> struct pair
|
||||
|
||||
// template <class T1, class T2> bool operator<=>(const pair<T1,T2>&, const pair<T1,T2>&);
|
||||
// template <class T1, class T2, class U1, class U2>
|
||||
// constexpr common_comparison_category_t<synth-three-way-result<T1, U1>,synth-three-way-result<T2, U2>>
|
||||
// operator<=>(const pair<T1,T2>&, const pair<U1,U2>&);
|
||||
|
||||
// UNSUPPORTED: c++03, c++11, c++14, c++17
|
||||
|
||||
@@ -19,14 +21,37 @@
|
||||
#include <limits>
|
||||
#include <type_traits> // std::is_constant_evaluated
|
||||
#include <utility>
|
||||
#include <string>
|
||||
|
||||
#include "test_macros.h"
|
||||
|
||||
template<class T> concept HasEqual = requires(T t) { t == t; };
|
||||
template<class T> concept HasLess = requires(T t) { t < t; };
|
||||
template<class T> concept HasSpaceship = requires(T t) { t <=> t; };
|
||||
template <class T>
|
||||
concept HasEqual = requires(T t) { t == t; };
|
||||
template <class T>
|
||||
concept HasLess = requires(T t) { t < t; };
|
||||
template <class T, class U = T>
|
||||
concept HasSpaceship = requires(T t, U u) { t <=> u; };
|
||||
|
||||
constexpr bool test() {
|
||||
{
|
||||
// Pairs of different types should compare with strong ordering.
|
||||
using P1 = std::pair<int, int>;
|
||||
using P2 = std::pair<long long, long long>;
|
||||
ASSERT_SAME_TYPE(decltype(P1() <=> P2()), std::strong_ordering);
|
||||
assert((P1(1, 1) <=> P2(1, 2)) == std::strong_ordering::less);
|
||||
assert((P1(2, 1) <=> P2(1, 2)) == std::strong_ordering::greater);
|
||||
assert((P1(0, 0) <=> P2(0, 0)) == std::strong_ordering::equal);
|
||||
}
|
||||
{
|
||||
// Pairs of different types should compare with partial ordering.
|
||||
using P1 = std::pair<int, int>;
|
||||
using P2 = std::pair<double, double>;
|
||||
ASSERT_SAME_TYPE(decltype(P1() <=> P2()), std::partial_ordering);
|
||||
assert((P1(1, 1) <=> P2(1.0, 2.0)) == std::partial_ordering::less);
|
||||
assert((P1(2, 1) <=> P2(1.0, 2.0)) == std::partial_ordering::greater);
|
||||
assert((P1(0, 0) <=> P2(0.0, 0.0)) == std::partial_ordering::equivalent);
|
||||
}
|
||||
{ static_assert(!HasSpaceship<std::pair<int, int>, std::pair<std::string, int>>); }
|
||||
{
|
||||
// Pairs of types that both have strong ordering should compare with strong ordering.
|
||||
using P = std::pair<int, int>;
|
||||
@@ -50,7 +75,7 @@ constexpr bool test() {
|
||||
}
|
||||
{
|
||||
// Pairs of int (strongly ordered) and double (partially ordered) should compare with partial ordering.
|
||||
using P = std::pair<int, double>;
|
||||
using P = std::pair<int, double>;
|
||||
constexpr double nan = std::numeric_limits<double>::quiet_NaN();
|
||||
ASSERT_SAME_TYPE(decltype(P() <=> P()), std::partial_ordering);
|
||||
assert((P(1, 1.0) <=> P(1, 2.0)) == std::partial_ordering::less);
|
||||
@@ -62,7 +87,7 @@ constexpr bool test() {
|
||||
assert((P(1, nan) <=> P(1, nan)) == std::partial_ordering::unordered);
|
||||
}
|
||||
{
|
||||
using P = std::pair<double, int>;
|
||||
using P = std::pair<double, int>;
|
||||
constexpr double nan = std::numeric_limits<double>::quiet_NaN();
|
||||
ASSERT_SAME_TYPE(decltype(P() <=> P()), std::partial_ordering);
|
||||
assert((P(2.0, 1) <=> P(1.0, 2)) == std::partial_ordering::greater);
|
||||
@@ -93,12 +118,12 @@ constexpr bool test() {
|
||||
#endif
|
||||
{
|
||||
{
|
||||
using P = std::pair<int, double>;
|
||||
using P = std::pair<int, double>;
|
||||
constexpr double nan = std::numeric_limits<double>::quiet_NaN();
|
||||
assert((P(1, 2.0) <=> P(1, nan)) == std::partial_ordering::unordered);
|
||||
}
|
||||
{
|
||||
using P = std::pair<double, int>;
|
||||
using P = std::pair<double, int>;
|
||||
constexpr double nan = std::numeric_limits<double>::quiet_NaN();
|
||||
assert((P(1.0, 1) <=> P(nan, 2)) == std::partial_ordering::unordered);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user