#ifndef COMMON_COMPTR_H #define COMMON_COMPTR_H #include #include #include "opthelpers.h" template class ComPtr { T *mPtr{nullptr}; public: ComPtr() noexcept = default; ComPtr(const ComPtr &rhs) : 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) { if(!rhs.mPtr) { if(mPtr) mPtr->Release(); mPtr = nullptr; } else { rhs.mPtr->AddRef(); try { if(mPtr) mPtr->Release(); mPtr = rhs.mPtr; } catch(...) { rhs.mPtr->Release(); throw; } } return *this; } ComPtr& operator=(ComPtr&& rhs) { if(&rhs != this) [[likely]] { if(mPtr) mPtr->Release(); mPtr = std::exchange(rhs.mPtr, nullptr); } return *this; } 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); } }; #endif