From 1b3d208c77145b670207a646050bbe2cc8aea567 Mon Sep 17 00:00:00 2001 From: Avi Patel Date: Mon, 27 Jul 2026 06:00:45 -0400 Subject: [PATCH] [libc++] Implement P1901R2: owner_hash and owner_equal for shared_ptr/weak_ptr (#210551) Fixes #105372. ## Acknowledgements Claude assisted with test development. --- libcxx/docs/FeatureTestMacroTable.rst | 2 +- libcxx/docs/ReleaseNotes/24.rst | 1 + libcxx/docs/Status/Cxx26Papers.csv | 2 +- libcxx/include/__memory/shared_ptr.h | 73 +++++++++++++++++++ libcxx/include/memory | 31 ++++++++ libcxx/include/version | 2 +- libcxx/modules/std/memory.inc | 8 ++ .../utilities/smartptr/nodiscard.verify.cpp | 32 ++++++++ .../memory.version.compile.pass.cpp | 16 ++-- .../version.version.compile.pass.cpp | 16 ++-- .../owner_equal_shared_ptr.pass.cpp | 42 +++++++++++ .../owner_equal_weak_ptr.pass.cpp | 43 +++++++++++ .../owner_hash.pass.cpp | 46 ++++++++++++ .../owner_equal.pass.cpp | 71 ++++++++++++++++++ .../owner_hash.pass.cpp | 51 +++++++++++++ .../owner_equal_shared_ptr.pass.cpp | 39 ++++++++++ .../owner_equal_weak_ptr.pass.cpp | 44 +++++++++++ .../owner_hash.pass.cpp | 36 +++++++++ .../generate_feature_test_macro_components.py | 1 - 19 files changed, 530 insertions(+), 26 deletions(-) create mode 100644 libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.obs/owner_equal_shared_ptr.pass.cpp create mode 100644 libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.obs/owner_equal_weak_ptr.pass.cpp create mode 100644 libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.obs/owner_hash.pass.cpp create mode 100644 libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.weak/util.smartptr.ownerequal/owner_equal.pass.cpp create mode 100644 libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.weak/util.smartptr.ownerhash/owner_hash.pass.cpp create mode 100644 libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.weak/util.smartptr.weak.obs/owner_equal_shared_ptr.pass.cpp create mode 100644 libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.weak/util.smartptr.weak.obs/owner_equal_weak_ptr.pass.cpp create mode 100644 libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.weak/util.smartptr.weak.obs/owner_hash.pass.cpp diff --git a/libcxx/docs/FeatureTestMacroTable.rst b/libcxx/docs/FeatureTestMacroTable.rst index 108702e71dec..60af581e122e 100644 --- a/libcxx/docs/FeatureTestMacroTable.rst +++ b/libcxx/docs/FeatureTestMacroTable.rst @@ -526,7 +526,7 @@ Status ---------------------------------------------------------- ----------------- ``__cpp_lib_senders`` *unimplemented* ---------------------------------------------------------- ----------------- - ``__cpp_lib_smart_ptr_owner_equality`` *unimplemented* + ``__cpp_lib_smart_ptr_owner_equality`` ``202306L`` ---------------------------------------------------------- ----------------- ``__cpp_lib_span_at`` ``202311L`` ---------------------------------------------------------- ----------------- diff --git a/libcxx/docs/ReleaseNotes/24.rst b/libcxx/docs/ReleaseNotes/24.rst index e20fa560865a..2cd6a4c75611 100644 --- a/libcxx/docs/ReleaseNotes/24.rst +++ b/libcxx/docs/ReleaseNotes/24.rst @@ -42,6 +42,7 @@ Implemented Papers - P0792R14: ``function_ref`` : a type-erased callable reference (`Github `__) - P3948R1: ``constant_wrapper`` is the only tool needed for passing constant expressions via function arguments (`Github `__) - P3961R1: Less double indirection in ``function_ref`` (RU-220) (`Github `__) +- P1901R2: Enabling the Use of ``weak_ptr`` as Keys in Unordered Associative Containers (`Github `__) Improvements and New Features ----------------------------- diff --git a/libcxx/docs/Status/Cxx26Papers.csv b/libcxx/docs/Status/Cxx26Papers.csv index 81b20f608809..855ac2533a28 100644 --- a/libcxx/docs/Status/Cxx26Papers.csv +++ b/libcxx/docs/Status/Cxx26Papers.csv @@ -12,7 +12,7 @@ "`P2338R4 `__","Freestanding Library: Character primitives and the C library","2023-06 (Varna)","","","`#105369 `__","" "`P2013R5 `__","Freestanding Language: Optional ``::operator new``","2023-06 (Varna)","","","`#105370 `__","" "`P2363R5 `__","Extending associative containers with the remaining heterogeneous overloads","2023-06 (Varna)","","","`#105371 `__","" -"`P1901R2 `__","Enabling the Use of ``weak_ptr`` as Keys in Unordered Associative Containers","2023-06 (Varna)","","","`#105372 `__","" +"`P1901R2 `__","Enabling the Use of ``weak_ptr`` as Keys in Unordered Associative Containers","2023-06 (Varna)","|Complete|","24","`#105372 `__","" "`P1885R12 `__","Naming Text Encodings to Demystify Them","2023-06 (Varna)","|Complete|","23","`#105373 `__","" "`P0792R14 `__","``function_ref``: a type-erased callable reference","2023-06 (Varna)","|Complete|","24","`#105376 `__","" "`P2874R2 `__","P2874R2: Mandating Annex D Require No More","2023-06 (Varna)","|Complete|","12","`#105377 `__","" diff --git a/libcxx/include/__memory/shared_ptr.h b/libcxx/include/__memory/shared_ptr.h index 4112c1175b9e..7d8a0d27739a 100644 --- a/libcxx/include/__memory/shared_ptr.h +++ b/libcxx/include/__memory/shared_ptr.h @@ -18,6 +18,7 @@ #include <__cstddef/ptrdiff_t.h> #include <__exception/exception.h> #include <__functional/binary_function.h> +#include <__functional/hash.h> #include <__functional/operations.h> #include <__functional/reference_wrapper.h> #include <__fwd/ostream.h> @@ -555,6 +556,22 @@ public: _LIBCPP_HIDE_FROM_ABI bool __owner_equivalent(const shared_ptr& __p) const { return __cntrl_ == __p.__cntrl_; } +#if _LIBCPP_STD_VER >= 26 + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI size_t owner_hash() const noexcept { + return std::hash<__shared_weak_count*>()(__cntrl_); + } + + template + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI bool owner_equal(shared_ptr<_Up> const& __p) const noexcept { + return __cntrl_ == __p.__cntrl_; + } + + template + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI bool owner_equal(weak_ptr<_Up> const& __p) const noexcept { + return __cntrl_ == __p.__cntrl_; + } +#endif + #if _LIBCPP_STD_VER >= 17 [[nodiscard]] _LIBCPP_HIDE_FROM_ABI __add_lvalue_reference_t operator[](ptrdiff_t __i) const { static_assert(is_array<_Tp>::value, "std::shared_ptr::operator[] is only valid when T is an array type."); @@ -1245,6 +1262,22 @@ public: return __cntrl_ < __r.__cntrl_; } +#if _LIBCPP_STD_VER >= 26 + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI size_t owner_hash() const noexcept { + return std::hash<__shared_weak_count*>()(__cntrl_); + } + + template + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI bool owner_equal(shared_ptr<_Up> const& __p) const noexcept { + return __cntrl_ == __p.__cntrl_; + } + + template + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI bool owner_equal(weak_ptr<_Up> const& __p) const noexcept { + return __cntrl_ == __p.__cntrl_; + } +#endif + template friend class weak_ptr; template @@ -1318,6 +1351,46 @@ struct owner_less { }; #endif +#if _LIBCPP_STD_VER >= 26 +struct owner_hash { + template + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI size_t operator()(shared_ptr<_Tp> const& __p) const noexcept { + return __p.owner_hash(); + } + template + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI size_t operator()(weak_ptr<_Tp> const& __p) const noexcept { + return __p.owner_hash(); + } + + using is_transparent = void; +}; + +struct owner_equal { + template + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI bool + operator()(shared_ptr<_Tp> const& __x, shared_ptr<_Up> const& __y) const noexcept { + return __x.owner_equal(__y); + } + template + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI bool + operator()(shared_ptr<_Tp> const& __x, weak_ptr<_Up> const& __y) const noexcept { + return __x.owner_equal(__y); + } + template + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI bool + operator()(weak_ptr<_Tp> const& __x, shared_ptr<_Up> const& __y) const noexcept { + return __x.owner_equal(__y); + } + template + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI bool + operator()(weak_ptr<_Tp> const& __x, weak_ptr<_Up> const& __y) const noexcept { + return __x.owner_equal(__y); + } + + using is_transparent = void; +}; +#endif + template class enable_shared_from_this { mutable weak_ptr<_Tp> __weak_this_; diff --git a/libcxx/include/memory b/libcxx/include/memory index d5d48ed9a9e6..6a16358324f1 100644 --- a/libcxx/include/memory +++ b/libcxx/include/memory @@ -633,6 +633,9 @@ public: explicit operator bool() const noexcept; template bool owner_before(shared_ptr const& b) const noexcept; template bool owner_before(weak_ptr const& b) const noexcept; + size_t owner_hash() const noexcept; // C++26 + template bool owner_equal(shared_ptr const& b) const noexcept; // C++26 + template bool owner_equal(weak_ptr const& b) const noexcept; // C++26 }; template @@ -771,6 +774,9 @@ public: shared_ptr lock() const noexcept; template bool owner_before(shared_ptr const& b) const noexcept; template bool owner_before(weak_ptr const& b) const noexcept; + size_t owner_hash() const noexcept; // C++26 + template bool owner_equal(shared_ptr const& b) const noexcept; // C++26 + template bool owner_equal(weak_ptr const& b) const noexcept; // C++26 }; template @@ -817,6 +823,31 @@ struct owner_less typedef void is_transparent; }; +// struct owner_hash +struct owner_hash { // C++26 + template + size_t operator()(const shared_ptr&) const noexcept; + + template + size_t operator()(const weak_ptr&) const noexcept; + + using is_transparent = unspecified; +}; + +// struct owner_equal +struct owner_equal { // C++26 + template + bool operator()(const shared_ptr&, const shared_ptr&) const noexcept; + template + bool operator()(const shared_ptr&, const weak_ptr&) const noexcept; + template + bool operator()(const weak_ptr&, const shared_ptr&) const noexcept; + template + bool operator()(const weak_ptr&, const weak_ptr&) const noexcept; + + using is_transparent = unspecified; +}; + template class enable_shared_from_this { diff --git a/libcxx/include/version b/libcxx/include/version index 9160c51835d6..5d0b96a1fe23 100644 --- a/libcxx/include/version +++ b/libcxx/include/version @@ -628,7 +628,7 @@ __cpp_lib_void_t 201411L # define __cpp_lib_reference_wrapper 202403L # define __cpp_lib_saturation_arithmetic 202603L // # define __cpp_lib_senders 202406L -// # define __cpp_lib_smart_ptr_owner_equality 202306L +# define __cpp_lib_smart_ptr_owner_equality 202306L # define __cpp_lib_span_at 202311L # define __cpp_lib_sstream_from_string_view 202306L # define __cpp_lib_string_subview 202506L diff --git a/libcxx/modules/std/memory.inc b/libcxx/modules/std/memory.inc index c25e9e3443e9..0338ec0db325 100644 --- a/libcxx/modules/std/memory.inc +++ b/libcxx/modules/std/memory.inc @@ -171,6 +171,14 @@ export namespace std { // [util.smartptr.ownerless], class template owner_less using std::owner_less; +#if _LIBCPP_STD_VER >= 26 + // [util.smartptr.owner.hash], class owner_hash + using std::owner_hash; + + // [util.smartptr.owner.equal], class owner_equal + using std::owner_equal; +#endif + // [util.smartptr.enab], class template enable_shared_from_this using std::enable_shared_from_this; diff --git a/libcxx/test/libcxx/utilities/smartptr/nodiscard.verify.cpp b/libcxx/test/libcxx/utilities/smartptr/nodiscard.verify.cpp index 6943a4002c24..84020942f0a7 100644 --- a/libcxx/test/libcxx/utilities/smartptr/nodiscard.verify.cpp +++ b/libcxx/test/libcxx/utilities/smartptr/nodiscard.verify.cpp @@ -59,6 +59,14 @@ void test() { sPtr.owner_before(std::shared_ptr()); // expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}} sPtr.owner_before(std::weak_ptr()); +#if TEST_STD_VER >= 26 + // expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}} + sPtr.owner_hash(); + // expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}} + sPtr.owner_equal(std::shared_ptr()); + // expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}} + sPtr.owner_equal(std::weak_ptr()); +#endif #if TEST_STD_VER >= 17 sPtr[0]; // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} #endif @@ -138,7 +146,31 @@ void test() { wPtr.owner_before(std::weak_ptr()); // expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}} wPtr.owner_before(std::shared_ptr()); +#if TEST_STD_VER >= 26 + // expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}} + wPtr.owner_hash(); + // expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}} + wPtr.owner_equal(std::weak_ptr()); + // expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}} + wPtr.owner_equal(std::shared_ptr()); +#endif } +#if TEST_STD_VER >= 26 + { // [util.smartptr.owner.hash], [util.smartptr.owner.equal] + std::shared_ptr sPtr; + std::weak_ptr wPtr; + + std::owner_hash oh; + oh(sPtr); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + oh(wPtr); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + + std::owner_equal oe; + oe(sPtr, sPtr); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + oe(sPtr, wPtr); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + oe(wPtr, sPtr); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + oe(wPtr, wPtr); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + } +#endif { // [util.smartptr.enab] class EnableShared : public std::enable_shared_from_this {}; EnableShared es; diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/memory.version.compile.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/memory.version.compile.pass.cpp index c58357a463ff..dc14ff766ac5 100644 --- a/libcxx/test/std/language.support/support.limits/support.limits.general/memory.version.compile.pass.cpp +++ b/libcxx/test/std/language.support/support.limits/support.limits.general/memory.version.compile.pass.cpp @@ -648,17 +648,11 @@ # error "__cpp_lib_smart_ptr_for_overwrite should have the value 202002L in c++26" # endif -# if !defined(_LIBCPP_VERSION) -# ifndef __cpp_lib_smart_ptr_owner_equality -# error "__cpp_lib_smart_ptr_owner_equality should be defined in c++26" -# endif -# if __cpp_lib_smart_ptr_owner_equality != 202306L -# error "__cpp_lib_smart_ptr_owner_equality should have the value 202306L in c++26" -# endif -# else -# ifdef __cpp_lib_smart_ptr_owner_equality -# error "__cpp_lib_smart_ptr_owner_equality should not be defined because it is unimplemented in libc++!" -# endif +# ifndef __cpp_lib_smart_ptr_owner_equality +# error "__cpp_lib_smart_ptr_owner_equality should be defined in c++26" +# endif +# if __cpp_lib_smart_ptr_owner_equality != 202306L +# error "__cpp_lib_smart_ptr_owner_equality should have the value 202306L in c++26" # endif # ifndef __cpp_lib_to_address diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp index 3af3d6694c6b..9143d715ff7d 100644 --- a/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp +++ b/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp @@ -8012,17 +8012,11 @@ # error "__cpp_lib_smart_ptr_for_overwrite should have the value 202002L in c++26" # endif -# if !defined(_LIBCPP_VERSION) -# ifndef __cpp_lib_smart_ptr_owner_equality -# error "__cpp_lib_smart_ptr_owner_equality should be defined in c++26" -# endif -# if __cpp_lib_smart_ptr_owner_equality != 202306L -# error "__cpp_lib_smart_ptr_owner_equality should have the value 202306L in c++26" -# endif -# else -# ifdef __cpp_lib_smart_ptr_owner_equality -# error "__cpp_lib_smart_ptr_owner_equality should not be defined because it is unimplemented in libc++!" -# endif +# ifndef __cpp_lib_smart_ptr_owner_equality +# error "__cpp_lib_smart_ptr_owner_equality should be defined in c++26" +# endif +# if __cpp_lib_smart_ptr_owner_equality != 202306L +# error "__cpp_lib_smart_ptr_owner_equality should have the value 202306L in c++26" # endif # ifndef __cpp_lib_source_location diff --git a/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.obs/owner_equal_shared_ptr.pass.cpp b/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.obs/owner_equal_shared_ptr.pass.cpp new file mode 100644 index 000000000000..356ad0ab4827 --- /dev/null +++ b/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.obs/owner_equal_shared_ptr.pass.cpp @@ -0,0 +1,42 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: std-at-least-c++26 + +// + +// shared_ptr + +// template bool owner_equal(shared_ptr const& b) const noexcept; + +#include +#include +#include + +#include "test_macros.h" + +int main(int, char**) { + const std::shared_ptr p1(new int); + const std::shared_ptr p2 = p1; + const std::shared_ptr p3(new int); + const std::shared_ptr empty1; + const std::shared_ptr empty2; + + std::same_as decltype(auto) result = p1.owner_equal(p2); + assert(result); + static_assert(noexcept(p1.owner_equal(p2))); + + assert(p2.owner_equal(p1)); + assert(!p1.owner_equal(p3)); + assert(!p3.owner_equal(p1)); + + assert(empty1.owner_equal(empty2)); + assert(!p1.owner_equal(empty1)); + + return 0; +} diff --git a/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.obs/owner_equal_weak_ptr.pass.cpp b/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.obs/owner_equal_weak_ptr.pass.cpp new file mode 100644 index 000000000000..11166b2bec49 --- /dev/null +++ b/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.obs/owner_equal_weak_ptr.pass.cpp @@ -0,0 +1,43 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: std-at-least-c++26 + +// + +// shared_ptr + +// template bool owner_equal(weak_ptr const& b) const noexcept; + +#include +#include +#include + +#include "test_macros.h" + +int main(int, char**) { + const std::shared_ptr p1(new int); + const std::shared_ptr p2 = p1; + const std::shared_ptr p3(new int); + const std::weak_ptr w1(p1); + const std::weak_ptr w3(p3); + const std::shared_ptr empty_sp; + const std::weak_ptr empty_wp; + + std::same_as decltype(auto) result = p1.owner_equal(w1); + assert(result); + static_assert(noexcept(p1.owner_equal(w1))); + + assert(p2.owner_equal(w1)); + assert(!p1.owner_equal(w3)); + assert(!p3.owner_equal(w1)); + + assert(empty_sp.owner_equal(empty_wp)); + + return 0; +} diff --git a/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.obs/owner_hash.pass.cpp b/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.obs/owner_hash.pass.cpp new file mode 100644 index 000000000000..79ebea344ba7 --- /dev/null +++ b/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.obs/owner_hash.pass.cpp @@ -0,0 +1,46 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: std-at-least-c++26 + +// + +// shared_ptr + +// size_t owner_hash() const noexcept; + +#include +#include +#include +#include + +#include "test_macros.h" + +struct Pair { + int a; + int b; +}; + +int main(int, char**) { + const std::shared_ptr p1(new int); + const std::shared_ptr p2 = p1; + const std::weak_ptr w1(p1); + + std::same_as decltype(auto) hash1 = p1.owner_hash(); + static_assert(noexcept(p1.owner_hash())); + + assert(hash1 == p2.owner_hash()); + assert(hash1 == w1.owner_hash()); + + const std::shared_ptr sp(new Pair{1, 2}); + const std::shared_ptr alias(sp, &sp->b); + assert(static_cast(sp.get()) != static_cast(alias.get())); + assert(sp.owner_hash() == alias.owner_hash()); + + return 0; +} diff --git a/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.weak/util.smartptr.ownerequal/owner_equal.pass.cpp b/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.weak/util.smartptr.ownerequal/owner_equal.pass.cpp new file mode 100644 index 000000000000..ce8580c7547b --- /dev/null +++ b/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.weak/util.smartptr.ownerequal/owner_equal.pass.cpp @@ -0,0 +1,71 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: std-at-least-c++26 + +// + +// struct owner_equal +// { +// template +// bool operator()(shared_ptr const&, shared_ptr const&) const noexcept; +// template +// bool operator()(shared_ptr const&, weak_ptr const&) const noexcept; +// template +// bool operator()(weak_ptr const&, shared_ptr const&) const noexcept; +// template +// bool operator()(weak_ptr const&, weak_ptr const&) const noexcept; +// +// using is_transparent = unspecified; +// }; + +#include +#include +#include +#include + +#include "test_macros.h" + +int main(int, char**) { + const std::shared_ptr p1(new int); + const std::shared_ptr p2 = p1; + const std::shared_ptr p3(new int); + const std::weak_ptr w1(p1); + const std::weak_ptr w3(p3); + + std::owner_equal oe; + + std::same_as decltype(auto) result = oe(p1, p2); + assert(result); + static_assert(noexcept(oe(p1, p2))); + static_assert(noexcept(oe(p1, w1))); + static_assert(noexcept(oe(w1, p1))); + static_assert(noexcept(oe(w1, w1))); + + assert(oe(p1, w1)); + assert(oe(w1, p1)); + assert(oe(w1, w1)); + + assert(!oe(p1, p3)); + assert(!oe(p1, w3)); + assert(!oe(w1, p3)); + assert(!oe(w1, w3)); + + using member_is_transparent [[maybe_unused]] = std::owner_equal::is_transparent; + LIBCPP_STATIC_ASSERT(std::same_as); + + { + std::unordered_set, std::owner_hash, std::owner_equal> s; + s.insert(w1); + assert(s.count(w1) == 1); + assert(s.count(std::weak_ptr(p2)) == 1); + assert(s.count(w3) == 0); + } + + return 0; +} diff --git a/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.weak/util.smartptr.ownerhash/owner_hash.pass.cpp b/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.weak/util.smartptr.ownerhash/owner_hash.pass.cpp new file mode 100644 index 000000000000..fa0931abe3a3 --- /dev/null +++ b/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.weak/util.smartptr.ownerhash/owner_hash.pass.cpp @@ -0,0 +1,51 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: std-at-least-c++26 + +// + +// struct owner_hash +// { +// template +// size_t operator()(shared_ptr const&) const noexcept; +// template +// size_t operator()(weak_ptr const&) const noexcept; +// +// using is_transparent = unspecified; +// }; + +#include +#include +#include +#include + +#include "test_macros.h" + +int main(int, char**) { + const std::shared_ptr p1(new int); + const std::shared_ptr p2 = p1; + const std::weak_ptr w1(p1); + + std::owner_hash oh; + + std::same_as decltype(auto) hash_p1 = oh(p1); + std::same_as decltype(auto) hash_w1 = oh(w1); + static_assert(noexcept(oh(p1))); + static_assert(noexcept(oh(w1))); + + assert(hash_p1 == p1.owner_hash()); + assert(hash_w1 == w1.owner_hash()); + assert(hash_p1 == oh(p2)); + assert(hash_p1 == hash_w1); + + using member_is_transparent [[maybe_unused]] = std::owner_hash::is_transparent; + LIBCPP_STATIC_ASSERT(std::same_as); + + return 0; +} diff --git a/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.weak/util.smartptr.weak.obs/owner_equal_shared_ptr.pass.cpp b/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.weak/util.smartptr.weak.obs/owner_equal_shared_ptr.pass.cpp new file mode 100644 index 000000000000..f71131f7369e --- /dev/null +++ b/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.weak/util.smartptr.weak.obs/owner_equal_shared_ptr.pass.cpp @@ -0,0 +1,39 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: std-at-least-c++26 + +// + +// weak_ptr + +// template bool owner_equal(shared_ptr const& b) const noexcept; + +#include +#include +#include + +#include "test_macros.h" + +int main(int, char**) { + const std::shared_ptr p1(new int); + const std::shared_ptr p3(new int); + const std::weak_ptr w1(p1); + const std::weak_ptr empty; + + std::same_as decltype(auto) result = w1.owner_equal(p1); + assert(result); + static_assert(noexcept(w1.owner_equal(p1))); + + assert(!w1.owner_equal(p3)); + + const std::shared_ptr empty_sp; + assert(empty.owner_equal(empty_sp)); + + return 0; +} diff --git a/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.weak/util.smartptr.weak.obs/owner_equal_weak_ptr.pass.cpp b/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.weak/util.smartptr.weak.obs/owner_equal_weak_ptr.pass.cpp new file mode 100644 index 000000000000..d0e8b6e65767 --- /dev/null +++ b/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.weak/util.smartptr.weak.obs/owner_equal_weak_ptr.pass.cpp @@ -0,0 +1,44 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: std-at-least-c++26 + +// + +// weak_ptr + +// template bool owner_equal(weak_ptr const& b) const noexcept; + +#include +#include +#include + +#include "test_macros.h" + +int main(int, char**) { + const std::shared_ptr p1(new int); + const std::shared_ptr p3(new int); + const std::weak_ptr w1(p1); + const std::weak_ptr w2(p1); + const std::weak_ptr w3(p3); + const std::weak_ptr empty1; + const std::weak_ptr empty2; + + std::same_as decltype(auto) result = w1.owner_equal(w2); + assert(result); + static_assert(noexcept(w1.owner_equal(w2))); + + assert(w2.owner_equal(w1)); + assert(!w1.owner_equal(w3)); + assert(!w3.owner_equal(w1)); + + assert(empty1.owner_equal(empty2)); + assert(!w1.owner_equal(empty1)); + + return 0; +} diff --git a/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.weak/util.smartptr.weak.obs/owner_hash.pass.cpp b/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.weak/util.smartptr.weak.obs/owner_hash.pass.cpp new file mode 100644 index 000000000000..aac6fec718d5 --- /dev/null +++ b/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.weak/util.smartptr.weak.obs/owner_hash.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 +// +//===----------------------------------------------------------------------===// + +// REQUIRES: std-at-least-c++26 + +// + +// weak_ptr + +// size_t owner_hash() const noexcept; + +#include +#include +#include +#include + +#include "test_macros.h" + +int main(int, char**) { + const std::shared_ptr p1(new int); + const std::weak_ptr w1(p1); + const std::weak_ptr w2(p1); + + std::same_as decltype(auto) hash1 = w1.owner_hash(); + static_assert(noexcept(w1.owner_hash())); + + assert(hash1 == w2.owner_hash()); + assert(hash1 == p1.owner_hash()); + + return 0; +} diff --git a/libcxx/utils/generate_feature_test_macro_components.py b/libcxx/utils/generate_feature_test_macro_components.py index 145be8c4f33c..09126c14478b 100644 --- a/libcxx/utils/generate_feature_test_macro_components.py +++ b/libcxx/utils/generate_feature_test_macro_components.py @@ -1314,7 +1314,6 @@ feature_test_macros = [ "c++26": 202306 # P1901R2 Enabling the Use of weak_ptr as Keys in Unordered Associative Containers }, "headers": ["memory"], - "unimplemented": True, }, { "name": "__cpp_lib_source_location",