From 25057f99ac871684695175738f9ac31890bb4bba Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Sun, 14 Jul 2024 17:01:46 +0200 Subject: w --- compat/borrowed-ptr-cast.hpp | 38 ------------------- compat/borrowed-ptr-fwd.hpp | 17 +++++++-- compat/borrowed-ptr.hpp | 31 +++++++++++---- compat/borrowed-ptr.inl | 90 ++++++++++++++++++++++++++++++-------------- test/bptr.cpp | 15 +++++++- 5 files changed, 112 insertions(+), 79 deletions(-) delete mode 100644 compat/borrowed-ptr-cast.hpp diff --git a/compat/borrowed-ptr-cast.hpp b/compat/borrowed-ptr-cast.hpp deleted file mode 100644 index 18f0a50e..00000000 --- a/compat/borrowed-ptr-cast.hpp +++ /dev/null @@ -1,38 +0,0 @@ -#pragma once -#include "borrowed-ptr-fwd.hpp" -#include "compat/assert.hpp" - -namespace floormat::detail_borrowed_ptr { - -//static_assert(std::is_same_v || std::has_virtual_destructor_v && std::has_virtual_destructor_v); // todo! for simple_bptr - -template -concept StaticCastable = requires(From* from) { - static_cast(from); -}; - -} // namespace floormat::detail_borrowed_ptr - -namespace floormat { - -template -bptr static_pointer_cast(const bptr& p) noexcept -{ - // hack to generate better error message - if constexpr (detail_borrowed_ptr::StaticCastable) - { - if (p.blk && p.blk->_ptr) [[likely]] - return bptr{p, nullptr}; - } - else - { - using detail_borrowed_ptr::StaticCastable; - // concepts can't be forward-declared so use static_assert - static_assert(StaticCastable, - "cannot static_cast, classes must be related by inheritance"); - } - - return bptr{nullptr}; -} - -} // namespace floormat diff --git a/compat/borrowed-ptr-fwd.hpp b/compat/borrowed-ptr-fwd.hpp index 38927cc6..5f9c09f4 100644 --- a/compat/borrowed-ptr-fwd.hpp +++ b/compat/borrowed-ptr-fwd.hpp @@ -1,10 +1,19 @@ #pragma once + namespace floormat { struct bptr_base; -template class bptr; -template bptr static_pointer_cast(const bptr& p) noexcept; -template bptr(T* ptr) -> bptr; -template bptr(const T* ptr) -> bptr; + +template +requires std::is_convertible_v +class bptr; + +template +requires std::is_convertible_v +bptr(T* ptr) -> bptr; + +template +requires std::is_convertible_v +bptr(const T* ptr) -> bptr; } // namespace floormat diff --git a/compat/borrowed-ptr.hpp b/compat/borrowed-ptr.hpp index 146fc334..2f7f00d2 100644 --- a/compat/borrowed-ptr.hpp +++ b/compat/borrowed-ptr.hpp @@ -4,18 +4,22 @@ namespace floormat::detail_borrowed_ptr { struct control_block; + +template +concept StaticCastable = requires(From* from) { + static_cast(from); +}; + template concept DerivedFrom = requires(From* x) { - requires !std::is_same_v; - requires std::is_nothrow_convertible_v; + !std::is_same_v; + std::is_convertible_v; }; } // namespace floormat::detail_borrowed_ptr namespace floormat { -template class bptr; - struct bptr_base { virtual ~bptr_base() noexcept; @@ -27,6 +31,7 @@ struct bptr_base }; template +requires std::is_convertible_v class bptr final // NOLINT(*-special-member-functions) { detail_borrowed_ptr::control_block* blk; @@ -58,8 +63,6 @@ public: template Y> CORRADE_ALWAYS_INLINE bptr(bptr&&) noexcept; template Y> CORRADE_ALWAYS_INLINE bptr& operator=(bptr&&) noexcept; - operator bptr() const noexcept requires (!std::is_const_v); - void reset() noexcept; void destroy() noexcept; void swap(bptr& other) noexcept; @@ -73,8 +76,20 @@ public: bool operator==(const bptr>& other) const noexcept; bool operator==(const bptr>& other) const noexcept; - template friend class bptr; - template friend bptr static_pointer_cast(const bptr& p) noexcept; + template requires std::is_convertible_v friend class bptr; + + template + requires (std::is_convertible_v && detail_borrowed_ptr::StaticCastable) + friend bptr static_pointer_cast(const bptr& p) noexcept; }; +template +requires (std::is_convertible_v && detail_borrowed_ptr::StaticCastable) +bptr static_pointer_cast(const bptr& p) noexcept +{ + if (p.blk && p.blk->_ptr) [[likely]] + return bptr{p, nullptr}; + return bptr{nullptr}; +} + } // namespace floormat diff --git a/compat/borrowed-ptr.inl b/compat/borrowed-ptr.inl index e7b4bbbd..c4f19de5 100644 --- a/compat/borrowed-ptr.inl +++ b/compat/borrowed-ptr.inl @@ -39,6 +39,7 @@ struct control_block namespace floormat { template +requires std::is_convertible_v template requires std::is_constructible_v, Ts&&...> bptr::bptr(InPlaceInitT, Ts&&... args) noexcept: @@ -46,65 +47,75 @@ bptr{ new std::remove_const_t{ forward(args)... } } { } -template bptr::bptr(std::nullptr_t) noexcept: blk{nullptr} {} -template bptr::bptr() noexcept: bptr{nullptr} {} +template +requires std::is_convertible_v +bptr::bptr(std::nullptr_t) noexcept: blk{nullptr} {} + +template +requires std::is_convertible_v +bptr::bptr() noexcept: bptr{nullptr} {} -template bptr::bptr(T* ptr) noexcept: +template +requires std::is_convertible_v +bptr::bptr(T* ptr) noexcept: blk{ptr ? new detail_borrowed_ptr::control_block{const_cast*>(ptr), 1} : nullptr} {} template +requires std::is_convertible_v bptr::~bptr() noexcept { if (blk) blk->decrement(blk); } -template bptr::bptr(const bptr& other) noexcept: bptr{other, nullptr} {} -template bptr& bptr::operator=(const bptr& other) noexcept { return _copy_assign(other); } +template +requires std::is_convertible_v +bptr::bptr(const bptr& other) noexcept: bptr{other, nullptr} {} + +template +requires std::is_convertible_v +bptr& bptr::operator=(const bptr& other) noexcept { return _copy_assign(other); } template +requires std::is_convertible_v template Y> bptr::bptr(const bptr& other) noexcept: bptr{other, nullptr} {} template +requires std::is_convertible_v template Y> bptr& bptr::operator=(const bptr& other) noexcept { return _copy_assign(other); } -template bptr& bptr::operator=(bptr&& other) noexcept { return _move_assign(move(other)); } -template bptr::bptr(bptr&& other) noexcept: bptr{move(other), nullptr} {} +template +requires std::is_convertible_v +bptr& bptr::operator=(bptr&& other) noexcept { return _move_assign(move(other)); } +template +requires std::is_convertible_v +bptr::bptr(bptr&& other) noexcept: bptr{move(other), nullptr} {} template +requires std::is_convertible_v template Y> bptr::bptr(bptr&& other) noexcept: bptr{move(other), nullptr} {} template +requires std::is_convertible_v template Y> bptr& bptr::operator=(bptr&& other) noexcept { return _move_assign(move(other)); } template -bptr::operator bptr() const noexcept requires (!std::is_const_v) { - if (blk && blk->_ptr) - { - ++blk->_count; - return bptr{}; - } - return bptr{nullptr}; -} - -template +requires std::is_convertible_v void bptr::reset() noexcept { if (blk) - { blk->decrement(blk); - blk = nullptr; - } } template +requires std::is_convertible_v void bptr::destroy() noexcept { if (!blk) @@ -113,9 +124,12 @@ void bptr::destroy() noexcept blk->_ptr = nullptr; } -template bptr& bptr::operator=(std::nullptr_t) noexcept { reset(); return *this; } +template +requires std::is_convertible_v +bptr& bptr::operator=(std::nullptr_t) noexcept { reset(); return *this; } template +requires std::is_convertible_v template bptr::bptr(const bptr& other, std::nullptr_t) noexcept: blk{other.blk} @@ -128,6 +142,7 @@ bptr::bptr(const bptr& other, std::nullptr_t) noexcept: } template +requires std::is_convertible_v template bptr& bptr::_copy_assign(const bptr& other) noexcept { @@ -143,6 +158,7 @@ bptr& bptr::_copy_assign(const bptr& other) noexcept } template +requires std::is_convertible_v template bptr::bptr(bptr&& other, std::nullptr_t) noexcept: blk{other.blk} @@ -151,6 +167,7 @@ bptr::bptr(bptr&& other, std::nullptr_t) noexcept: } template +requires std::is_convertible_v template bptr& bptr::_move_assign(bptr&& other) noexcept { @@ -161,7 +178,9 @@ bptr& bptr::_move_assign(bptr&& other) noexcept return *this; } -template T* bptr::get() const noexcept +template +requires std::is_convertible_v +T* bptr::get() const noexcept { if (blk) [[likely]] return static_cast(blk->_ptr); @@ -169,26 +188,41 @@ template T* bptr::get() const noexcept return nullptr; } -template T* bptr::operator->() const noexcept +template +requires std::is_convertible_v +T* bptr::operator->() const noexcept { auto* ret = get(); fm_bptr_assert(ret); return ret; } -template T& bptr::operator*() const noexcept { return *operator->(); } +template +requires std::is_convertible_v +T& bptr::operator*() const noexcept { return *operator->(); } -template bptr::operator bool() const noexcept { return get(); } -template bool bptr::operator==(const bptr>& other) const noexcept { return get() == other.get(); } -template bool bptr::operator==(const bptr>& other) const noexcept { return get() == other.get(); } +template +requires std::is_convertible_v +bptr::operator bool() const noexcept { return get(); } + +template +requires std::is_convertible_v +bool bptr::operator==(const bptr>& other) const noexcept { return get() == other.get(); } template +requires std::is_convertible_v +bool bptr::operator==(const bptr>& other) const noexcept { return get() == other.get(); } + +template +requires std::is_convertible_v void bptr::swap(bptr& other) noexcept { floormat::swap(blk, other.blk); } -template uint32_t bptr::use_count() const noexcept +template +requires std::is_convertible_v +uint32_t bptr::use_count() const noexcept { if (blk && blk->_ptr) [[likely]] return blk->_count; diff --git a/test/bptr.cpp b/test/bptr.cpp index ffff5b19..e9d0dff3 100644 --- a/test/bptr.cpp +++ b/test/bptr.cpp @@ -1,6 +1,5 @@ #include "app.hpp" #include "compat/borrowed-ptr.inl" -#include "compat/borrowed-ptr-cast.hpp" #include "compat/assert.hpp" #include "compat/defs.hpp" #include @@ -376,6 +375,19 @@ void test11() auto p3 = static_pointer_cast(p1); fm_assert(p2->x == 1); fm_assert(p3); + p1.destroy(); + fm_assert(!p2); fm_assert(!p3); +} + +void test12() +{ + auto p1 = bptr{new Foo{1}}; + { + fm_assert(p1.use_count() == 1); + auto p2 = static_pointer_cast(p1); + fm_assert(p1.use_count() == 2); + } + fm_assert(p1.use_count() == 1); } } // namespace @@ -393,6 +405,7 @@ void Test::test_bptr() test9(); test10(); test11(); + test12(); } } // namespace floormat -- cgit v1.2.3