diff --git a/libcxx/docs/ReleaseNotes.rst b/libcxx/docs/ReleaseNotes.rst --- a/libcxx/docs/ReleaseNotes.rst +++ b/libcxx/docs/ReleaseNotes.rst @@ -41,6 +41,8 @@ Improvements and New Features ----------------------------- +* Implemented ``operator<=>`` for ``std::shared_ptr`` + Deprecations and Removals ------------------------- diff --git a/libcxx/docs/Status/SpaceshipProjects.csv b/libcxx/docs/Status/SpaceshipProjects.csv --- a/libcxx/docs/Status/SpaceshipProjects.csv +++ b/libcxx/docs/Status/SpaceshipProjects.csv @@ -26,7 +26,7 @@ | `[variant.monostate.relops] `_","| monostate | variant",None,Kent Ross,|In Progress| | `[unique.ptr.special] `_,| unique_ptr,[comparisons.three.way],Unassigned,|Not Started| -| `[util.smartptr.shared.cmp] `_,| shared_ptr,[comparisons.three.way],Unassigned,|Not Started| +| `[util.smartptr.shared.cmp] `_,| shared_ptr,[comparisons.three.way],Adrian Vogelsgesang,|Complete| | `[type.index.members] `_,| type_index,None,Unassigned,|Not Started| | `[charconv.syn] `_,| to_chars_result,None,Mark de Wever,|Complete| | `[charconv.syn] `_,| from_chars_result,None,Mark de Wever,|Complete| diff --git a/libcxx/include/__memory/shared_ptr.h b/libcxx/include/__memory/shared_ptr.h --- a/libcxx/include/__memory/shared_ptr.h +++ b/libcxx/include/__memory/shared_ptr.h @@ -1184,6 +1184,8 @@ return __x.get() == __y.get(); } +#if _LIBCPP_STD_VER <= 17 + template inline _LIBCPP_INLINE_VISIBILITY bool @@ -1230,6 +1232,17 @@ return !(__x < __y); } +#endif // _LIBCPP_STD_VER <= 17 + +#if _LIBCPP_STD_VER > 17 +template +strong_ordering +operator<=>(shared_ptr<_Tp> const& __a, shared_ptr<_Up> const& __b) _NOEXCEPT +{ + return compare_three_way()(__a.get(), __b.get()); +} +#endif + template inline _LIBCPP_INLINE_VISIBILITY bool @@ -1238,6 +1251,8 @@ return !__x; } +#if _LIBCPP_STD_VER <= 17 + template inline _LIBCPP_INLINE_VISIBILITY bool @@ -1326,6 +1341,17 @@ return !(nullptr < __x); } +#endif // _LIBCPP_STD_VER <= 17 + +#if _LIBCPP_STD_VER > 17 +template +strong_ordering +operator<=>(shared_ptr<_Tp> const& __a, nullptr_t) _NOEXCEPT +{ + return compare_three_way()(__a.get(), static_cast::element_type*>(nullptr)); +} +#endif + template inline _LIBCPP_INLINE_VISIBILITY void diff --git a/libcxx/include/memory b/libcxx/include/memory --- a/libcxx/include/memory +++ b/libcxx/include/memory @@ -617,40 +617,44 @@ template bool operator==(shared_ptr const& a, shared_ptr const& b) noexcept; template - bool operator!=(shared_ptr const& a, shared_ptr const& b) noexcept; + bool operator!=(shared_ptr const& a, shared_ptr const& b) noexcept; // removed in C++20 template - bool operator<(shared_ptr const& a, shared_ptr const& b) noexcept; + bool operator<(shared_ptr const& a, shared_ptr const& b) noexcept; // removed in C++20 template - bool operator>(shared_ptr const& a, shared_ptr const& b) noexcept; + bool operator>(shared_ptr const& a, shared_ptr const& b) noexcept; // removed in C++20 template - bool operator<=(shared_ptr const& a, shared_ptr const& b) noexcept; + bool operator<=(shared_ptr const& a, shared_ptr const& b) noexcept; // removed in C++20 template - bool operator>=(shared_ptr const& a, shared_ptr const& b) noexcept; + bool operator>=(shared_ptr const& a, shared_ptr const& b) noexcept; // removed in C++20 +template + strong_ordering operator<=>(shared_ptr const& a, shared_ptr const& b) noexcept; // C++20 template bool operator==(const shared_ptr& x, nullptr_t) noexcept; template - bool operator==(nullptr_t, const shared_ptr& y) noexcept; + bool operator==(nullptr_t, const shared_ptr& y) noexcept; // removed in C++20 template - bool operator!=(const shared_ptr& x, nullptr_t) noexcept; + bool operator!=(const shared_ptr& x, nullptr_t) noexcept; // removed in C++20 template - bool operator!=(nullptr_t, const shared_ptr& y) noexcept; + bool operator!=(nullptr_t, const shared_ptr& y) noexcept; // removed in C++20 template - bool operator<(const shared_ptr& x, nullptr_t) noexcept; + bool operator<(const shared_ptr& x, nullptr_t) noexcept; // removed in C++20 template -bool operator<(nullptr_t, const shared_ptr& y) noexcept; + bool operator<(nullptr_t, const shared_ptr& y) noexcept; // removed in C++20 template - bool operator<=(const shared_ptr& x, nullptr_t) noexcept; + bool operator<=(const shared_ptr& x, nullptr_t) noexcept; // removed in C++20 template - bool operator<=(nullptr_t, const shared_ptr& y) noexcept; + bool operator<=(nullptr_t, const shared_ptr& y) noexcept; // removed in C++20 template - bool operator>(const shared_ptr& x, nullptr_t) noexcept; + bool operator>(const shared_ptr& x, nullptr_t) noexcept; // removed in C++20 template - bool operator>(nullptr_t, const shared_ptr& y) noexcept; + bool operator>(nullptr_t, const shared_ptr& y) noexcept; // removed in C++20 template - bool operator>=(const shared_ptr& x, nullptr_t) noexcept; + bool operator>=(const shared_ptr& x, nullptr_t) noexcept; // removed in C++20 template - bool operator>=(nullptr_t, const shared_ptr& y) noexcept; + bool operator>=(nullptr_t, const shared_ptr& y) noexcept; // removed in C++20 +template + strong_ordering operator<=>(shared_ptr const& a, nullptr_t) noexcept; // C++20 // shared_ptr specialized algorithms: template void swap(shared_ptr& a, shared_ptr& b) noexcept; diff --git a/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.cmp/cmp_nullptr.pass.cpp b/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.cmp/cmp_nullptr.pass.cpp --- a/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.cmp/cmp_nullptr.pass.cpp +++ b/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.cmp/cmp_nullptr.pass.cpp @@ -34,6 +34,8 @@ // bool operator>=(const shared_ptr& x, nullptr_t) noexcept; // template // bool operator>=(nullptr_t, const shared_ptr& y) noexcept; +// template +// strong_ordering operator<=>(shared_ptr const& a, nullptr_t) noexcept; // C++20 #include #include @@ -55,6 +57,10 @@ assert(!(nullptr > p1)); assert( (p1 >= nullptr)); assert(!(nullptr >= p1)); +#if TEST_STD_VER > 17 + assert((nullptr <=> p1) == std::strong_ordering::less); + assert((p1 <=> nullptr) == std::strong_ordering::greater); +#endif const std::shared_ptr p2; assert( (p2 == nullptr)); @@ -67,6 +73,9 @@ assert(!(nullptr > p2)); assert( (p2 >= nullptr)); assert( (nullptr >= p2)); +#if TEST_STD_VER > 17 + assert((nullptr <=> p2) == std::strong_ordering::equivalent); +#endif - return 0; + return 0; } diff --git a/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.cmp/order.pass.cpp b/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.cmp/order.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.cmp/order.pass.cpp @@ -0,0 +1,36 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// + +// shared_ptr + +// template +// strong_ordering operator<=>(shared_ptr const& a, shared_ptr const& b) noexcept; + +#include +#include + +#include "test_macros.h" + +void do_nothing(int*) {} + +int main(int, char**) { +#if TEST_STD_VER > 17 + int* ptr1(new int); + int* ptr2(new int); + const std::shared_ptr p1(ptr1); + const std::shared_ptr p2(ptr2); + const std::shared_ptr p3(ptr2, do_nothing); + assert((p1 <=> p2) != std::strong_ordering::equal); + assert((p1 <=> p2) == (ptr1 <=> ptr2)); + assert((p2 <=> p3) == std::strong_ordering::equal); +#endif + + return 0; +}