MGL(Win32)
読み取り中…
検索中…
一致する文字列を見つけられません
mgl_array_2d.h
[詳解]
1// SPDX-License-Identifier: Zlib
2/* ------------------------------------------------------------------------- */
9/* ------------------------------------------------------------------------- */
10
11#ifndef INCGUARD_MGL_ARRAY_2D_H_1746562234
12#define INCGUARD_MGL_ARRAY_2D_H_1746562234
13
14#include <memory>
15#include <type_traits>
16#include <utility>
17
20#include <mgl/memory/mgl_memory_utility.h>
22
23namespace MGL
24{
25/* ------------------------------------------------------------------------- */
30/* ------------------------------------------------------------------------- */
31template <class ValueType, class IndexType = size_t>
33{
34public:
35 // 配列の要素はデフォルト構築可能でなければならない
36 static_assert(std::is_default_constructible_v<ValueType>, "Array2D element must be constructible by default.");
37
38 // インデックスは整数型である必要がある
39 static_assert(std::is_integral_v<IndexType>, "IndexType must be integral value.");
40
41 // コピーは禁止
42 Array2D(Array2D &) = delete;
43 Array2D &operator=(Array2D &) = delete;
44
45 /* ------------------------------------------------------------------------- */
50 /* ------------------------------------------------------------------------- */
51 Array2D(Memory::ClearMode clearMode = Memory::ClearMode::Auto) noexcept
52 : Array2D(0, 0, clearMode)
53 {
54 }
55
56 /* ------------------------------------------------------------------------- */
63 /* ------------------------------------------------------------------------- */
64 Array2D(IndexType width, IndexType height, Memory::ClearMode clearMode = Memory::ClearMode::Auto) noexcept
65 {
66 Allocate(width, height, clearMode);
67 }
68
69 /* ------------------------------------------------------------------------- */
77 /* ------------------------------------------------------------------------- */
78 Array2D(IndexType width, IndexType height, const ValueType &invalidValue, Memory::ClearMode clearMode = Memory::ClearMode::Auto) noexcept
79 {
80 Allocate(width, height, clearMode);
81 SetInvalidValue(invalidValue);
82 }
83
84 /* ------------------------------------------------------------------------- */
92 /* ------------------------------------------------------------------------- */
93 Array2D(IndexType width, IndexType height, ValueType &&invalidValue, Memory::ClearMode clearMode = Memory::ClearMode::Auto) noexcept
94 {
95 Allocate(width, height, clearMode);
96 SetInvalidValue(std::move(invalidValue));
97 }
98
99 /* ------------------------------------------------------------------------- */
104 /* ------------------------------------------------------------------------- */
105 Array2D(Array2D &&rhs) noexcept
106 {
107 *this = std::move(rhs);
108 }
109
110 /* ------------------------------------------------------------------------- */
115 /* ------------------------------------------------------------------------- */
116 Array2D &operator=(Array2D &&rhs) noexcept
117 {
118 Deallocate();
119
120 // NOLINTBEGIN(cppcoreguidelines-prefer-member-initializer) : 上のDeallocate()が呼べなくなるので無理
121 _width = rhs._width;
122 _height = rhs._height;
123 _arraySize = rhs._arraySize;
124 _top = rhs._top;
125 _tail = rhs._tail;
126 // NOLINTEND(cppcoreguidelines-prefer-member-initializer)
127
128 rhs._width = 0;
129 rhs._height = 0;
130 rhs._arraySize = 0;
131 rhs._top = nullptr;
132 rhs._tail = nullptr;
133
134 return *this;
135 }
136
137 /* ------------------------------------------------------------------------- */
141 /* ------------------------------------------------------------------------- */
142 ~Array2D() noexcept
143 {
144 Deallocate();
145 }
146
147 /* ------------------------------------------------------------------------- */
156 /* ------------------------------------------------------------------------- */
157 bool New(size_t width, size_t height, Memory::ClearMode clearMode = Memory::ClearMode::Auto) noexcept
158 {
159 // 末尾(無効値)が存在している場合はそれを保つように生成
160 if (_tail != nullptr)
161 {
162 auto invalidValue = std::move(*_tail); // アロケート中に消えるので別のメモリ空間に移動しておく
163 if (Allocate(width, height, clearMode))
164 {
165 SetInvalidValue(invalidValue);
166 return true;
167 }
168 return false;
169 }
170 // 末尾が存在していない場合は普通に生成
171 else
172 {
173 // Note: 実はここには到達しない(コンストラクタがアロケートして無効値も生成されるため)
174 return Allocate(width, height, clearMode);
175 }
176 }
177
178 /* ------------------------------------------------------------------------- */
185 /* ------------------------------------------------------------------------- */
186 bool Renew(Memory::ClearMode clearMode = Memory::ClearMode::Auto) noexcept
187 {
188 return New(_width, _height, clearMode);
189 }
190
191 /* ------------------------------------------------------------------------- */
196 /* ------------------------------------------------------------------------- */
197 constexpr void Fill(const ValueType &value) noexcept
198 {
199 for (auto *e = begin(); e != end(); e++)
200 {
201 *e = value;
202 }
203 }
204
205 /* ------------------------------------------------------------------------- */
212 /* ------------------------------------------------------------------------- */
213 [[nodiscard]] static constexpr std::pair<IndexType, IndexType> MakePair(IndexType x, IndexType y) noexcept
214 {
215 return {x, y};
216 }
217
218 /* ------------------------------------------------------------------------- */
225 /* ------------------------------------------------------------------------- */
226 [[nodiscard]] constexpr const ValueType &Get(IndexType x, IndexType y) const noexcept
227 {
228 return _top[GetIndex(x, y)];
229 }
230
231 /* ------------------------------------------------------------------------- */
237 /* ------------------------------------------------------------------------- */
238 [[nodiscard]] const ValueType &Get(const std::pair<IndexType, IndexType> &pair) const noexcept
239 {
240 return Get(pair.first, pair.second);
241 }
242
243#if __cplusplus >= 202211L // 添字演算子の多次元サポートはC++23以降で利用可能
244 /* ------------------------------------------------------------------------- */
251 /* ------------------------------------------------------------------------- */
252 [[nodiscard]] const ValueType &operator[](IndexType x, IndexType y) const noexcept
253 {
254 return Get(x, y);
255 }
256#endif
257
258 /* ------------------------------------------------------------------------- */
264 /* ------------------------------------------------------------------------- */
265 [[nodiscard]] const ValueType &operator[](const std::pair<IndexType, IndexType> &pair) const noexcept
266 {
267 return Get(pair.first, pair.second);
268 }
269
270 /* ------------------------------------------------------------------------- */
277 /* ------------------------------------------------------------------------- */
278 [[nodiscard]] constexpr ValueType *GetPtr(IndexType x, IndexType y) const noexcept
279 {
280 auto index = GetIndex(x, y);
281 if (index >= _arraySize)
282 {
283 return nullptr;
284 }
285
286 return &_top[index];
287 }
288
289 /* ------------------------------------------------------------------------- */
295 /* ------------------------------------------------------------------------- */
296 [[nodiscard]] constexpr ValueType *GetPtr(const std::pair<IndexType, IndexType> &pair) const noexcept
297 {
298 return GetPtr(pair.first, pair.second);
299 }
300
301 /* ------------------------------------------------------------------------- */
307 /* ------------------------------------------------------------------------- */
308 template <class LoopBody>
309 constexpr void ForEach(LoopBody body) noexcept
310 {
311 for (IndexType y = 0; y < _height; ++y)
312 {
313 for (IndexType x = 0; x < _width; ++x)
314 {
315 if (!InvokeLoopBody(body, x, y))
316 {
317 return;
318 }
319 }
320 }
321 }
322
323 /* ------------------------------------------------------------------------- */
329 /* ------------------------------------------------------------------------- */
330 template <class LoopBody>
331 constexpr void ForEach(LoopBody body) const noexcept
332 {
333 for (IndexType y = 0; y < _height; ++y)
334 {
335 for (IndexType x = 0; x < _width; ++x)
336 {
337 if (!InvokeLoopBody(body, x, y))
338 {
339 return;
340 }
341 }
342 }
343 }
344
345 /* ------------------------------------------------------------------------- */
355 /* ------------------------------------------------------------------------- */
356 template <class LoopBody>
357 constexpr void ForRange(IndexType beginX, IndexType beginY, IndexType endX, IndexType endY, LoopBody body) noexcept
358 {
359 if (_arraySize == 0)
360 {
361 return;
362 }
363
364 Range<IndexType> rangeX(
365 std::clamp(beginX, static_cast<IndexType>(0), GetWidth() - 1),
366 std::clamp(endX, static_cast<IndexType>(0), GetWidth() - 1));
367
368 Range<IndexType> rangeY(
369 std::clamp(beginY, static_cast<IndexType>(0), GetHeight() - 1),
370 std::clamp(endY, static_cast<IndexType>(0), GetHeight() - 1));
371
372 for (auto y = rangeY.Begin(); rangeY.Contains(y); y = rangeY.Next(y))
373 {
374 for (auto x = rangeX.Begin(); rangeX.Contains(x); x = rangeX.Next(x))
375 {
376 if (!InvokeLoopBody(body, x, y))
377 {
378 return;
379 }
380 }
381 }
382 }
383
384 /* ------------------------------------------------------------------------- */
392 /* ------------------------------------------------------------------------- */
393 template <class LoopBody>
394 constexpr void ForRange(
395 const std::pair<IndexType, IndexType> &begin,
396 const std::pair<IndexType, IndexType> &end,
397 LoopBody body) noexcept
398 {
399 ForRange(begin.first, begin.second, end.first, end.second, body);
400 }
401
402 /* ------------------------------------------------------------------------- */
412 /* ------------------------------------------------------------------------- */
413 template <class LoopBody>
414 constexpr void ForRange(IndexType beginX, IndexType beginY, IndexType endX, IndexType endY, LoopBody body) const noexcept
415 {
416 if (_arraySize == 0)
417 {
418 return;
419 }
420
421 Range<IndexType> rangeX(
422 std::clamp(beginX, 0, GetWidth() - 1),
423 std::clamp(endX, 0, GetWidth() - 1));
424
425 Range<IndexType> rangeY(
426 std::clamp(beginY, 0, GetHeight() - 1),
427 std::clamp(endY, 0, GetHeight() - 1));
428
429 for (auto y = rangeY.Begin(); rangeY.Contains(y); y = rangeY.Next(y))
430 {
431 for (auto x = rangeX.Begin(); rangeX.Contains(x); x = rangeX.Next(x))
432 {
433 if (!InvokeLoopBody(body, x, y))
434 {
435 return;
436 }
437 }
438 }
439 }
440
441 /* ------------------------------------------------------------------------- */
449 /* ------------------------------------------------------------------------- */
450 template <class LoopBody>
451 constexpr void ForRange(
452 const std::pair<IndexType, IndexType> &begin,
453 const std::pair<IndexType, IndexType> &end,
454 LoopBody body) const noexcept
455 {
456 ForRange(begin.first, begin.second, end.first, end.second, body);
457 }
458
459 /* ------------------------------------------------------------------------- */
466 /* ------------------------------------------------------------------------- */
467 [[nodiscard]] constexpr bool Contains(const ValueType &element) const noexcept
468 {
469 return Contains(std::addressof(element));
470 }
471
472 /* ------------------------------------------------------------------------- */
479 /* ------------------------------------------------------------------------- */
480 [[nodiscard]] constexpr bool Contains(const ValueType *element) const noexcept
481 {
482 // Note:
483 // ValueType型の実体をを内包するValueType型は作れないはずなので、
484 // 各要素のアドレスと一致するかのチェックは不要なはず。
485
486 auto topAddress = reinterpret_cast<uintptr_t>(_top);
487 auto elemAddress = reinterpret_cast<uintptr_t>(element);
488 auto tailAddress = reinterpret_cast<uintptr_t>(_tail);
489
490 return (topAddress <= elemAddress) && (elemAddress < tailAddress);
491 }
492
493 /* ------------------------------------------------------------------------- */
498 /* ------------------------------------------------------------------------- */
499 constexpr void SetInvalidValue(const ValueType &value) noexcept
500 {
501 if (_tail != nullptr)
502 {
503 *_tail = value;
504 }
505 }
506
507 /* ------------------------------------------------------------------------- */
512 /* ------------------------------------------------------------------------- */
513 constexpr void SetInvalidValue(ValueType &&value) noexcept
514 {
515 if (_tail != nullptr)
516 {
517 *_tail = std::move(value);
518 }
519 }
520
521 /* ------------------------------------------------------------------------- */
526 /* ------------------------------------------------------------------------- */
527 [[nodiscard]] constexpr IndexType GetWidth() const noexcept
528 {
529 return _width;
530 }
531
532 /* ------------------------------------------------------------------------- */
537 /* ------------------------------------------------------------------------- */
538 [[nodiscard]] constexpr IndexType GetHeight() const noexcept
539 {
540 return _height;
541 }
542
543 /* ------------------------------------------------------------------------- */
548 /* ------------------------------------------------------------------------- */
549 [[nodiscard]] constexpr size_t GetArraySize() const noexcept
550 {
551 return _arraySize;
552 }
553
554 /* ------------------------------------------------------------------------- */
559 /* ------------------------------------------------------------------------- */
560 [[nodiscard]] constexpr ValueType *begin() const noexcept
561 {
562 return _top;
563 }
564
565 /* ------------------------------------------------------------------------- */
570 /* ------------------------------------------------------------------------- */
571 [[nodiscard]] constexpr ValueType *end() const noexcept
572 {
573 return _tail;
574 }
575
576 /* ------------------------------------------------------------------------- */
581 /* ------------------------------------------------------------------------- */
582 [[nodiscard]] constexpr const ValueType *cbegin() const noexcept
583 {
584 return _top;
585 }
586
587 /* ------------------------------------------------------------------------- */
592 /* ------------------------------------------------------------------------- */
593 [[nodiscard]] constexpr const ValueType *cend() const noexcept
594 {
595 return _tail;
596 }
597
598private:
599 /* ------------------------------------------------------------------------- */
608 /* ------------------------------------------------------------------------- */
609 bool Allocate(IndexType width, IndexType height, Memory::ClearMode clearMode) noexcept
610 {
611 // IndexTypeが符号付きの場合、負の値を0に補正する
612 if constexpr (std::is_signed_v<IndexType>)
613 {
614 width = std::max(0, width);
615 height = std::max(0, height);
616 }
617
618 // 行または列のサイズに0が指定されている場合はサイズ0の配列とみなす
619 if ((width == 0) || (height == 0))
620 {
621 width = height = 0;
622 }
623 auto arraySize = static_cast<size_t>(width) * static_cast<size_t>(height);
624
625 // 生成済みかつ同サイズであればアロケートを省略
626 if ((_top != nullptr) && (_arraySize == arraySize))
627 {
628 // 全てのデストラクタを呼び出す
629 std::destroy_n(_top, _arraySize + 1);
630
631 // メモリ領域をクリア
632 _top = Memory::Utility::InitializeArrayBuffer<ValueType>(_top, _arraySize + 1, clearMode);
633 }
634 // 未生成、またはサイズが異なる場合は一旦削除して際生成
635 else
636 {
637 // 一旦削除
638 Deallocate();
639
640 // アロケータからメモリを確保
641 const auto size = sizeof(ValueType) * (arraySize + 1);
642 auto *ptr = Memory::Allocate(size);
643 MGL_ASSERT(ptr, "Memory allocation failed.");
644 if (ptr == nullptr)
645 {
646 return false;
647 }
648
649 // メモリ領域をクリア
650 _top = Memory::Utility::InitializeArrayBuffer<ValueType>(ptr, arraySize + 1, clearMode);
651
652 // 確保したメモリリソースをもとに各メンバを初期化
653 _tail = std::addressof(_top[arraySize]);
654 _width = width;
655 _height = height;
656 _arraySize = arraySize;
657 }
658
659 return true;
660 }
661
662 /* ------------------------------------------------------------------------- */
666 /* ------------------------------------------------------------------------- */
667 void Deallocate() noexcept
668 {
669 if (_top != nullptr)
670 {
671 std::destroy_n(_top, _arraySize + 1);
672 Memory::Deallocate(_top);
673 _top = _tail = nullptr;
674 _arraySize = 0;
675 }
676 }
677
678 /* ------------------------------------------------------------------------- */
685 /* ------------------------------------------------------------------------- */
686 [[nodiscard]] constexpr size_t GetIndex(IndexType x, IndexType y) const noexcept
687 {
688 // 符号付きの場合、どちらか一方が負の値だったら失敗
689 if constexpr (std::is_signed_v<IndexType>)
690 {
691 if (x < 0 || y < 0)
692 {
693 return _arraySize;
694 }
695 }
696
697 // どちらか一方が指定サイズより大きければ失敗
698 if (x >= _width)
699 {
700 return _arraySize;
701 }
702 if (y >= _height)
703 {
704 return _arraySize;
705 }
706
707 return static_cast<size_t>(y * _width + x);
708 }
709
710 /* ------------------------------------------------------------------------- */
720 /* ------------------------------------------------------------------------- */
721 template <class LoopBody>
722 constexpr bool InvokeLoopBody(LoopBody body, IndexType x, IndexType y) noexcept
723 {
724 // 座標付き、中断あり
725 if constexpr (std::is_invocable_r_v<bool, decltype(body), IndexType, IndexType, ValueType &>)
726 {
727 return body(x, y, _top[GetIndex(x, y)]);
728 }
729 // 座標付き、中断なし
730 else if constexpr (std::is_invocable_r_v<void, decltype(body), IndexType, IndexType, ValueType &>)
731 {
732 body(x, y, _top[GetIndex(x, y)]);
733 return true;
734 }
735 // 座標なし、中断あり
736 else if constexpr (std::is_invocable_r_v<bool, decltype(body), ValueType &>)
737 {
738 return body(_top[GetIndex(x, y)]);
739 }
740 // 座標なし、中断なし
741 else if constexpr (std::is_invocable_r_v<void, decltype(body), ValueType &>)
742 {
743 body(_top[GetIndex(x, y)]);
744 return true;
745 }
746 // それ以外は不適格
747 else
748 {
749 static_assert(std::false_type::value, "Loop body is not matching arguments.");
750 return false;
751 }
752 }
753
754 /* ------------------------------------------------------------------------- */
764 /* ------------------------------------------------------------------------- */
765 template <class LoopBody>
766 constexpr bool InvokeLoopBody(LoopBody body, IndexType x, IndexType y) const noexcept
767 {
768 // 座標付き、中断あり
769 if constexpr (std::is_invocable_r_v<bool, decltype(body), IndexType, IndexType, const ValueType &>)
770 {
771 return body(x, y, _top[GetIndex(x, y)]);
772 }
773 // 座標付き、中断なし
774 else if constexpr (std::is_invocable_r_v<void, decltype(body), IndexType, IndexType, const ValueType &>)
775 {
776 body(x, y, _top[GetIndex(x, y)]);
777 return true;
778 }
779 // 座標なし、中断あり
780 else if constexpr (std::is_invocable_r_v<bool, decltype(body), const ValueType &>)
781 {
782 return body(_top[GetIndex(x, y)]);
783 }
784 // 座標なし、中断なし
785 else if constexpr (std::is_invocable_r_v<void, decltype(body), const ValueType &>)
786 {
787 body(_top[GetIndex(x, y)]);
788 return true;
789 }
790 // それ以外は不適格
791 else
792 {
793 static_assert(std::false_type::value, "Loop body is not matching arguments.");
794 return false;
795 }
796 }
797
798 IndexType _width{0};
799 IndexType _height{0};
800 size_t _arraySize{0};
801 ValueType *_top{nullptr};
802 ValueType *_tail{nullptr};
803};
804} // namespace MGL
805
806#endif // INCGUARD_MGL_ARRAY_2D_H_1746562234
807
808// vim: et ts=4 sw=4 sts=4
動的2次元配列クラス
Definition mgl_array_2d.h:33
Array2D & operator=(Array2D &&rhs) noexcept
ムーブ代入
Definition mgl_array_2d.h:116
bool Renew(Memory::ClearMode clearMode=Memory::ClearMode::Auto) noexcept
配列を同じサイズで構築し直す
Definition mgl_array_2d.h:186
constexpr ValueType * begin() const noexcept
先頭の要素を取得
Definition mgl_array_2d.h:560
constexpr IndexType GetHeight() const noexcept
配列のY方向の最大値を取得
Definition mgl_array_2d.h:538
static constexpr std::pair< IndexType, IndexType > MakePair(IndexType x, IndexType y) noexcept
ペアの生成
Definition mgl_array_2d.h:213
constexpr const ValueType * cbegin() const noexcept
先頭の要素をconstで取得
Definition mgl_array_2d.h:582
constexpr void ForRange(IndexType beginX, IndexType beginY, IndexType endX, IndexType endY, LoopBody body) noexcept
範囲を指定して要素にアクセス
Definition mgl_array_2d.h:357
constexpr IndexType GetWidth() const noexcept
配列のX方向の最大値を取得
Definition mgl_array_2d.h:527
constexpr size_t GetArraySize() const noexcept
配列全体のサイズを取得
Definition mgl_array_2d.h:549
Array2D(IndexType width, IndexType height, ValueType &&invalidValue, Memory::ClearMode clearMode=Memory::ClearMode::Auto) noexcept
コンストラクタ
Definition mgl_array_2d.h:93
constexpr void ForEach(LoopBody body) const noexcept
全ての要素へ読み取り専用でアクセス
Definition mgl_array_2d.h:331
constexpr void ForRange(const std::pair< IndexType, IndexType > &begin, const std::pair< IndexType, IndexType > &end, LoopBody body) noexcept
範囲を指定して要素にアクセス
Definition mgl_array_2d.h:394
constexpr void Fill(const ValueType &value) noexcept
全ての要素を指定値で書き込む
Definition mgl_array_2d.h:197
constexpr bool Contains(const ValueType *element) const noexcept
指定した要素が範囲内に含まれているかを取得
Definition mgl_array_2d.h:480
constexpr void ForRange(IndexType beginX, IndexType beginY, IndexType endX, IndexType endY, LoopBody body) const noexcept
範囲を指定して読み取り専用で要素にアクセス
Definition mgl_array_2d.h:414
const ValueType & operator[](const std::pair< IndexType, IndexType > &pair) const noexcept
添字演算子による要素の取得
Definition mgl_array_2d.h:265
constexpr void ForRange(const std::pair< IndexType, IndexType > &begin, const std::pair< IndexType, IndexType > &end, LoopBody body) const noexcept
範囲を指定して読み取り専用で要素にアクセス
Definition mgl_array_2d.h:451
constexpr void SetInvalidValue(ValueType &&value) noexcept
無効値の設定
Definition mgl_array_2d.h:513
constexpr ValueType * end() const noexcept
末尾の要素を取得
Definition mgl_array_2d.h:571
constexpr const ValueType * cend() const noexcept
末尾の要素をconstで取得
Definition mgl_array_2d.h:593
~Array2D() noexcept
デストラクタ
Definition mgl_array_2d.h:142
Array2D(Array2D &&rhs) noexcept
ムーブコンストラクタ
Definition mgl_array_2d.h:105
constexpr void SetInvalidValue(const ValueType &value) noexcept
無効値の設定
Definition mgl_array_2d.h:499
constexpr void ForEach(LoopBody body) noexcept
全ての要素へのアクセス
Definition mgl_array_2d.h:309
constexpr bool Contains(const ValueType &element) const noexcept
指定した要素が範囲内に含まれているかを取得
Definition mgl_array_2d.h:467
const ValueType & Get(const std::pair< IndexType, IndexType > &pair) const noexcept
要素の取得
Definition mgl_array_2d.h:238
constexpr ValueType * GetPtr(const std::pair< IndexType, IndexType > &pair) const noexcept
書き込み可能な要素へのポインタを取得
Definition mgl_array_2d.h:296
Array2D(IndexType width, IndexType height, const ValueType &invalidValue, Memory::ClearMode clearMode=Memory::ClearMode::Auto) noexcept
コンストラクタ
Definition mgl_array_2d.h:78
Array2D(Memory::ClearMode clearMode=Memory::ClearMode::Auto) noexcept
コンストラクタ
Definition mgl_array_2d.h:51
bool New(size_t width, size_t height, Memory::ClearMode clearMode=Memory::ClearMode::Auto) noexcept
配列の生成
Definition mgl_array_2d.h:157
Array2D(IndexType width, IndexType height, Memory::ClearMode clearMode=Memory::ClearMode::Auto) noexcept
コンストラクタ
Definition mgl_array_2d.h:64
constexpr const ValueType & Get(IndexType x, IndexType y) const noexcept
要素の取得
Definition mgl_array_2d.h:226
constexpr ValueType * GetPtr(IndexType x, IndexType y) const noexcept
書き込み可能な要素へのポインタを取得
Definition mgl_array_2d.h:278
値の範囲を表現するクラス
Definition mgl_range.h:28
constexpr bool Contains(T value) const noexcept
指定された値が範囲内に含まれているかを取得
Definition mgl_range.h:154
constexpr T Next(T value) const noexcept
指定された値の次の値を取得
Definition mgl_range.h:115
constexpr T Begin() const noexcept
開始値を取得
Definition mgl_range.h:49
ValueType
値のタイプ
Definition mgl_achievement_defs.h:33
MGL メモリ関連
MGL 値の範囲を表現するクラス
MGL デバッグ用マクロ
#define MGL_ASSERT(...)
アサート用マクロ
Definition mgl_system_debug_macro.h:88