MGL(Win32)
読み取り中…
検索中…
一致する文字列を見つけられません
mgl_unique_ptr.h
[詳解]
1// SPDX-License-Identifier: Zlib
2/* ------------------------------------------------------------------------- */
9/* ------------------------------------------------------------------------- */
10
11#ifndef INCGUARD_MGL_UNIQUE_PTR_H_1743858098
12#define INCGUARD_MGL_UNIQUE_PTR_H_1743858098
13
14#include <memory>
15#include <type_traits>
16
19
20namespace MGL
21{
22/* ------------------------------------------------------------------------- */
27/* ------------------------------------------------------------------------- */
28template <class T>
30{
31public:
32 /* ------------------------------------------------------------------------- */
36 /* ------------------------------------------------------------------------- */
37 constexpr UniquePtr() noexcept
38 : _ptr(nullptr)
39 {
40 }
41
42 // コピーは禁止
43 UniquePtr(UniquePtr &) = delete;
44 UniquePtr &operator=(UniquePtr &) = delete;
45
46 /* ------------------------------------------------------------------------- */
51 /* ------------------------------------------------------------------------- */
52 UniquePtr(UniquePtr &&rhs) noexcept
53 {
54 Delete();
55 _ptr = rhs._ptr; // NOLINT(cppcoreguidelines-prefer-member-initializer) : Delete()が呼べなくなるので無理
56 rhs._ptr = nullptr;
57 }
58
59 /* ------------------------------------------------------------------------- */
64 /* ------------------------------------------------------------------------- */
65 UniquePtr &operator=(UniquePtr &&rhs) noexcept
66 {
67 Delete();
68 _ptr = rhs._ptr;
69 rhs._ptr = nullptr;
70 return *this;
71 }
72
73 /* ------------------------------------------------------------------------- */
77 /* ------------------------------------------------------------------------- */
78 ~UniquePtr() noexcept
79 {
80 Delete();
81 }
82
83 /* ------------------------------------------------------------------------- */
90 /* ------------------------------------------------------------------------- */
91 template <class U = T, class... Args>
92 UniquePtr &New(Args &&...args) noexcept
93 {
94 // TとUが異なる型、かつ継承関係に無い場合は生成できない
95 if constexpr (std::is_class_v<T> && !std::is_same_v<T, U>)
96 {
97 static_assert(std::is_base_of_v<T, U>, "Cannot be converted to the specified type.");
98 }
99
100 Delete();
101 _ptr = Allocate<U>(std::forward<Args>(args)...);
102 return *this;
103 }
104
105 /* ------------------------------------------------------------------------- */
113 /* ------------------------------------------------------------------------- */
114 template <class U = T, class Initializer, class... Args>
115 UniquePtr &InitNew(Initializer initializer, Args &&...args) noexcept
116 {
117 // TとUが異なる型、かつ継承関係に無い場合は生成できない
118 if constexpr (std::is_class_v<T> && !std::is_same_v<T, U>)
119 {
120 static_assert(std::is_base_of_v<T, U>, "Cannot be converted to the specified type.");
121 }
122
123 // 既存のオブジェクトを削除して再生成
124 Delete();
125 auto obj = Allocate<U>(std::forward<Args>(args)...);
126
127 // オブジェクトが生成されていれば初期化関数を呼び出し
128 if (obj != nullptr)
129 {
130 if (!InvokeInitializer(initializer, *obj))
131 {
132 std::destroy_at(obj);
133 MGL::Memory::Deallocate(obj);
134 obj = nullptr;
135 }
136 }
137 _ptr = obj;
138 return *this;
139 }
140
141 /* ------------------------------------------------------------------------- */
145 /* ------------------------------------------------------------------------- */
146 void Delete() noexcept
147 {
148 if (_ptr != nullptr)
149 {
150 std::destroy_at(_ptr);
151 MGL::Memory::Deallocate(_ptr);
152 _ptr = nullptr;
153 }
154 }
155
156 /* ------------------------------------------------------------------------- */
161 /* ------------------------------------------------------------------------- */
162 [[nodiscard]] constexpr T *Get() const noexcept
163 {
164 return _ptr;
165 }
166
167 /* ------------------------------------------------------------------------- */
172 /* ------------------------------------------------------------------------- */
173 [[nodiscard]] constexpr T *operator->() const noexcept
174 {
175 return _ptr;
176 }
177
178
179 /* ------------------------------------------------------------------------- */
184 /* ------------------------------------------------------------------------- */
185 [[nodiscard]] constexpr std::add_lvalue_reference_t<T> operator*() const noexcept
186 {
187 return *_ptr;
188 }
189
190 /* ------------------------------------------------------------------------- */
196 /* ------------------------------------------------------------------------- */
197 [[nodiscard]] constexpr bool IsNull() const noexcept
198 {
199 return _ptr == nullptr;
200 }
201
202 /* ------------------------------------------------------------------------- */
208 /* ------------------------------------------------------------------------- */
209 [[nodiscard]] constexpr bool operator!() const noexcept
210 {
211 return _ptr == nullptr;
212 }
213
214 /* ------------------------------------------------------------------------- */
220 /* ------------------------------------------------------------------------- */
221 [[nodiscard]] explicit constexpr operator bool() const noexcept
222 {
223 return _ptr != nullptr;
224 }
225
226 /* ------------------------------------------------------------------------- */
233 /* ------------------------------------------------------------------------- */
234 template <class U = T, class... Args>
235 [[nodiscard]] static UniquePtr Make(Args &&...args) noexcept
236 {
237 // TとUが異なる型、かつ継承関係に無い場合は生成できない
238 if constexpr (std::is_class_v<T> && !std::is_same_v<T, U>)
239 {
240 static_assert(std::is_base_of_v<T, U>, "Cannot be converted to the specified type.");
241 }
242
243 return UniquePtr(Allocate<U>(std::forward<Args>(args)...));
244 }
245
246 /* ------------------------------------------------------------------------- */
253 /* ------------------------------------------------------------------------- */
254 template <class U = T, class Initializer, class... Args>
255 [[nodiscard]] static UniquePtr InitMake(Initializer initializer, Args &&...args) noexcept
256 {
257 // TとUが異なる型、かつ継承関係に無い場合は生成できない
258 if constexpr (std::is_class_v<T> && !std::is_same_v<T, U>)
259 {
260 static_assert(std::is_base_of_v<T, U>, "Cannot be converted to the specified type.");
261 }
262
263 // オブジェクトを生成して初期化関数を呼び出し
264 auto obj = Allocate<U>(std::forward<Args>(args)...);
265 if (obj != nullptr)
266 {
267 if (!InvokeInitializer(initializer, *obj))
268 {
269 std::destroy_at(obj);
270 MGL::Memory::Deallocate(obj);
271 obj = nullptr;
272 }
273 }
274
275 return UniquePtr(obj);
276 }
277
278 /* ------------------------------------------------------------------------- */
283 /* ------------------------------------------------------------------------- */
284 std::shared_ptr<T> MoveSharedPtr()
285 {
286 // シェアードポインタへ渡すデリータ
287 auto deleter = [](T *ptr) constexpr
288 {
289 if (ptr != nullptr)
290 {
291 std::destroy_at(ptr);
292 MGL::Memory::Deallocate(ptr);
293 }
294 };
295
296 // シェアードポインタに渡すアロケータ
297 const STL::Allocator<void> allocator;
298
299 // デリータとアロケータを使用するシェアードポインタに渡して、自身はnullptrに
300 auto sharedPtr = std::shared_ptr<T>(_ptr, deleter, allocator);
301 _ptr = nullptr;
302
303 return sharedPtr;
304 }
305
306private:
307 /* ------------------------------------------------------------------------- */
312 /* ------------------------------------------------------------------------- */
313 constexpr UniquePtr(T *ptr) noexcept
314 : _ptr(ptr)
315 {
316 }
317
318 /* ------------------------------------------------------------------------- */
324 /* ------------------------------------------------------------------------- */
325 template <class U, class... Args>
326 [[nodiscard]] static U *Allocate(Args &&...args) noexcept
327 {
328 // クラスオブジェクトを生成
329 auto *ptr = MGL::Memory::Allocate(sizeof(U));
330 if (ptr == nullptr)
331 {
332 return nullptr;
333 }
334
335 // 例外なし
336 if constexpr (std::is_nothrow_constructible_v<U, Args...>)
337 {
338 return new (ptr) U(std::forward<Args>(args)...);
339 }
340 // 例外あり
341 else
342 {
343 try
344 {
345 return new (ptr) U(std::forward<Args>(args)...);
346 }
347 catch (...)
348 {
350 }
351 }
352
353 return nullptr;
354 }
355
356 /* ------------------------------------------------------------------------- */
364 /* ------------------------------------------------------------------------- */
365 template <class U, class Initializer>
366 static bool InvokeInitializer(Initializer initializer, U &obj) noexcept
367 {
368 // 関数がbool型の戻り値を返す場合はその結果を返す
369 if constexpr (std::is_invocable_r_v<bool, decltype(initializer), U &>)
370 {
371 return initializer(obj);
372 }
373 // 関数の戻り値がvoidなら常にtrue
374 else if constexpr (std::is_invocable_r_v<void, decltype(initializer), U &>)
375 {
376 initializer(obj);
377 return true;
378 }
379 // それ以外は不適格
380 else
381 {
382 static_assert(std::false_type::value, "Initializer must be U& type argument and bool or void value returns.");
383 return false;
384 }
385 }
386
388 T *_ptr{nullptr};
389};
390
391
392// 配列は扱えない
393template <class T>
394class UniquePtr<T[]>
395{
396 static_assert(false, "MGL::UniquePtr cannot specification array type.");
397};
398
399// サイズ付きの配列も扱えない
400template <class T, size_t n>
401class UniquePtr<T[n]>
402{
403 static_assert(false, "MGL::UniquePtr cannot specification sized array type.");
404};
405} // namespace MGL
406
407#endif // INCGUARD_MGL_UNIQUE_PTR_H_1743858098
408
409// vim: et ts=4 sw=4 sts=4
STL用アロケータ
Definition mgl_stl_memory.h:24
ユニークポインタ
Definition mgl_unique_ptr.h:30
UniquePtr(UniquePtr &&rhs) noexcept
ムーブコンストラクタ
Definition mgl_unique_ptr.h:52
~UniquePtr() noexcept
デストラクタ
Definition mgl_unique_ptr.h:78
static UniquePtr InitMake(Initializer initializer, Args &&...args) noexcept
新たなクラスオブジェクトの生成
Definition mgl_unique_ptr.h:255
UniquePtr & InitNew(Initializer initializer, Args &&...args) noexcept
初期化付きのクラスオブジェクトの生成
Definition mgl_unique_ptr.h:115
constexpr bool IsNull() const noexcept
保持しているポインタがNULLであるかをチェック
Definition mgl_unique_ptr.h:197
void Delete() noexcept
オブジェクトの削除
Definition mgl_unique_ptr.h:146
UniquePtr & New(Args &&...args) noexcept
オブジェクトを生成
Definition mgl_unique_ptr.h:92
constexpr T * operator->() const noexcept
演算子によるポインタへのアクセス
Definition mgl_unique_ptr.h:173
constexpr std::add_lvalue_reference_t< T > operator*() const noexcept
演算子によるポインタの間接参照
Definition mgl_unique_ptr.h:185
constexpr bool operator!() const noexcept
保持しているポインタが無効であるかを取得
Definition mgl_unique_ptr.h:209
static UniquePtr Make(Args &&...args) noexcept
新たなクラスオブジェクトの生成
Definition mgl_unique_ptr.h:235
constexpr UniquePtr() noexcept
コンストラクタ
Definition mgl_unique_ptr.h:37
constexpr T * Get() const noexcept
ポインタを取得
Definition mgl_unique_ptr.h:162
UniquePtr & operator=(UniquePtr &&rhs) noexcept
演算子によるムーブ
Definition mgl_unique_ptr.h:65
std::shared_ptr< T > MoveSharedPtr()
シェアードポインタへのムーブ
Definition mgl_unique_ptr.h:284
MGL メモリ関連
void Deallocate(void *buffer) noexcept
デアロケート
Definition mgl_memory.cc:118
MGL STLのメモリ関連の代替