diff options
author | Chris Robinson <[email protected]> | 2023-05-04 08:33:43 -0700 |
---|---|---|
committer | Chris Robinson <[email protected]> | 2023-05-04 08:33:43 -0700 |
commit | 3d2e586636f765eb2fccebb757305295d7b2c954 (patch) | |
tree | ee37b042f27859871a07d1b143bff6350239cca3 /common | |
parent | 7cda37a67c8f147536c53f0073df9a9e61d40587 (diff) |
Update ComPtr and use an out_ptr() function
Diffstat (limited to 'common')
-rw-r--r-- | common/comptr.h | 95 |
1 files changed, 69 insertions, 26 deletions
diff --git a/common/comptr.h b/common/comptr.h index cdc6dec0..5a733ea2 100644 --- a/common/comptr.h +++ b/common/comptr.h @@ -2,49 +2,46 @@ #define COMMON_COMPTR_H #include <cstddef> +#include <memory> +#include <type_traits> #include <utility> - -#include "opthelpers.h" - +#include <variant> template<typename T> -class ComPtr { - T *mPtr{nullptr}; +struct ComPtr { + using element_type = T; + + static constexpr bool RefIsNoexcept{noexcept(std::declval<T&>().AddRef()) + && noexcept(std::declval<T&>().Release())}; -public: ComPtr() noexcept = default; - ComPtr(const ComPtr &rhs) : mPtr{rhs.mPtr} { if(mPtr) mPtr->AddRef(); } + ComPtr(const ComPtr &rhs) noexcept(RefIsNoexcept) : mPtr{rhs.mPtr} + { if(mPtr) mPtr->AddRef(); } ComPtr(ComPtr&& rhs) noexcept : mPtr{rhs.mPtr} { rhs.mPtr = nullptr; } ComPtr(std::nullptr_t) noexcept { } explicit ComPtr(T *ptr) noexcept : mPtr{ptr} { } ~ComPtr() { if(mPtr) mPtr->Release(); } - ComPtr& operator=(const ComPtr &rhs) + ComPtr& operator=(const ComPtr &rhs) noexcept(RefIsNoexcept) { - if(!rhs.mPtr) + if constexpr(RefIsNoexcept) { - if(mPtr) - mPtr->Release(); - mPtr = nullptr; + if(rhs.mPtr) rhs.mPtr->AddRef(); + if(mPtr) mPtr->Release(); + mPtr = rhs.mPtr; + return *this; } else { - rhs.mPtr->AddRef(); - try { - if(mPtr) - mPtr->Release(); - mPtr = rhs.mPtr; - } - catch(...) { - rhs.mPtr->Release(); - throw; - } + ComPtr tmp{rhs}; + if(mPtr) mPtr->Release(); + mPtr = tmp.release(); + return *this; } - return *this; } - ComPtr& operator=(ComPtr&& rhs) + ComPtr& operator=(ComPtr&& rhs) noexcept(RefIsNoexcept) { - if(&rhs != this) LIKELY + if(&rhs != this) { if(mPtr) mPtr->Release(); mPtr = std::exchange(rhs.mPtr, nullptr); @@ -52,17 +49,63 @@ public: return *this; } + void reset(T *ptr=nullptr) noexcept(RefIsNoexcept) + { + if(mPtr) mPtr->Release(); + mPtr = ptr; + } + explicit operator bool() const noexcept { return mPtr != nullptr; } T& operator*() const noexcept { return *mPtr; } T* operator->() const noexcept { return mPtr; } T* get() const noexcept { return mPtr; } - T** getPtr() noexcept { return &mPtr; } T* release() noexcept { return std::exchange(mPtr, nullptr); } void swap(ComPtr &rhs) noexcept { std::swap(mPtr, rhs.mPtr); } void swap(ComPtr&& rhs) noexcept { std::swap(mPtr, rhs.mPtr); } + +private: + T *mPtr{nullptr}; }; + +namespace al { + +template<typename SP, typename PT, typename ...Args> +class out_ptr_t { + static_assert(!std::is_same_v<PT,void*>); + + SP &mRes; + std::variant<PT,void*> mPtr{}; + +public: + out_ptr_t(SP &res) : mRes{res} { } + ~out_ptr_t() + { + auto set_res = [this](auto &ptr) + { mRes.reset(static_cast<PT>(ptr)); }; + std::visit(set_res, mPtr); + } + out_ptr_t(const out_ptr_t&) = delete; + + out_ptr_t& operator=(const out_ptr_t&) = delete; + + operator PT*() noexcept + { return &std::get<PT>(mPtr); } + + operator void**() noexcept + { return &mPtr.template emplace<void*>(); } +}; + +template<typename T=void, typename SP, typename ...Args> +auto out_ptr(SP &res) +{ + using ptype = typename SP::element_type*; + return out_ptr_t<SP,ptype>{res}; +} + +} // namespace al + #endif |