Fix shared_ptr_compatible

A shared_ptr<void> is not anonymous, it's just a wrapped void*.
This commit is contained in:
Steven Dee (Jōshin) 2024-08-29 09:01:51 -07:00
parent 709cc85d96
commit 47e4f60cf1
No known key found for this signature in database
2 changed files with 18 additions and 13 deletions

View file

@ -154,8 +154,8 @@ class shared_emplace : public shared_ref
} }
}; };
template<typename T, typename U> template <typename T, typename U>
concept shared_ptr_convertible = is_convertible_v<U, T> || is_void_v<T>; concept shared_ptr_compatible = is_convertible_v<U*, T*>;
} // namespace __ } // namespace __
@ -175,15 +175,15 @@ class shared_ptr
} }
template<typename U> template<typename U>
requires is_convertible_v<U, T> requires __::shared_ptr_compatible<T, U>
explicit shared_ptr(U* const p) : shared_ptr(p, default_delete<U>()) explicit shared_ptr(U* const p) : shared_ptr(p, default_delete<U>())
{ {
} }
template<typename U, typename D> template<typename U, typename D>
requires is_convertible_v<U, T> requires __::shared_ptr_compatible<T, U>
shared_ptr(U* const p, D d) shared_ptr(U* const p, D d)
: p(p), rc(__::shared_pointer<T, D>::make(p, move(d))) : p(p), rc(__::shared_pointer<U, D>::make(p, move(d)))
{ {
} }
@ -203,7 +203,7 @@ class shared_ptr
} }
template<typename U> template<typename U>
requires __::shared_ptr_convertible<T, U> requires __::shared_ptr_compatible<T, U>
shared_ptr(const shared_ptr<U>& r) noexcept : p(r.p), rc(r.rc) shared_ptr(const shared_ptr<U>& r) noexcept : p(r.p), rc(r.rc)
{ {
if (rc) if (rc)
@ -211,7 +211,7 @@ class shared_ptr
} }
template<typename U> template<typename U>
requires __::shared_ptr_convertible<T, U> requires __::shared_ptr_compatible<T, U>
shared_ptr(shared_ptr<U>&& r) noexcept : p(r.p), rc(r.rc) shared_ptr(shared_ptr<U>&& r) noexcept : p(r.p), rc(r.rc)
{ {
r.p = nullptr; r.p = nullptr;
@ -231,7 +231,7 @@ class shared_ptr
} }
template<typename U> template<typename U>
requires is_convertible_v<U, T> requires __::shared_ptr_compatible<T, U>
explicit shared_ptr(const weak_ptr<U>& r) : p(r.p), rc(r.rc) explicit shared_ptr(const weak_ptr<U>& r) : p(r.p), rc(r.rc)
{ {
if (r.expired()) { if (r.expired()) {
@ -241,7 +241,7 @@ class shared_ptr
} }
template<typename U, typename D> template<typename U, typename D>
requires is_convertible_v<U, T> requires __::shared_ptr_compatible<T, U>
shared_ptr(unique_ptr<U, D>&& r) shared_ptr(unique_ptr<U, D>&& r)
: p(r.p), rc(__::shared_pointer<U, D>::make(move(r))) : p(r.p), rc(__::shared_pointer<U, D>::make(move(r)))
{ {
@ -260,7 +260,7 @@ class shared_ptr
} }
template<typename U> template<typename U>
requires __::shared_ptr_convertible<T, U> requires __::shared_ptr_compatible<T, U>
shared_ptr& operator=(shared_ptr<U> r) noexcept shared_ptr& operator=(shared_ptr<U> r) noexcept
{ {
shared_ptr<T>(move(r)).swap(*this); shared_ptr<T>(move(r)).swap(*this);
@ -277,14 +277,14 @@ class shared_ptr
} }
template<typename U> template<typename U>
requires is_convertible_v<U, T> requires __::shared_ptr_compatible<T, U>
void reset(U* const p2) void reset(U* const p2)
{ {
shared_ptr<T>(p2).swap(*this); shared_ptr<T>(p2).swap(*this);
} }
template<typename U, typename D> template<typename U, typename D>
requires is_convertible_v<U, T> requires __::shared_ptr_compatible<T, U>
void reset(U* const p2, D d) void reset(U* const p2, D d)
{ {
shared_ptr<T>(p2, d).swap(*this); shared_ptr<T>(p2, d).swap(*this);
@ -362,7 +362,7 @@ class weak_ptr
constexpr weak_ptr() noexcept = default; constexpr weak_ptr() noexcept = default;
template<typename U> template<typename U>
requires is_convertible_v<U, T> requires __::shared_ptr_compatible<T, U>
weak_ptr(const shared_ptr<U>& r) noexcept : p(r.p), rc(r.rc) weak_ptr(const shared_ptr<U>& r) noexcept : p(r.p), rc(r.rc)
{ {
if (rc) if (rc)

View file

@ -140,6 +140,11 @@ main()
shared_ptr<void> y(x); shared_ptr<void> y(x);
} }
{
// You can also create a shared pointer to void in the first place.
shared_ptr<void> x(new int);
}
{ {
// You can take a shared pointer to a subobject, and it will free the // You can take a shared pointer to a subobject, and it will free the
// base object. // base object.