[libcxx-commits] [libcxx] [libc++] Implement P1901R2: owner_hash and owner_equal for shared_ptr/weak_ptr (PR #210551)

via libcxx-commits libcxx-commits at lists.llvm.org
Sat Jul 18 14:44:43 PDT 2026


llvmorg-github-actions[bot] wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-libcxx

Author: Avi Patel (firedog1234)

<details>
<summary>Changes</summary>

## Summary

Implements P1901R2 (C++26), adding ownership-based hashing and equality support for `std::shared_ptr` and `std::weak_ptr`.

This change:
- Implements `shared_ptr::owner_hash()` / `weak_ptr::owner_hash()`
- Implements `shared_ptr::owner_equal()` / `weak_ptr::owner_equal()`
- Adds the free function objects `std::owner_hash` and `std::owner_equal`
- Enables `std::weak_ptr` to be used as keys in unordered associative containers

Fixes #<!-- -->105372.

## Test Plan

- Added libc++ tests for:
  - `util.smartptr.shared.obs/`
  - `util.smartptr.weak.obs/`
  - `util.smartptr.ownerhash/`
  - `util.smartptr.ownerequal/`

## Acknowledgements

Claude assisted with test development and documentation.

---

Patch is 27.09 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/210551.diff


17 Files Affected:

- (modified) libcxx/docs/FeatureTestMacroTable.rst (+1-1) 
- (modified) libcxx/docs/ReleaseNotes/23.rst (+1) 
- (modified) libcxx/docs/Status/Cxx26Papers.csv (+1-1) 
- (modified) libcxx/include/__memory/shared_ptr.h (+71) 
- (modified) libcxx/include/memory (+32) 
- (modified) libcxx/include/version (+1-1) 
- (modified) libcxx/test/std/language.support/support.limits/support.limits.general/memory.version.compile.pass.cpp (+5-11) 
- (modified) libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp (+5-11) 
- (added) libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.obs/owner_equal_shared_ptr.pass.cpp (+40) 
- (added) libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.obs/owner_equal_weak_ptr.pass.cpp (+41) 
- (added) libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.obs/owner_hash.pass.cpp (+44) 
- (added) libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.weak/util.smartptr.ownerequal/owner_equal.pass.cpp (+69) 
- (added) libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.weak/util.smartptr.ownerhash/owner_hash.pass.cpp (+49) 
- (added) libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.weak/util.smartptr.weak.obs/owner_equal_shared_ptr.pass.cpp (+37) 
- (added) libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.weak/util.smartptr.weak.obs/owner_equal_weak_ptr.pass.cpp (+42) 
- (added) libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.weak/util.smartptr.weak.obs/owner_hash.pass.cpp (+34) 
- (modified) libcxx/utils/generate_feature_test_macro_components.py (-1) 


``````````diff
diff --git a/libcxx/docs/FeatureTestMacroTable.rst b/libcxx/docs/FeatureTestMacroTable.rst
index 6bf2f35fb4212..8a26828240de4 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/23.rst b/libcxx/docs/ReleaseNotes/23.rst
index 1213e8f43c8cd..1dee9843c9c55 100644
--- a/libcxx/docs/ReleaseNotes/23.rst
+++ b/libcxx/docs/ReleaseNotes/23.rst
@@ -55,6 +55,7 @@ Implemented Papers
 - P3369R0: constexpr for ``uninitialized_default_construct`` (`Github <https://llvm.org/PR118380>`__)
 - P3508R0: Wording for "constexpr for specialized memory algorithms" (`Github <https://llvm.org/PR118379>`__)
 - P4206R0: Revert string support in ``std::constant_wrapper`` (`Github <https://llvm.org/PR203338>`__)
+- P1901R2: Enabling the Use of ``weak_ptr`` as Keys in Unordered Associative Containers (`Github <https://llvm.org/PR105372>`__)
 
 Improvements and New Features
 -----------------------------
diff --git a/libcxx/docs/Status/Cxx26Papers.csv b/libcxx/docs/Status/Cxx26Papers.csv
index efc98495d1d5c..98135f198110c 100644
--- a/libcxx/docs/Status/Cxx26Papers.csv
+++ b/libcxx/docs/Status/Cxx26Papers.csv
@@ -12,7 +12,7 @@
 "`P2338R4 <https://wg21.link/P2338R4>`__","Freestanding Library: Character primitives and the C library","2023-06 (Varna)","","","`#105369 <https://github.com/llvm/llvm-project/issues/105369>`__",""
 "`P2013R5 <https://wg21.link/P2013R5>`__","Freestanding Language: Optional ``::operator new``","2023-06 (Varna)","","","`#105370 <https://github.com/llvm/llvm-project/issues/105370>`__",""
 "`P2363R5 <https://wg21.link/P2363R5>`__","Extending associative containers with the remaining heterogeneous overloads","2023-06 (Varna)","","","`#105371 <https://github.com/llvm/llvm-project/issues/105371>`__",""
-"`P1901R2 <https://wg21.link/P1901R2>`__","Enabling the Use of ``weak_ptr`` as Keys in Unordered Associative Containers","2023-06 (Varna)","","","`#105372 <https://github.com/llvm/llvm-project/issues/105372>`__",""
+"`P1901R2 <https://wg21.link/P1901R2>`__","Enabling the Use of ``weak_ptr`` as Keys in Unordered Associative Containers","2023-06 (Varna)","|Complete|","23","`#105372 <https://github.com/llvm/llvm-project/issues/105372>`__",""
 "`P1885R12 <https://wg21.link/P1885R12>`__","Naming Text Encodings to Demystify Them","2023-06 (Varna)","|Complete|","23","`#105373 <https://github.com/llvm/llvm-project/issues/105373>`__",""
 "`P0792R14 <https://wg21.link/P0792R14>`__","``function_ref``: a type-erased callable reference","2023-06 (Varna)","","","`#105376 <https://github.com/llvm/llvm-project/issues/105376>`__",""
 "`P2874R2 <https://wg21.link/P2874R2>`__","P2874R2: Mandating Annex D Require No More","2023-06 (Varna)","|Complete|","12","`#105377 <https://github.com/llvm/llvm-project/issues/105377>`__",""
diff --git a/libcxx/include/__memory/shared_ptr.h b/libcxx/include/__memory/shared_ptr.h
index ebd542ba14d01..0770f2a8e383d 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 @@ class _LIBCPP_SHARED_PTR_TRIVIAL_ABI shared_ptr {
 
   _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 <class _Up>
+  [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI bool owner_equal(shared_ptr<_Up> const& __p) const _NOEXCEPT {
+    return __cntrl_ == __p.__cntrl_;
+  }
+
+  template <class _Up>
+  [[__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<element_type> operator[](ptrdiff_t __i) const {
     static_assert(is_array<_Tp>::value, "std::shared_ptr<T>::operator[] is only valid when T is an array type.");
@@ -1244,6 +1261,22 @@ class _LIBCPP_SHARED_PTR_TRIVIAL_ABI weak_ptr {
     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 <class _Up>
+  [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI bool owner_equal(shared_ptr<_Up> const& __p) const _NOEXCEPT {
+    return __cntrl_ == __p.__cntrl_;
+  }
+
+  template <class _Up>
+  [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI bool owner_equal(weak_ptr<_Up> const& __p) const _NOEXCEPT {
+    return __cntrl_ == __p.__cntrl_;
+  }
+#endif
+
   template <class _Up>
   friend class weak_ptr;
   template <class _Up>
@@ -1317,6 +1350,44 @@ struct owner_less<void> {
 };
 #endif
 
+#if _LIBCPP_STD_VER >= 26
+struct owner_hash {
+  template <class _Tp>
+  [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI size_t operator()(shared_ptr<_Tp> const& __p) const _NOEXCEPT {
+    return __p.owner_hash();
+  }
+  template <class _Tp>
+  [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI size_t operator()(weak_ptr<_Tp> const& __p) const _NOEXCEPT {
+    return __p.owner_hash();
+  }
+  typedef void is_transparent;
+};
+
+struct owner_equal {
+  template <class _Tp, class _Up>
+  [[__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 <class _Tp, class _Up>
+  [[__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 <class _Tp, class _Up>
+  [[__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 <class _Tp, class _Up>
+  [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI bool
+  operator()(weak_ptr<_Tp> const& __x, weak_ptr<_Up> const& __y) const _NOEXCEPT {
+    return __x.owner_equal(__y);
+  }
+  typedef void is_transparent;
+};
+#endif
+
 template <class _Tp>
 class enable_shared_from_this {
   mutable weak_ptr<_Tp> __weak_this_;
diff --git a/libcxx/include/memory b/libcxx/include/memory
index d5d48ed9a9e6d..03636ddb839b0 100644
--- a/libcxx/include/memory
+++ b/libcxx/include/memory
@@ -633,6 +633,9 @@ public:
     explicit operator bool() const noexcept;
     template<class U> bool owner_before(shared_ptr<U> const& b) const noexcept;
     template<class U> bool owner_before(weak_ptr<U> const& b) const noexcept;
+    size_t owner_hash() const noexcept;                                       // C++26
+    template<class U> bool owner_equal(shared_ptr<U> const& b) const noexcept; // C++26
+    template<class U> bool owner_equal(weak_ptr<U> const& b) const noexcept;   // C++26
 };
 
 template<class T>
@@ -771,6 +774,9 @@ public:
     shared_ptr<T> lock() const noexcept;
     template<class U> bool owner_before(shared_ptr<U> const& b) const noexcept;
     template<class U> bool owner_before(weak_ptr<U> const& b) const noexcept;
+    size_t owner_hash() const noexcept;                                       // C++26
+    template<class U> bool owner_equal(shared_ptr<U> const& b) const noexcept; // C++26
+    template<class U> bool owner_equal(weak_ptr<U> const& b) const noexcept;   // C++26
 };
 
 template<class T>
@@ -817,6 +823,32 @@ struct owner_less<void>
     typedef void is_transparent;
 };
 
+// class owner_hash:                                                          // C++26
+struct owner_hash
+{
+    template <class _Tp>
+    size_t operator()(shared_ptr<_Tp> const& __p) const noexcept;
+    template <class _Tp>
+    size_t operator()(weak_ptr<_Tp> const& __p) const noexcept;
+
+    typedef void is_transparent;
+};
+
+// class owner_equal:                                                         // C++26
+struct owner_equal
+{
+    template <class _Tp, class _Up>
+    bool operator()(shared_ptr<_Tp> const& __x, shared_ptr<_Up> const& __y) const noexcept;
+    template <class _Tp, class _Up>
+    bool operator()(shared_ptr<_Tp> const& __x,   weak_ptr<_Up> const& __y) const noexcept;
+    template <class _Tp, class _Up>
+    bool operator()(  weak_ptr<_Tp> const& __x, shared_ptr<_Up> const& __y) const noexcept;
+    template <class _Tp, class _Up>
+    bool operator()(  weak_ptr<_Tp> const& __x,   weak_ptr<_Up> const& __y) const noexcept;
+
+    typedef void is_transparent;
+};
+
 template<class T>
 class enable_shared_from_this
 {
diff --git a/libcxx/include/version b/libcxx/include/version
index 4a6b01093641d..31b5cc4048e18 100644
--- a/libcxx/include/version
+++ b/libcxx/include/version
@@ -628,7 +628,7 @@ __cpp_lib_void_t                                        201411L <type_traits>
 # 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/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 c58357a463ffd..dc14ff766ac5c 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 f2d74cc99d864..11b181a66c518 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
@@ -8024,17 +8024,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 0000000000000..0f8c6935ef811
--- /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,40 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20, c++23
+
+// <memory>
+
+// shared_ptr
+
+// template<class U> bool owner_equal(shared_ptr<U> const& b) const noexcept;
+
+#include <memory>
+#include <cassert>
+#include "test_macros.h"
+
+int main(int, char**) {
+  const std::shared_ptr<int> p1(new int);
+  const std::shared_ptr<int> p2 = p1;
+  const std::shared_ptr<int> p3(new int);
+  const std::shared_ptr<void> empty1;
+  const std::shared_ptr<long> empty2;
+
+  assert(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));
+
+  ASSERT_SAME_TYPE(decltype(p1.owner_equal(p2)), bool);
+  ASSERT_NOEXCEPT(p1.owner_equal(p2));
+
+  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 0000000000000..6ac9f57e07a05
--- /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,41 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20, c++23
+
+// <memory>
+
+// shared_ptr
+
+// template<class U> bool owner_equal(weak_ptr<U> const& b) const noexcept;
+
+#include <memory>
+#include <cassert>
+#include "test_macros.h"
+
+int main(int, char**) {
+  const std::shared_ptr<int> p1(new int);
+  const std::shared_ptr<int> p2 = p1;
+  const std::shared_ptr<int> p3(new int);
+  const std::weak_ptr<int> w1(p1);
+  const std::weak_ptr<int> w3(p3);
+  const std::shared_ptr<void> empty_sp;
+  const std::weak_ptr<long> empty_wp;
+
+  assert(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));
+
+  ASSERT_SAME_TYPE(decltype(p1.owner_equal(w1)), bool);
+  ASSERT_NOEXCEPT(p1.owner_equal(w1));
+
+  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 0000000000000..57967b9369fe3
--- /dev/null
+++ b/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.obs/owner_hash.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
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20, c++23
+
+// <memory>
+
+// shared_ptr
+
+// size_t owner_hash() const noexcept;
+
+#include <memory>
+#include <cassert>
+#include <cstddef>
+#include "test_macros.h"
+
+struct Pair {
+  int a;
+  int b;
+};
+
+int main(int, char**) {
+  const std::shared_ptr<int> p1(new int);
+  const std::shared_ptr<int> p2 = p1;
+  const std::weak_ptr<int> w1(p1);
+
+  assert(p1.owner_hash() == p2.owner_hash());
+  assert(p1.owner_hash() == w1.owner_hash());
+
+  const std::shared_ptr<Pair> sp(new Pair{1, 2});
+  const std::shared_ptr<int> alias(sp, &sp->b);
+  assert(static_cast<void*>(sp.get()) != static_cast<void*>(alias.get()));
+  assert(sp.owner_hash() == alias.owner_hash());
+
+  ASSERT_SAME_TYPE(decltype(p1.owner_hash()), std::size_t);
+  ASSERT_NOEXCEPT(p1.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 0000000000000..1c6c9e8bd5d67
--- /dev/null
+++ b/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.weak/util.smartptr.ownerequal/owner_equal.pass.cpp
@@ -0,0 +1,69 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20, c++23
+
+// <memory>
+
+// struct owner_equal
+// {
+//     template<class T, class U>
+//         bool operator()(shared_ptr<T> const&, shared_ptr<U> const&) const noexcept;
+//     template<class T, class U>
+//         bool operator()(shared_ptr<T> const&, weak_ptr<U> const&) const noexcept;
+//     template<class T, class U>
+//         bool operator()(weak_ptr<T> const&, shared_ptr<U> const&) const noexcept;
+//     template<class T, class U>
+//         bool operator()(weak_ptr<T> const&, weak_ptr<U> const&) const noexcept;
+//
+//     typedef unspecified is_transparent;
+// };
+
+#include <memory>
+#include <cassert>
+#include <type_traits>
+#include <unordered_set>
+#include "test_macros.h"
+
+int main(int, char**) {
+  const std::shared_ptr<int> p1(new int);
+  const std::shared_ptr<int> p2 = p1;
+  const std::shared_ptr<int> p3(new int);
+  const std::weak_ptr<int> w1(p1);
+  const std::weak_ptr<int> w3(p3);
+
+  std::owner_equal oe;
+
+  assert(oe(p1, p2));
+  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));
+
+  ASSERT_SAME_TYPE(decltype(oe(p1, p2)), bool);
+  ASSERT_NOEXCEPT(oe(p1, p2));
+  ASSERT_NOEXCEPT(oe(p1, w1));
+  ASSERT_NOEXCEPT(oe(w1, p1));
+  ASSERT_NOEXCEPT(oe(w1, w1));
+
+  static_assert(std::is_same<std::owner_equal::is_transparent, void>::value, "");
+
+  {
+    std::unordered_set<std::weak_p...
[truncated]

``````````

</details>


https://github.com/llvm/llvm-project/pull/210551


More information about the libcxx-commits mailing list