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

Fixes #105372.

## Acknowledgements

Claude assisted with test development.
This commit is contained in:
Avi Patel 2026-07-27 06:00:45 -04:00 committed by GitHub
parent cf08d4bc70
commit 1b3d208c77
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
19 changed files with 530 additions and 26 deletions

View file

@ -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``
---------------------------------------------------------- -----------------

View file

@ -42,6 +42,7 @@ Implemented Papers
- P0792R14: ``function_ref`` : a type-erased callable reference (`Github <https://llvm.org/PR105376>`__)
- P3948R1: ``constant_wrapper`` is the only tool needed for passing constant expressions via function arguments (`Github <https://llvm.org/PR189604>`__)
- P3961R1: Less double indirection in ``function_ref`` (RU-220) (`Github <https://llvm.org/PR189606>`__)
- P1901R2: Enabling the Use of ``weak_ptr`` as Keys in Unordered Associative Containers (`Github <https://llvm.org/PR105372>`__)
Improvements and New Features
-----------------------------

View file

@ -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|","24","`#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)","|Complete|","24","`#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>`__",""

1 Paper # Paper Name Meeting Status First released version GitHub issue Notes
12 `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>`__
13 `P2013R5 <https://wg21.link/P2013R5>`__ Freestanding Language: Optional ``::operator new`` 2023-06 (Varna) `#105370 <https://github.com/llvm/llvm-project/issues/105370>`__
14 `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>`__
15 `P1901R2 <https://wg21.link/P1901R2>`__ Enabling the Use of ``weak_ptr`` as Keys in Unordered Associative Containers 2023-06 (Varna) |Complete| 24 `#105372 <https://github.com/llvm/llvm-project/issues/105372>`__
16 `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>`__
17 `P0792R14 <https://wg21.link/P0792R14>`__ ``function_ref``: a type-erased callable reference 2023-06 (Varna) |Complete| 24 `#105376 <https://github.com/llvm/llvm-project/issues/105376>`__
18 `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>`__

View file

@ -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 <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.");
@ -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 <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>
@ -1318,6 +1351,46 @@ 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();
}
using is_transparent = void;
};
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);
}
using is_transparent = void;
};
#endif
template <class _Tp>
class enable_shared_from_this {
mutable weak_ptr<_Tp> __weak_this_;

View file

@ -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,31 @@ struct owner_less<void>
typedef void is_transparent;
};
// struct owner_hash
struct owner_hash { // C++26
template<class T>
size_t operator()(const shared_ptr<T>&) const noexcept;
template<class T>
size_t operator()(const weak_ptr<T>&) const noexcept;
using is_transparent = unspecified;
};
// struct owner_equal
struct owner_equal { // C++26
template<class T, class U>
bool operator()(const shared_ptr<T>&, const shared_ptr<U>&) const noexcept;
template<class T, class U>
bool operator()(const shared_ptr<T>&, const weak_ptr<U>&) const noexcept;
template<class T, class U>
bool operator()(const weak_ptr<T>&, const shared_ptr<U>&) const noexcept;
template<class T, class U>
bool operator()(const weak_ptr<T>&, const weak_ptr<U>&) const noexcept;
using is_transparent = unspecified;
};
template<class T>
class enable_shared_from_this
{

View file

@ -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

View file

@ -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;

View file

@ -59,6 +59,14 @@ void test() {
sPtr.owner_before(std::shared_ptr<int>());
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
sPtr.owner_before(std::weak_ptr<int>());
#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<int>());
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
sPtr.owner_equal(std::weak_ptr<int>());
#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<int>());
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
wPtr.owner_before(std::shared_ptr<int>());
#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<int>());
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
wPtr.owner_equal(std::shared_ptr<int>());
#endif
}
#if TEST_STD_VER >= 26
{ // [util.smartptr.owner.hash], [util.smartptr.owner.equal]
std::shared_ptr<int> sPtr;
std::weak_ptr<int> 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> {};
EnableShared es;

View file

@ -648,18 +648,12 @@
# 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
# endif
# ifndef __cpp_lib_to_address
# error "__cpp_lib_to_address should be defined in c++26"

View file

@ -8012,18 +8012,12 @@
# 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
# endif
# ifndef __cpp_lib_source_location
# error "__cpp_lib_source_location should be defined in c++26"

View file

@ -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
// <memory>
// shared_ptr
// template<class U> bool owner_equal(shared_ptr<U> const& b) const noexcept;
#include <cassert>
#include <concepts>
#include <memory>
#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;
std::same_as<bool> 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;
}

View file

@ -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
// <memory>
// shared_ptr
// template<class U> bool owner_equal(weak_ptr<U> const& b) const noexcept;
#include <cassert>
#include <concepts>
#include <memory>
#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;
std::same_as<bool> 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;
}

