IceShard 1
A personal game engine project, with development focused on 2D/2.5D games.
Loading...
Searching...
No Matches
ptr.hxx
Go to the documentation of this file.
1
3
4#pragma once
6
7namespace ice
8{
9
10 template<typename Object> requires ice::concepts::IsRefCounted<Object>
11 class Ptr
12 {
13 using RCPassKey = ice::detail::RCPassKey;
14 public:
15 ~Ptr() noexcept;
16 explicit Ptr(std::nullptr_t = nullptr) noexcept;
17 explicit Ptr(Object* object_ptr) noexcept;
18
19 Ptr(Ptr const& other) noexcept;
20 auto operator=(Ptr const& other) noexcept -> Ptr&;
21
22 Ptr(Ptr&& other) noexcept;
23 auto operator=(Ptr&& other) noexcept -> Ptr&;
24
25 template<typename Derived> requires std::is_base_of_v<Object, Derived>
26 Ptr(Ptr<Derived> const& other) noexcept;
27 template<typename Derived> requires std::is_base_of_v<Object, Derived>
28 auto operator=(Ptr<Derived> const& other) noexcept -> Ptr&;
29
30 template<typename Self>
31 [[nodiscard]]
32 auto raw_ptr(this Self& self) noexcept -> Object* { return self._ptr; }
33
34 template<typename Self>
35 auto operator->(this Self& self) noexcept { return self.raw_ptr(); }
36
37 template<typename Self>
38 auto operator==(this Self const& self, std::nullptr_t) noexcept -> bool { return self.raw_ptr() == nullptr; }
39
40 private:
41 Object* _ptr;
42 };
43
44 template<typename Object> requires ice::concepts::IsRefCounted<Object>
45 class Ptr<Object const>
46 {
47 using RCPassKey = ice::detail::RCPassKey;
48 public:
49 ~Ptr() noexcept;
50 explicit Ptr(std::nullptr_t = nullptr) noexcept;
51
52 Ptr(Ptr const& other) noexcept;
53 auto operator=(Ptr const& other) noexcept -> Ptr&;
54 Ptr(Ptr<Object> const& other) noexcept;
55 auto operator=(Ptr<Object> const& other) noexcept -> Ptr&;
56
57 Ptr(Ptr&& other) noexcept;
58 auto operator=(Ptr&& other) noexcept -> Ptr&;
59 Ptr(Ptr<Object>&& other) noexcept;
60 auto operator=(Ptr<Object>&& other) noexcept -> Ptr&;
61
62 template<typename Derived> requires std::is_base_of_v<Object, Derived>
63 auto operator=(Ptr<Derived const> const& other) noexcept -> Ptr&;
64
65 [[nodiscard]]
66 auto raw_ptr() const noexcept -> Object const* { return _ptr; }
67
68 auto operator->() const noexcept -> Object const* { return raw_ptr(); }
69
70 auto operator==(std::nullptr_t) const noexcept -> bool { return raw_ptr() == nullptr; }
71
72 private:
73 Object* _ptr;
74 };
75
77
78 template<typename Object> requires ice::concepts::IsRefCounted<Object>
79 inline Ptr<Object>::~Ptr() noexcept
80 {
81 if (_ptr != nullptr)
82 {
83 _ptr->rc_sub(RCPassKey{});
84 }
85 }
86
87 template<typename Object> requires ice::concepts::IsRefCounted<Object>
88 inline Ptr<Object>::Ptr(std::nullptr_t) noexcept
89 : _ptr{ nullptr }
90 {
91 }
92
93 template<typename Object> requires ice::concepts::IsRefCounted<Object>
94 inline Ptr<Object>::Ptr(Object* object_ptr) noexcept
95 : _ptr{ object_ptr->rc_claim(RCPassKey{}) }
96 {
97 }
98
99 template<typename Object> requires ice::concepts::IsRefCounted<Object>
100 inline Ptr<Object>::Ptr(Ptr const& other) noexcept
101 : _ptr{ other->rc_add(RCPassKey{}) }
102 {
103 }
104
105 template<typename Object> requires ice::concepts::IsRefCounted<Object>
106 inline auto Ptr<Object>::operator=(Ptr const& other) noexcept -> Ptr&
107 {
108 if (this != ice::addressof(other))
109 {
110 if (Object* prev = ice::exchange(_ptr, nullptr); prev != nullptr)
111 {
112 prev->rc_sub(RCPassKey{});
113 }
114
115 _ptr = other->rc_add(RCPassKey{});
116 ICE_ASSERT_CORE(_ptr == nullptr || _ptr->rc_unclaimed(RCPassKey{}) == false);
117 }
118 return *this;
119 }
120
121 template<typename Object> requires ice::concepts::IsRefCounted<Object>
122 inline Ptr<Object>::Ptr(Ptr&& other) noexcept
123 : _ptr{ std::exchange(other._ptr, nullptr) }
124 {
125 ICE_ASSERT_CORE(_ptr == nullptr || _ptr->rc_unclaimed(RCPassKey{}) == false);
126 }
127
128 template<typename Object> requires ice::concepts::IsRefCounted<Object>
129 inline auto Ptr<Object>::operator=(Ptr&& other) noexcept -> Ptr&
130 {
131 if (this != ice::addressof(other))
132 {
133 if (Object* prev = ice::exchange(_ptr, nullptr); prev != nullptr)
134 {
135 prev->rc_sub(RCPassKey{});
136 }
137
138 _ptr = ice::exchange(other._ptr, nullptr);
139 ICE_ASSERT_CORE(_ptr == nullptr || _ptr->rc_unclaimed(RCPassKey{}) == false);
140 }
141 return *this;
142 }
143
144 template<typename Object> requires ice::concepts::IsRefCounted<Object>
145 template<typename Derived> requires std::is_base_of_v<Object, Derived>
146 inline Ptr<Object>::Ptr(Ptr<Derived> const& other) noexcept
147 : _ptr{ other.raw_ptr()->rc_add(RCPassKey{}) }
148 {
149 ICE_ASSERT_CORE(_ptr == nullptr || _ptr->rc_unclaimed(RCPassKey{}) == false);
150 }
151
152 template<typename Object> requires ice::concepts::IsRefCounted<Object>
153 template<typename Derived> requires std::is_base_of_v<Object, Derived>
154 inline auto Ptr<Object>::operator=(Ptr<Derived> const& other) noexcept -> Ptr&
155 {
156 if (Object* prev = ice::exchange(_ptr, nullptr); prev != nullptr)
157 {
158 prev->rc_sub(RCPassKey{});
159 }
160
161 _ptr = other.raw_ptr()->rc_add(RCPassKey{});
162 ICE_ASSERT_CORE(_ptr == nullptr || _ptr->rc_unclaimed(RCPassKey{}) == false);
163 return *this;
164 }
165
167
168 template<typename Object> requires ice::concepts::IsRefCounted<Object>
169 inline Ptr<Object const>::~Ptr() noexcept
170 {
171 if (_ptr != nullptr)
172 {
173 _ptr->rc_sub(RCPassKey{});
174 }
175 }
176
177 template<typename Object> requires ice::concepts::IsRefCounted<Object>
178 inline Ptr<Object const>::Ptr(std::nullptr_t) noexcept
179 : _ptr{ nullptr }
180 {
181 }
182
183 template<typename Object> requires ice::concepts::IsRefCounted<Object>
184 inline Ptr<Object const>::Ptr(Ptr const& other) noexcept
185 : _ptr{ other._ptr->rc_add(RCPassKey{}) }
186 {
187 }
188
189 template<typename Object> requires ice::concepts::IsRefCounted<Object>
190 inline auto Ptr<Object const>::operator=(Ptr const& other) noexcept -> Ptr&
191 {
192 if (this != ice::addressof(other))
193 {
194 if (Object* prev = ice::exchange(_ptr, nullptr); prev != nullptr)
195 {
196 prev->rc_sub(RCPassKey{});
197 }
198
199 _ptr = other._ptr->rc_add(RCPassKey{});
200 ICE_ASSERT_CORE(_ptr == nullptr || _ptr->rc_unclaimed(RCPassKey{}) == false);
201 }
202 return *this;
203 }
204
205 template<typename Object> requires ice::concepts::IsRefCounted<Object>
206 inline Ptr<Object const>::Ptr(Ptr<Object> const& other) noexcept
207 : _ptr{ other->rc_add(RCPassKey{}) }
208 {
209 }
210
211 template<typename Object> requires ice::concepts::IsRefCounted<Object>
212 inline auto Ptr<Object const>::operator=(Ptr<Object> const& other) noexcept -> Ptr&
213 {
214 if (Object* prev = ice::exchange(_ptr, nullptr); prev != nullptr)
215 {
216 prev->rc_sub(RCPassKey{});
217 }
218
219 _ptr = other->rc_add(RCPassKey{});
220 ICE_ASSERT_CORE(_ptr == nullptr || _ptr->rc_unclaimed(RCPassKey{}) == false);
221 return *this;
222 }
223
224 template<typename Object> requires ice::concepts::IsRefCounted<Object>
225 inline Ptr<Object const>::Ptr(Ptr&& other) noexcept
226 : _ptr{ std::exchange(other._ptr, nullptr) }
227 {
228 ICE_ASSERT_CORE(_ptr == nullptr || _ptr->rc_unclaimed(RCPassKey{}) == false);
229 }
230
231 template<typename Object> requires ice::concepts::IsRefCounted<Object>
232 inline auto Ptr<Object const>::operator=(Ptr&& other) noexcept -> Ptr&
233 {
234 if (this != ice::addressof(other))
235 {
236 if (Object* prev = ice::exchange(_ptr, nullptr); prev != nullptr)
237 {
238 prev->rc_sub(RCPassKey{});
239 }
240
241 _ptr = ice::exchange(other._ptr, nullptr);
242 ICE_ASSERT_CORE(_ptr == nullptr || _ptr->rc_unclaimed(RCPassKey{}) == false);
243 }
244 return *this;
245 }
246
247 template<typename Object> requires ice::concepts::IsRefCounted<Object>
248 inline Ptr<Object const>::Ptr(Ptr<Object>&& other) noexcept
249 : _ptr{ std::exchange(other._ptr, nullptr) }
250 {
251 ICE_ASSERT_CORE(_ptr == nullptr || _ptr->rc_unclaimed(RCPassKey{}) == false);
252 }
253
254 template<typename Object> requires ice::concepts::IsRefCounted<Object>
255 inline auto Ptr<Object const>::operator=(Ptr<Object>&& other) noexcept -> Ptr&
256 {
257 if (this != ice::addressof(other))
258 {
259 if (Object* prev = ice::exchange(_ptr, nullptr); prev != nullptr)
260 {
261 prev->rc_sub(RCPassKey{});
262 }
263
264 _ptr = ice::exchange(other._ptr, nullptr);
265 ICE_ASSERT_CORE(_ptr == nullptr || _ptr->rc_unclaimed(RCPassKey{}) == false);
266 }
267 return *this;
268 }
269
270 template<typename Object> requires ice::concepts::IsRefCounted<Object>
271 template<typename Derived> requires std::is_base_of_v<Object, Derived>
272 inline auto Ptr<Object const>::operator=(Ptr<Derived const> const& other) noexcept -> Ptr&
273 {
274 if (Object* prev = ice::exchange(_ptr, nullptr); prev != nullptr)
275 {
276 prev->rc_sub(RCPassKey{});
277 }
278
279 _ptr = other.raw_ptr()->rc_add(RCPassKey{});
280 ICE_ASSERT_CORE(_ptr == nullptr || _ptr->rc_unclaimed(RCPassKey{}) == false);
281 return *this;
282 }
283
284} // namespace ice
#define ICE_ASSERT_CORE(expression)
Definition assert_core.hxx:43
auto raw_ptr() const noexcept -> Object const *
Definition ptr.hxx:66
auto operator->() const noexcept -> Object const *
Definition ptr.hxx:68
auto operator==(std::nullptr_t) const noexcept -> bool
Definition ptr.hxx:70
Ptr(std::nullptr_t=nullptr) noexcept
Definition ptr.hxx:12
auto operator==(this Self const &self, std::nullptr_t) noexcept -> bool
Definition ptr.hxx:38
Ptr(std::nullptr_t=nullptr) noexcept
Definition ptr.hxx:88
auto operator=(Ptr const &other) noexcept -> Ptr &
Definition ptr.hxx:106
auto operator->(this Self &self) noexcept
Definition ptr.hxx:35
~Ptr() noexcept
Definition ptr.hxx:79
auto raw_ptr(this Self &self) noexcept -> Object *
Definition ptr.hxx:32
Definition refcounted.hxx:82
Definition refcounted.hxx:28
SPDX-License-Identifier: MIT.
Definition array.hxx:12
@ Object
Definition config_types.hxx:30