CommonLibSSE (Parapets fork)
Loading...
Searching...
No Matches
BSTSmartPointer.h
Go to the documentation of this file.
1#pragma once
2
3namespace 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*,
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*,
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
void reset()
Definition: BSTSmartPointer.h:167
void TryAttach()
Definition: BSTSmartPointer.h:214
void TryDetach()
Definition: BSTSmartPointer.h:221
BSTSmartPointer & operator=(const BSTSmartPointer &a_rhs)
Definition: BSTSmartPointer.h:114
constexpr BSTSmartPointer(std::nullptr_t) noexcept
Definition: BSTSmartPointer.h:48
element_type * _ptr
Definition: BSTSmartPointer.h:230
BSTSmartPointer & operator=(BSTSmartPointer< Y > &&a_rhs)
Definition: BSTSmartPointer.h:159
constexpr BSTSmartPointer() noexcept
Definition: BSTSmartPointer.h:43
constexpr element_type * get() const noexcept
Definition: BSTSmartPointer.h:188
BSTSmartPointer(const BSTSmartPointer &a_rhs)
Definition: BSTSmartPointer.h:67
~BSTSmartPointer()
Definition: BSTSmartPointer.h:108
BSTSmartPointer & operator=(BSTSmartPointer &&a_rhs)
Definition: BSTSmartPointer.h:141
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
constexpr element_type * operator->() const noexcept
Definition: BSTSmartPointer.h:204
BSTSmartPointer & operator=(const BSTSmartPointer< Y > &a_rhs)
Definition: BSTSmartPointer.h:132
void reset(Y *a_ptr)
Definition: BSTSmartPointer.h:179
Definition: AbsorbEffect.h:6
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:241
constexpr bool operator!=(const BSTSmartPointer< T1 > &a_lhs, const BSTSmartPointer< T2 > &a_rhs)
Definition: BSTSmartPointer.h:247
Definition: BSTSmartPointer.h:23
static void Release(T *a_ptr)
Definition: BSTSmartPointer.h:29
static constexpr void Acquire(T *a_ptr)
Definition: BSTSmartPointer.h:24
Definition: BSTSmartPointer.h:7
static void Release(T *a_ptr)
Definition: BSTSmartPointer.h:13
static void Acquire(T *a_ptr)
Definition: BSTSmartPointer.h:8