🛠️🐜 Antkeeper superbuild with dependencies included https://antkeeper.com
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

68 lines
1.6 KiB

  1. #ifndef COMMON_COMPTR_H
  2. #define COMMON_COMPTR_H
  3. #include <cstddef>
  4. #include <utility>
  5. #include "opthelpers.h"
  6. template<typename T>
  7. class ComPtr {
  8. T *mPtr{nullptr};
  9. public:
  10. ComPtr() noexcept = default;
  11. ComPtr(const ComPtr &rhs) : mPtr{rhs.mPtr} { if(mPtr) mPtr->AddRef(); }
  12. ComPtr(ComPtr&& rhs) noexcept : mPtr{rhs.mPtr} { rhs.mPtr = nullptr; }
  13. ComPtr(std::nullptr_t) noexcept { }
  14. explicit ComPtr(T *ptr) noexcept : mPtr{ptr} { }
  15. ~ComPtr() { if(mPtr) mPtr->Release(); }
  16. ComPtr& operator=(const ComPtr &rhs)
  17. {
  18. if(!rhs.mPtr)
  19. {
  20. if(mPtr)
  21. mPtr->Release();
  22. mPtr = nullptr;
  23. }
  24. else
  25. {
  26. rhs.mPtr->AddRef();
  27. try {
  28. if(mPtr)
  29. mPtr->Release();
  30. mPtr = rhs.mPtr;
  31. }
  32. catch(...) {
  33. rhs.mPtr->Release();
  34. throw;
  35. }
  36. }
  37. return *this;
  38. }
  39. ComPtr& operator=(ComPtr&& rhs)
  40. {
  41. if(likely(&rhs != this))
  42. {
  43. if(mPtr) mPtr->Release();
  44. mPtr = std::exchange(rhs.mPtr, nullptr);
  45. }
  46. return *this;
  47. }
  48. explicit operator bool() const noexcept { return mPtr != nullptr; }
  49. T& operator*() const noexcept { return *mPtr; }
  50. T* operator->() const noexcept { return mPtr; }
  51. T* get() const noexcept { return mPtr; }
  52. T** getPtr() noexcept { return &mPtr; }
  53. T* release() noexcept { return std::exchange(mPtr, nullptr); }
  54. void swap(ComPtr &rhs) noexcept { std::swap(mPtr, rhs.mPtr); }
  55. void swap(ComPtr&& rhs) noexcept { std::swap(mPtr, rhs.mPtr); }
  56. };
  57. #endif