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