CommonLibSSE NG
COMPTR.h
Go to the documentation of this file.
1 #pragma once
2 
3 #include "REX/W32/BASE.h"
4 
5 namespace REX::W32
6 {
7  // based on Microsoft::WRL::ComPtr
8  template <class T>
9  struct ComPtr
10  {
11  constexpr ComPtr() noexcept = default;
12  constexpr ComPtr(std::nullptr_t) noexcept {}
13 
14  ComPtr(const ComPtr& a_other) noexcept :
15  _ptr(a_other._ptr)
16  {
17  TryAddRef();
18  }
19 
20  template <class U>
21  ComPtr(U* a_other) noexcept :
22  _ptr(a_other)
23  {
24  TryAddRef();
25  }
26 
27  ~ComPtr() noexcept
28  {
29  TryRelease();
30  }
31 
32  ComPtr& operator=(std::nullptr_t) noexcept
33  {
34  TryRelease();
35  return *this;
36  }
37 
38  ComPtr& operator=(T* a_other) noexcept
39  {
40  if (_ptr != a_other)
41  ComPtr(a_other).Swap(*this);
42 
43  return *this;
44  }
45 
46  template <class U>
47  ComPtr& operator=(U* a_other) noexcept
48  {
49  ComPtr(a_other).Swap(*this);
50  return *this;
51  }
52 
53  ComPtr& operator=(const ComPtr& a_other) noexcept
54  {
55  if (_ptr != a_other._ptr)
56  ComPtr(a_other).Swap(*this);
57 
58  return *this;
59  }
60 
61  template <class U>
62  ComPtr& operator=(const ComPtr<U>& a_other) noexcept
63  {
64  ComPtr(a_other).Swap(*this);
65  return *this;
66  }
67 
68  ComPtr& operator=(ComPtr&& a_other) noexcept
69  {
70  ComPtr(static_cast<ComPtr&&>(a_other)).Swap(*this);
71  return *this;
72  }
73 
74  template <class U>
75  ComPtr& operator=(ComPtr<U>&& a_other) noexcept
76  {
77  ComPtr(static_cast<ComPtr<U>&&>(a_other)).Swap(*this);
78  return *this;
79  }
80 
81  T* operator->() const noexcept
82  {
83  return _ptr;
84  }
85 
86  void Attach(T* a_other) noexcept
87  {
88  if (_ptr != nullptr) {
89  [[maybe_unused]] auto ref = _ptr->Release();
90  assert((ref != 0) || (_ptr != a_other));
91  }
92 
93  _ptr = a_other;
94  }
95 
96  T* Detach() noexcept
97  {
98  T* ptr = _ptr;
99  _ptr = nullptr;
100  return ptr;
101  }
102 
103  T* Get() const noexcept
104  {
105  return _ptr;
106  }
107 
108  T** GetAddressOf() noexcept
109  {
110  return &_ptr;
111  }
112 
113  T* const* GetAddressOf() const noexcept
114  {
115  return &_ptr;
116  }
117 
118  T** ReleaseAndGetAddressOf() noexcept
119  {
120  TryRelease();
121  return &_ptr;
122  }
123 
124  std::uint32_t Reset() noexcept
125  {
126  return TryRelease();
127  }
128 
129  void Swap(ComPtr& a_other) noexcept
130  {
131  T* ptr = _ptr;
132  _ptr = a_other._ptr;
133  a_other._ptr = ptr;
134  }
135 
136  void Swap(ComPtr&& a_other) noexcept
137  {
138  T* ptr = _ptr;
139  _ptr = a_other._ptr;
140  a_other._ptr = ptr;
141  }
142 
143  template <class U>
144  HRESULT As(ComPtr<U>* a_ptr) const noexcept
145  {
146  return _ptr->QueryInterface(__uuidof(U), reinterpret_cast<void**>(a_ptr->ReleaseAndGetAddressOf()));
147  }
148 
149  template <class U>
150  HRESULT AsIID(const IID& a_iid, ComPtr<U>* a_ptr) const noexcept
151  {
152  return _ptr->QueryInterface(a_iid, reinterpret_cast<void**>(a_ptr->ReleaseAndGetAddressOf()));
153  }
154 
155  HRESULT CopyTo(const IID& a_iid, void** a_ptr) const noexcept
156  {
157  return _ptr->QueryInterface(a_iid, a_ptr);
158  }
159 
160  HRESULT CopyTo(T** a_ptr) const noexcept
161  {
162  TryAddRef();
163  *a_ptr = _ptr;
164  return 0;
165  }
166 
167  template <class U>
168  HRESULT CopyTo(U** a_ptr) const noexcept
169  {
170  return _ptr->QueryInterface(__uuidof(U), reinterpret_cast<void**>(a_ptr));
171  }
172 
173  protected:
174  template <class U>
175  friend struct ComPtr;
176 
177  void TryAddRef() const noexcept
178  {
179  if (_ptr)
180  _ptr->AddRef();
181  }
182 
183  std::uint32_t TryRelease() noexcept
184  {
185  T* ptr = _ptr;
186  if (ptr) {
187  _ptr = nullptr;
188  return ptr->Release();
189  }
190 
191  return 0;
192  }
193 
194  T* _ptr{ nullptr };
195  };
196 }
Definition: BSDirectInputManager.h:8
std::int32_t HRESULT
Definition: BASE.h:28
Definition: ActorValueList.h:28
Definition: COMPTR.h:10
ComPtr & operator=(std::nullptr_t) noexcept
Definition: COMPTR.h:32
std::uint32_t Reset() noexcept
Definition: COMPTR.h:124
ComPtr & operator=(ComPtr &&a_other) noexcept
Definition: COMPTR.h:68
void Attach(T *a_other) noexcept
Definition: COMPTR.h:86
ComPtr & operator=(const ComPtr< U > &a_other) noexcept
Definition: COMPTR.h:62
ComPtr(const ComPtr &a_other) noexcept
Definition: COMPTR.h:14
T * Get() const noexcept
Definition: COMPTR.h:103
ComPtr & operator=(ComPtr< U > &&a_other) noexcept
Definition: COMPTR.h:75
HRESULT CopyTo(T **a_ptr) const noexcept
Definition: COMPTR.h:160
constexpr ComPtr() noexcept=default
void Swap(ComPtr &a_other) noexcept
Definition: COMPTR.h:129
T * operator->() const noexcept
Definition: COMPTR.h:81
T *const * GetAddressOf() const noexcept
Definition: COMPTR.h:113
T * _ptr
Definition: COMPTR.h:194
HRESULT As(ComPtr< U > *a_ptr) const noexcept
Definition: COMPTR.h:144
std::uint32_t TryRelease() noexcept
Definition: COMPTR.h:183
T ** GetAddressOf() noexcept
Definition: COMPTR.h:108
ComPtr & operator=(U *a_other) noexcept
Definition: COMPTR.h:47
HRESULT CopyTo(U **a_ptr) const noexcept
Definition: COMPTR.h:168
T * Detach() noexcept
Definition: COMPTR.h:96
ComPtr & operator=(T *a_other) noexcept
Definition: COMPTR.h:38
void TryAddRef() const noexcept
Definition: COMPTR.h:177
HRESULT AsIID(const IID &a_iid, ComPtr< U > *a_ptr) const noexcept
Definition: COMPTR.h:150
friend struct ComPtr
Definition: COMPTR.h:175
ComPtr(U *a_other) noexcept
Definition: COMPTR.h:21
void Swap(ComPtr &&a_other) noexcept
Definition: COMPTR.h:136
~ComPtr() noexcept
Definition: COMPTR.h:27
ComPtr & operator=(const ComPtr &a_other) noexcept
Definition: COMPTR.h:53
HRESULT CopyTo(const IID &a_iid, void **a_ptr) const noexcept
Definition: COMPTR.h:155
T ** ReleaseAndGetAddressOf() noexcept
Definition: COMPTR.h:118
Definition: BASE.h:62