[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:
parent
cf08d4bc70
commit
1b3d208c77
19 changed files with 530 additions and 26 deletions
|
|
@ -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``
|
||||
---------------------------------------------------------- -----------------
|
||||
|
|
|
|||
|
|
@ -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
|
||||
-----------------------------
|
||||
|
|
|
|||
|
|
@ -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>`__",""
|
||||
|
|
|
|||
|
|
|
@ -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_;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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",
|
||||
|
|
|
|||
Loading…
Reference in a new issue