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