diff options
Diffstat (limited to 'compat')
-rw-r--r-- | compat/borrowed-ptr-fwd.hpp | 42 | ||||
-rw-r--r-- | compat/borrowed-ptr.cpp | 2 | ||||
-rw-r--r-- | compat/borrowed-ptr.inl | 84 |
3 files changed, 85 insertions, 43 deletions
diff --git a/compat/borrowed-ptr-fwd.hpp b/compat/borrowed-ptr-fwd.hpp index 465e9bf4..01dd20f7 100644 --- a/compat/borrowed-ptr-fwd.hpp +++ b/compat/borrowed-ptr-fwd.hpp @@ -1,6 +1,15 @@ #pragma once -namespace floormat::detail_borrowed_ptr { struct control_block_; } +namespace floormat::detail_borrowed_ptr { + +struct control_block; +template<typename From, typename To> +concept DerivedFrom = requires(From* x) { + requires !std::is_same_v<From, To>; + requires std::is_nothrow_convertible_v<From*, To*>; +}; + +} // namespace floormat::detail_borrowed_ptr namespace floormat { @@ -11,26 +20,39 @@ template<typename T> class bptr final // NOLINT(*-special-member-functions) { mutable T* casted_ptr; - detail_borrowed_ptr::control_block_* blk; + detail_borrowed_ptr::control_block* blk; - explicit bptr(DirectInitT, T* casted_ptr, detail_borrowed_ptr::control_block_* blk) noexcept; - //explicit bptr(NoInitT) noexcept; + explicit bptr(DirectInitT, T* casted_ptr, detail_borrowed_ptr::control_block* blk) noexcept; + + struct private_tag_t final {}; + static constexpr private_tag_t private_tag{}; + + template<typename Y> bptr(const bptr<Y>& other, private_tag_t) noexcept; + template<typename Y> bptr& _copy_assign(const bptr<Y>& other) noexcept; + template<typename Y> bptr(bptr<Y>&& other, private_tag_t) noexcept; + template<typename Y> bptr& _move_assign(bptr<Y>&& other) noexcept; public: template<typename... Ts> requires std::is_constructible_v<T, Ts&&...> explicit bptr(InPlaceInitT, Ts&&... args) noexcept; - bptr(std::nullptr_t) noexcept; // NOLINT(*-explicit-conversions) - bptr() noexcept; explicit bptr(T* ptr) noexcept; + bptr() noexcept; ~bptr() noexcept; + bptr(std::nullptr_t) noexcept; // NOLINT(*-explicit-conversions) bptr& operator=(std::nullptr_t) noexcept; - template<typename Y> requires std::is_convertible_v<Y*, T*> bptr(const bptr<Y>&) noexcept; - template<typename Y> requires std::is_convertible_v<Y*, T*> bptr& operator=(const bptr<Y>&) noexcept; - template<typename Y> requires std::is_convertible_v<Y*, T*> bptr(bptr<Y>&&) noexcept; - template<typename Y> requires std::is_convertible_v<Y*, T*> bptr& operator=(bptr<Y>&&) noexcept; + + bptr(const bptr&) noexcept; + bptr& operator=(const bptr&) noexcept; + template<detail_borrowed_ptr::DerivedFrom<T> Y> bptr(const bptr<Y>&) noexcept; + template<detail_borrowed_ptr::DerivedFrom<T> Y> bptr& operator=(const bptr<Y>&) noexcept; + + bptr(bptr&&) noexcept; + bptr& operator=(bptr&&) noexcept; + template<detail_borrowed_ptr::DerivedFrom<T> Y> bptr(bptr<Y>&&) noexcept; + template<detail_borrowed_ptr::DerivedFrom<T> Y> bptr& operator=(bptr<Y>&&) noexcept; friend bool operator==<T>(const bptr<T>& a, const bptr<T>& b) noexcept; explicit operator bool() const noexcept; diff --git a/compat/borrowed-ptr.cpp b/compat/borrowed-ptr.cpp index 413527cb..a73b869f 100644 --- a/compat/borrowed-ptr.cpp +++ b/compat/borrowed-ptr.cpp @@ -13,7 +13,7 @@ namespace floormat::detail_borrowed_ptr { #pragma warning(push) #pragma warning(disable : 5205) #endif -void control_block_::decrement(control_block_*& blk) noexcept +void control_block::decrement(control_block*& blk) noexcept { fm_bptr_assert(blk); auto c = --blk->_count; diff --git a/compat/borrowed-ptr.inl b/compat/borrowed-ptr.inl index fd2d25d2..98e0fec5 100644 --- a/compat/borrowed-ptr.inl +++ b/compat/borrowed-ptr.inl @@ -1,6 +1,7 @@ #pragma once #include "borrowed-ptr.hpp" #include "compat/assert.hpp" +#include <utility> #define FM_BPTR_DEBUG @@ -21,22 +22,22 @@ namespace floormat::detail_borrowed_ptr { #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wnon-virtual-dtor" #endif -struct control_block_ +struct control_block { void* _ptr; // todo maybe add directly embeddable objects? uint32_t _count; virtual void free_ptr() noexcept = 0; - static void decrement(control_block_*& blk) noexcept; + static void decrement(control_block*& blk) noexcept; }; #ifdef __GNUG__ #pragma GCC diagnostic pop #endif template<typename T> -struct control_block_impl final: control_block_ +struct control_block_impl final: control_block { void free_ptr() noexcept override; - [[nodiscard]] static control_block_* create(T* ptr) noexcept; + [[nodiscard]] static control_block* create(T* ptr) noexcept; protected: explicit control_block_impl(T* ptr) noexcept; }; @@ -56,7 +57,7 @@ void control_block_impl<T>::free_ptr() noexcept } template <typename T> -control_block_* control_block_impl<T>::create(T* ptr) noexcept +control_block* control_block_impl<T>::create(T* ptr) noexcept { if (ptr) { @@ -71,12 +72,10 @@ control_block_* control_block_impl<T>::create(T* ptr) noexcept namespace floormat { -template<typename T> bptr<T>::bptr(DirectInitT, T* casted_ptr, detail_borrowed_ptr::control_block_* blk) noexcept: +template<typename T> bptr<T>::bptr(DirectInitT, T* casted_ptr, detail_borrowed_ptr::control_block* blk) noexcept: casted_ptr{casted_ptr}, blk{blk} {} -//template<typename T> bptr<T>::bptr(NoInitT) noexcept {} - template<typename T> template<typename... Ts> requires std::is_constructible_v<T, Ts&&...> @@ -103,28 +102,29 @@ bptr<T>::~bptr() noexcept blk->decrement(blk); } +template<typename T> bptr<T>::bptr(const bptr& other) noexcept: bptr{other, private_tag} {} +template<typename T> bptr<T>& bptr<T>::operator=(const bptr& other) noexcept { return _copy_assign(other); } + template<typename T> -template<typename Y> -requires std::is_convertible_v<Y*, T*> -bptr<T>::bptr(const bptr<Y>& other) noexcept: - casted_ptr{other.casted_ptr}, blk{other.blk} -{ - if (blk) - { - ++blk->_count; - fm_bptr_assert(blk->_count > 1); - } -} +template<detail_borrowed_ptr::DerivedFrom<T> Y> +bptr<T>::bptr(const bptr<Y>& other) noexcept: bptr{other, private_tag} {} template<typename T> -template<typename Y> -requires std::is_convertible_v<Y*, T*> -bptr<T>::bptr(bptr<Y>&& other) noexcept: - casted_ptr{other.casted_ptr}, blk{other.blk} -{ - other.casted_ptr = nullptr; - other.blk = nullptr; -} +template<detail_borrowed_ptr::DerivedFrom<T> Y> +bptr<T>& bptr<T>::operator=(const bptr<Y>& other) noexcept +{ return _copy_assign(other); } + +template<typename T> bptr<T>& bptr<T>::operator=(bptr&& other) noexcept { return _move_assign(move(other)); } +template<typename T> bptr<T>::bptr(bptr&& other) noexcept: bptr{move(other), private_tag} {} + +template<typename T> +template<detail_borrowed_ptr::DerivedFrom<T> Y> +bptr<T>::bptr(bptr<Y>&& other) noexcept: bptr{move(other), private_tag} {} + +template<typename T> +template<detail_borrowed_ptr::DerivedFrom<T> Y> +bptr<T>& bptr<T>::operator=(bptr<Y>&& other) noexcept +{ return _move_assign(move(other)); } template<typename T> void bptr<T>::reset() noexcept @@ -153,8 +153,19 @@ template<typename T> bptr<T>& bptr<T>::operator=(std::nullptr_t) noexcept { rese template<typename T> template<typename Y> -requires std::is_convertible_v<Y*, T*> -bptr<T>& bptr<T>::operator=(const bptr<Y>& other) noexcept +bptr<T>::bptr(const bptr<Y>& other, private_tag_t) noexcept: + casted_ptr{other.casted_ptr}, blk{other.blk} +{ + if (blk) + { + ++blk->_count; + fm_bptr_assert(blk->_count > 1); + } +} + +template<typename T> +template<typename Y> +bptr<T>& bptr<T>::_copy_assign(const bptr<Y>& other) noexcept { if (blk != other.blk) { @@ -170,10 +181,19 @@ bptr<T>& bptr<T>::operator=(const bptr<Y>& other) noexcept template<typename T> template<typename Y> -requires std::is_convertible_v<Y*, T*> -bptr<T>& bptr<T>::operator=(bptr<Y>&& other) noexcept +bptr<T>::bptr(bptr<Y>&& other, private_tag_t) noexcept: + casted_ptr{other.casted_ptr}, blk{other.blk} { - blk->decrement(blk); + other.casted_ptr = nullptr; + other.blk = nullptr; +} + +template<typename T> +template<typename Y> +bptr<T>& bptr<T>::_move_assign(bptr<Y>&& other) noexcept +{ + if (blk) + blk->decrement(blk); casted_ptr = other.casted_ptr; blk = other.blk; other.casted_ptr = nullptr; |