CommonLibVR
BSTSmartPointer.h
Go to the documentation of this file.
1 #pragma once
2 
3 namespace RE
4 {
5  template <class T>
7  {
8  static void Acquire(T* a_ptr)
9  {
10  a_ptr->IncRef();
11  }
12 
13  static void Release(T* a_ptr)
14  {
15  if (a_ptr->DecRef() == 0) {
16  delete a_ptr;
17  }
18  }
19  };
20 
21  template <class T>
23  {
24  constexpr static void Acquire(T* a_ptr)
25  {
26  return;
27  }
28 
29  static void Release(T* a_ptr)
30  {
31  delete a_ptr;
32  }
33  };
34 
35  template <class T, template <class> class RefManager = BSTSmartPointerIntrusiveRefCount>
37  {
38  public:
39  using element_type = T;
40  using reference_manager = RefManager<T>;
41 
42  // 1
43  inline constexpr BSTSmartPointer() noexcept :
44  _ptr(nullptr)
45  {}
46 
47  // 2
48  inline constexpr BSTSmartPointer(std::nullptr_t) noexcept :
49  _ptr(nullptr)
50  {}
51 
52  // 3
53  template <
54  class Y,
55  std::enable_if_t<
56  std::is_convertible_v<
57  Y*,
58  element_type*>,
59  int> = 0>
60  inline explicit BSTSmartPointer(Y* a_rhs) :
61  _ptr(a_rhs)
62  {
63  TryAttach();
64  }
65 
66  // 9a
67  inline BSTSmartPointer(const BSTSmartPointer& a_rhs) :
68  _ptr(a_rhs._ptr)
69  {
70  TryAttach();
71  }
72 
73  // 9b
74  template <
75  class Y,
76  std::enable_if_t<
77  std::is_convertible_v<
78  Y*,
79  element_type*>,
80  int> = 0>
81  inline BSTSmartPointer(const BSTSmartPointer<Y>& a_rhs) :
82  _ptr(a_rhs._ptr)
83  {
84  TryAttach();
85  }
86 
87  // 10a
88  inline BSTSmartPointer(BSTSmartPointer&& a_rhs) noexcept :
89  _ptr(std::move(a_rhs._ptr))
90  {
91  a_rhs._ptr = nullptr;
92  }
93 
94  // 10b
95  template <
96  class Y,
97  std::enable_if_t<
98  std::is_convertible_v<
99  Y*,
100  element_type*>,
101  int> = 0>
102  inline BSTSmartPointer(BSTSmartPointer<Y>&& a_rhs) noexcept :
103  _ptr(std::move(a_rhs._ptr))
104  {
105  a_rhs._ptr = nullptr;
106  }
107 
109  {
110  TryDetach();
111  }
112 
113  // 1a
115  {
116  if (this != std::addressof(a_rhs)) {
117  TryDetach();
118  _ptr = a_rhs._ptr;
119  TryAttach();
120  }
121  return *this;
122  }
123 
124  // 1b
125  template <
126  class Y,
127  std::enable_if_t<
128  std::is_convertible_v<
129  Y*,
130  element_type*>,
131  int> = 0>
133  {
134  TryDetach();
135  _ptr = a_rhs._ptr;
136  TryAttach();
137  return *this;
138  }
139 
140  // 2a
142  {
143  if (this != std::addressof(a_rhs)) {
144  TryDetach();
145  _ptr = std::move(a_rhs._ptr);
146  a_rhs._ptr = nullptr;
147  }
148  return *this;
149  }
150 
151  // 2b
152  template <
153  class Y,
154  std::enable_if_t<
155  std::is_convertible_v<
156  Y*,
157  element_type*>,
158  int> = 0>
160  {
161  TryDetach();
162  _ptr = std::move(a_rhs._ptr);
163  a_rhs._ptr = nullptr;
164  return *this;
165  }
166 
167  inline void reset()
168  {
169  TryDetach();
170  }
171 
172  template <
173  class Y,
174  std::enable_if_t<
175  std::is_convertible_v<
176  Y*,
177  element_type*>,
178  int> = 0>
179  inline void reset(Y* a_ptr)
180  {
181  if (_ptr != a_ptr) {
182  TryDetach();
183  _ptr = a_ptr;
184  TryAttach();
185  }
186  }
187 
188  [[nodiscard]] constexpr element_type* get() const noexcept
189  {
190  return _ptr;
191  }
192 
193  [[nodiscard]] explicit constexpr operator bool() const noexcept
194  {
195  return static_cast<bool>(_ptr);
196  }
197 
198  [[nodiscard]] constexpr element_type& operator*() const noexcept
199  {
200  assert(static_cast<bool>(*this));
201  return *_ptr;
202  }
203 
204  [[nodiscard]] constexpr element_type* operator->() const noexcept
205  {
206  assert(static_cast<bool>(*this));
207  return _ptr;
208  }
209 
210  protected:
211  template <class, template <class> class>
212  friend class BSTSmartPointer;
213 
214  inline void TryAttach()
215  {
216  if (_ptr) {
217  reference_manager::Acquire(_ptr);
218  }
219  }
220 
221  inline void TryDetach()
222  {
223  if (_ptr) {
224  reference_manager::Release(_ptr);
225  _ptr = nullptr;
226  }
227  }
228 
229  // members
231  };
232  static_assert(sizeof(BSTSmartPointer<void*>) == 0x8);
233 
234  template <class T, class... Args>
235  [[nodiscard]] inline BSTSmartPointer<T> make_smart(Args&&... a_args)
236  {
237  return BSTSmartPointer<T>{ new T(std::forward<Args>(a_args)...) };
238  }
239 
240  template <class T1, class T2>
241  [[nodiscard]] constexpr bool operator==(const BSTSmartPointer<T1>& a_lhs, const BSTSmartPointer<T2>& a_rhs)
242  {
243  return a_lhs.get() == a_rhs.get();
244  }
245 
246  template <class T1, class T2>
247  [[nodiscard]] constexpr bool operator!=(const BSTSmartPointer<T1>& a_lhs, const BSTSmartPointer<T2>& a_rhs)
248  {
249  return !(a_lhs == a_rhs);
250  }
251 
252  template <class T>
253  [[nodiscard]] constexpr bool operator==(const BSTSmartPointer<T>& a_lhs, std::nullptr_t) noexcept
254  {
255  return !a_lhs;
256  }
257 
258  template <class T>
259  [[nodiscard]] constexpr bool operator==(std::nullptr_t, const BSTSmartPointer<T>& a_rhs) noexcept
260  {
261  return !a_rhs;
262  }
263 
264  template <class T>
265  [[nodiscard]] constexpr bool operator!=(const BSTSmartPointer<T>& a_lhs, std::nullptr_t) noexcept
266  {
267  return static_cast<bool>(a_lhs);
268  }
269 
270  template <class T>
271  [[nodiscard]] constexpr bool operator!=(std::nullptr_t, const BSTSmartPointer<T>& a_rhs) noexcept
272  {
273  return static_cast<bool>(a_rhs);
274  }
275 
276  template <class T>
278 
279  template <class T>
281  static_assert(sizeof(BSTAutoPointer<void*>) == 0x8);
282 }
283 
284 #define BSSmartPointer(className) \
285  class className; \
286  using className##Ptr = RE::BSTSmartPointer<className>;
Definition: BSTSmartPointer.h:37
BSTSmartPointer(const BSTSmartPointer< Y > &a_rhs)
Definition: BSTSmartPointer.h:81
BSTSmartPointer(BSTSmartPointer &&a_rhs) noexcept
Definition: BSTSmartPointer.h:88
constexpr element_type & operator*() const noexcept
Definition: BSTSmartPointer.h:198
BSTSmartPointer & operator=(const BSTSmartPointer &a_rhs)
Definition: BSTSmartPointer.h:114
void reset()
Definition: BSTSmartPointer.h:167
void TryAttach()
Definition: BSTSmartPointer.h:214
void TryDetach()
Definition: BSTSmartPointer.h:221
constexpr BSTSmartPointer(std::nullptr_t) noexcept
Definition: BSTSmartPointer.h:48
element_type * _ptr
Definition: BSTSmartPointer.h:230
constexpr BSTSmartPointer() noexcept
Definition: BSTSmartPointer.h:43
BSTSmartPointer & operator=(BSTSmartPointer< Y > &&a_rhs)
Definition: BSTSmartPointer.h:159
constexpr element_type * operator->() const noexcept
Definition: BSTSmartPointer.h:204
BSTSmartPointer(const BSTSmartPointer &a_rhs)
Definition: BSTSmartPointer.h:67
~BSTSmartPointer()
Definition: BSTSmartPointer.h:108
RefManager< T > reference_manager
Definition: BSTSmartPointer.h:40
BSTSmartPointer(BSTSmartPointer< Y > &&a_rhs) noexcept
Definition: BSTSmartPointer.h:102
T element_type
Definition: BSTSmartPointer.h:39
BSTSmartPointer(Y *a_rhs)
Definition: BSTSmartPointer.h:60
BSTSmartPointer & operator=(const BSTSmartPointer< Y > &a_rhs)
Definition: BSTSmartPointer.h:132
BSTSmartPointer & operator=(BSTSmartPointer &&a_rhs)
Definition: BSTSmartPointer.h:141
constexpr element_type * get() const noexcept
Definition: BSTSmartPointer.h:188
void reset(Y *a_ptr)
Definition: BSTSmartPointer.h:179
Definition: AbsorbEffect.h:6
constexpr bool operator==(const BSTSmartPointer< T1 > &a_lhs, const BSTSmartPointer< T2 > &a_rhs)
Definition: BSTSmartPointer.h:241
BSTSmartPointer(T *) -> BSTSmartPointer< T, BSTSmartPointerIntrusiveRefCount >
BSTSmartPointer< T > make_smart(Args &&... a_args)
Definition: BSTSmartPointer.h:235
constexpr bool operator!=(const BSTSmartPointer< T1 > &a_lhs, const BSTSmartPointer< T2 > &a_rhs)
Definition: BSTSmartPointer.h:247
Definition: BSTSmartPointer.h:23
constexpr static void Acquire(T *a_ptr)
Definition: BSTSmartPointer.h:24
static void Release(T *a_ptr)
Definition: BSTSmartPointer.h:29
Definition: BSTSmartPointer.h:7
static void Release(T *a_ptr)
Definition: BSTSmartPointer.h:13
static void Acquire(T *a_ptr)
Definition: BSTSmartPointer.h:8