diff --git a/stl/inc/memory b/stl/inc/memory index 279effbcc6b..1e2d864a9be 100644 --- a/stl/inc/memory +++ b/stl/inc/memory @@ -1791,6 +1791,13 @@ _NODISCARD bool operator==(const shared_ptr<_Ty1>& _Left, const shared_ptr<_Ty2> return _Left.get() == _Right.get(); } +#if _HAS_CXX20 +template +_NODISCARD strong_ordering operator<=>(const shared_ptr<_Ty1>& _Left, const shared_ptr<_Ty2>& _Right) noexcept { + return _Left.get() <=> _Right.get(); +} + +#else // ^^^ _HAS_CXX20 / !_HAS_CXX20 vvv template _NODISCARD bool operator!=(const shared_ptr<_Ty1>& _Left, const shared_ptr<_Ty2>& _Right) noexcept { return _Left.get() != _Right.get(); @@ -1815,12 +1822,20 @@ template _NODISCARD bool operator<=(const shared_ptr<_Ty1>& _Left, const shared_ptr<_Ty2>& _Right) noexcept { return _Left.get() <= _Right.get(); } +#endif // ^^^ !_HAS_CXX20 ^^^ template _NODISCARD bool operator==(const shared_ptr<_Ty>& _Left, nullptr_t) noexcept { return _Left.get() == nullptr; } +#if _HAS_CXX20 +template +_NODISCARD strong_ordering operator<=>(const shared_ptr<_Ty>& _Left, nullptr_t) noexcept { + return _Left.get() <=> static_cast::element_type*>(nullptr); +} + +#else // ^^^ _HAS_CXX20 / !_HAS_CXX20 vvv template _NODISCARD bool operator==(nullptr_t, const shared_ptr<_Ty>& _Right) noexcept { return nullptr == _Right.get(); @@ -1875,6 +1890,7 @@ template _NODISCARD bool operator<=(nullptr_t, const shared_ptr<_Ty>& _Right) noexcept { return static_cast::element_type*>(nullptr) <= _Right.get(); } +#endif // ^^^ !_HAS_CXX20 ^^^ template basic_ostream<_Elem, _Traits>& operator<<(basic_ostream<_Elem, _Traits>& _Out, const shared_ptr<_Ty>& _Px) { @@ -3415,10 +3431,12 @@ _NODISCARD bool operator==(const unique_ptr<_Ty1, _Dx1>& _Left, const unique_ptr return _Left.get() == _Right.get(); } +#if !_HAS_CXX20 template _NODISCARD bool operator!=(const unique_ptr<_Ty1, _Dx1>& _Left, const unique_ptr<_Ty2, _Dx2>& _Right) { return !(_Left == _Right); } +#endif // !_HAS_CXX20 template _NODISCARD bool operator<(const unique_ptr<_Ty1, _Dx1>& _Left, const unique_ptr<_Ty2, _Dx2>& _Right) { @@ -3443,11 +3461,25 @@ _NODISCARD bool operator<=(const unique_ptr<_Ty1, _Dx1>& _Left, const unique_ptr return !(_Right < _Left); } +#ifdef __cpp_lib_concepts +// clang-format off +template + requires three_way_comparable_with::pointer, + typename unique_ptr<_Ty2, _Dx2>::pointer> +_NODISCARD compare_three_way_result_t::pointer, + typename unique_ptr<_Ty2, _Dx2>::pointer> + operator<=>(const unique_ptr<_Ty1, _Dx1>& _Left, const unique_ptr<_Ty2, _Dx2>& _Right) { + // clang-format on + return _Left.get() <=> _Right.get(); +} +#endif // __cpp_lib_concepts + template _NODISCARD bool operator==(const unique_ptr<_Ty, _Dx>& _Left, nullptr_t) noexcept { return !_Left; } +#if !_HAS_CXX20 template _NODISCARD bool operator==(nullptr_t, const unique_ptr<_Ty, _Dx>& _Right) noexcept { return !_Right; @@ -3462,6 +3494,7 @@ template _NODISCARD bool operator!=(nullptr_t _Left, const unique_ptr<_Ty, _Dx>& _Right) noexcept { return !(_Left == _Right); } +#endif // !_HAS_CXX20 template _NODISCARD bool operator<(const unique_ptr<_Ty, _Dx>& _Left, nullptr_t _Right) { @@ -3505,6 +3538,17 @@ _NODISCARD bool operator<=(nullptr_t _Left, const unique_ptr<_Ty, _Dx>& _Right) return !(_Right < _Left); } +#ifdef __cpp_lib_concepts +// clang-format off +template + requires three_way_comparable::pointer> +_NODISCARD compare_three_way_result_t::pointer> operator<=>( + const unique_ptr<_Ty, _Dx>& _Left, nullptr_t) { + // clang-format on + return _Left.get() <=> static_cast::pointer>(nullptr); +} +#endif // __cpp_lib_concepts + template struct _Can_stream_unique_ptr : false_type {}; template diff --git a/tests/std/tests/P1614R2_spaceship/test.cpp b/tests/std/tests/P1614R2_spaceship/test.cpp index dd19714b162..b53a111df7e 100644 --- a/tests/std/tests/P1614R2_spaceship/test.cpp +++ b/tests/std/tests/P1614R2_spaceship/test.cpp @@ -864,6 +864,26 @@ void ordering_test_cases() { assert((m1 <=> m2) == 0); static_assert((m1 <=> m2) == 0); } + { // unique_ptr + std::unique_ptr p1{nullptr}; + std::unique_ptr& p2 = p1; + std::unique_ptr p3{new int}; + + spaceship_test(p1, p2, p3); + spaceship_test(p1, nullptr, p3); + } + { // shared_ptr + std::shared_ptr p1{nullptr}; + std::shared_ptr& p2 = p1; // same managed ptr + std::shared_ptr p3 = p2; // same stored ptr + + std::shared_ptr p4{new int}; + std::shared_ptr p5 = p4; // same stored ptr + + spaceship_test(p1, p2, p4); + spaceship_test(p1, p3, p5); + spaceship_test(p1, nullptr, p4); + } { // slice std::slice a1(2, 3, 4); std::slice a2(2, 3, 4); diff --git a/tests/tr1/tests/memory1/test.cpp b/tests/tr1/tests/memory1/test.cpp index c27161919eb..695d941c98a 100644 --- a/tests/tr1/tests/memory1/test.cpp +++ b/tests/tr1/tests/memory1/test.cpp @@ -13,6 +13,9 @@ #include #include +// TRANSITION, VSO-1281038: False C6287 for C++20 synthesized operators +#pragma warning(disable : 6287) // Redundant code: the left and right sub-expressions are identical. + static void t_bad_weak_ptr() { // test bad_weak_ptr STD bad_weak_ptr ptr; STD exception* eptr = &ptr;