View file

@ -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
// <memory>
// shared_ptr
// size_t owner_hash() const noexcept;
#include <cassert>
#include <concepts>
#include <cstddef>
#include <memory>
#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);
std::same_as<std::size_t> 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<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());
return 0;
}

View file

@ -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
// <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;
//
// using is_transparent = unspecified;
// };
#include <cassert>
#include <concepts>
#include <memory>
#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;
std::same_as<bool> 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<member_is_transparent, void>);
{
std::unordered_set<std::weak_ptr<int>, std::owner_hash, std::owner_equal> s;
s.insert(w1);
assert(s.count(w1) == 1);
assert(s.count(std::weak_ptr<int>(p2)) == 1);
assert(s.count(w3) == 0);
}
return 0;
}

View file

@ -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
// <memory>
// struct owner_hash
// {
// template<class T>
// size_t operator()(shared_ptr<T> const&) const noexcept;
// template<class T>
// size_t operator()(weak_ptr<T> const&) const noexcept;
//
// using is_transparent = unspecified;
// };
#include <cassert>
#include <concepts>
#include <cstddef>
#include <memory>
#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::weak_ptr<int> w1(p1);
std::owner_hash oh;
std::same_as<std::size_t> decltype(auto) hash_p1 = oh(p1);
std::same_as<std::size_t> 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<member_is_transparent, void>);
return 0;
}

View file

@ -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
// <memory>
// weak_ptr
// template<class U> bool owner_equal(shared_ptr<U> const& b) const noexcept;
#include <cassert>
#include <concepts>
#include <memory>
#include "test_macros.h"
int main(int, char**) {
const std::shared_ptr<int> p1(new int);
const std::shared_ptr<int> p3(new int);
const std::weak_ptr<int> w1(p1);
const std::weak_ptr<void> empty;
std::same_as<bool> 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<long> empty_sp;
assert(empty.owner_equal(empty_sp));
return 0;
}

View file

@ -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
// <memory>
// weak_ptr
// template<class U> bool owner_equal(weak_ptr<U> const& b) const noexcept;
#include <cassert>
#include <concepts>
#include <memory>
#include "test_macros.h"
int main(int, char**) {
const std::shared_ptr<int> p1(new int);
const std::shared_ptr<int> p3(new int);
const std::weak_ptr<int> w1(p1);
const std::weak_ptr<int> w2(p1);
const std::weak_ptr<int> w3(p3);
const std::weak_ptr<void> empty1;
const std::weak_ptr<long> empty2;
std::same_as<bool> 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;
}

View file

@ -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
// <memory>
// weak_ptr
// size_t owner_hash() const noexcept;
#include <cassert>
#include <concepts>
#include <cstddef>
#include <memory>
#include "test_macros.h"
int main(int, char**) {
const std::shared_ptr<int> p1(new int);
const std::weak_ptr<int> w1(p1);
const std::weak_ptr<int> w2(p1);
std::same_as<std::size_t> decltype(auto) hash1 = w1.owner_hash();
static_assert(noexcept(w1.owner_hash()));
assert(hash1 == w2.owner_hash());
assert(hash1 == p1.owner_hash());
return 0;
}

View file

@ -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",