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