KisaragiLibrary
 
読み取り中…
検索中…
一致する文字列を見つけられません
RangeNum.hpp
[詳解]
1#pragma once
2
3/**
4 * @file RangeNum.hpp
5 * @brief 範囲指定の値型を提供します。
6 * @author 樺澤陽向
7 * @date 2025/05/07
8 * @since 1.0.0
9 */
10
11#include <cassert>
12#include <cmath>
14
15namespace Kisaragi_Lib
16{
17 /// <summary>
18 /// 範囲外の入力された値をどのように扱うかを決定するPolicyのベース型
19 /// </summary>
20 /// @since 1.0.0
21 struct IOutOfRange{};
22
23 /// <summary>
24 /// 範囲外が与えられたら即座に終了
25 /// </summary>
26 /// @since 1.0.0
28 {
29 template<typename T>
30 static void Handle(const T& _value, const T& _min, const T& _max)
31 {
32 assert((_value < _min || _value > _max) && "RangeNum: 値が範囲外です");
33 }
34 };
35
36 /// <summary>
37 /// 範囲外が与えられたら近い範囲内に自動修正
38 /// </summary>
39 /// @since 1.0.0
41 {
42 template<typename T>
43 static void Handle(T& _value, const T& _min, const T& _max)
44 {
45 if (_value < _min)
46 {
47 _value = _min;
48 }
49 else if (_value > _max)
50 {
51 _value = _max;
52 }
53 }
54 };
55
56 /// <summary>
57 /// 範囲外が与えられたら警告のみ出力
58 /// </summary>
59 /// @since 1.0.0
61 {
62 template<typename T>
63 static void Handle(const T& _value, const T& _min, const T& _max)
64 {
65 if (_value < _min || _value > _max)
66 {
67 Debug::PrintAssertStatic( "Warning: 範囲外の値 " + _value + " が渡されました");
68 }
69 }
70 };
71
72 /// <summary>
73 /// 範囲外が与えられたらループした値に戻す
74 /// </summary>
75 /// @since 1.1.1
77 {
78 template<typename T,
79 std::enable_if_t<std::is_integral<T>::value,int> = 0>
80 static void Handle(T& _value, const T& _min, const T& _max)
81 {
82 T range = _max - _min + 1; // 範囲の幅 (max含む場合)
83
84 if (range <= 0)
85 {
86 return; // 範囲がおかしい場合は処理しない
87 }
88
89 auto positive_mod = [](T a, T b) -> T
90 {
91 T r = a % b;
92 return (r < 0) ? r + b : r;
93 };
94
95 // _value を _min から始まる範囲内にループさせる
96 _value = positive_mod(_value - _min, range) + _min;
97 }
98
99 template<typename T,
100 std::enable_if_t<std::is_floating_point_v<T>,int> = 0>
101 static void Handle(T& _value, const T& _min, const T& _max)
102 {
103 T range = _max - _min;
104 if (range <= 0) return;
105
106 T offset = std::fmod(_value - _min, range);
107 if (offset < 0)
108 offset += range;
109
110 _value = _min + offset;
111 }
112 };
113
114
115 /// <summary>
116 /// 特定範囲の値を管理するための数値型
117 /// </summary>
118 /// <typeparam name="T">値型の型</typeparam>
119 /// <typeparam name="Policy">IOutOfRange派生型</typeparam>
120 /// @since 1.0.0
121 template<typename T, typename Policy>
123 {
124 // Tが値型か検証
125 static_assert(std::is_arithmetic<T>::value, "RangeNum には数値型を渡してください");
126
127 // Policy が IOutOfRange の派生型であることを検証
128 static_assert(std::is_base_of<IOutOfRange, Policy>::value, "Policy は IOutOfRange の派生型でなくてはなりません");
129
130 // IOutOfRangeを渡されていないか確認
131 static_assert(!std::is_same<IOutOfRange, Policy>::value, "Policy に IOutOfRange を渡すことはできません");
132
133 private:
134 /// <summary>
135 /// 値
136 /// </summary>
138
139 /// <summary>
140 /// 最小値
141 /// </summary>
143
144 /// <summary>
145 /// 最大値
146 /// </summary>
148
149 // 値をチェックして設定
150 void Assign(T& _v)
151 {
152 Policy::Handle(_v, MIN, MAX);
153 value = _v;
154 }
155
156 public:
157 // コンストラクタ
158 RangeNum(T min, T max) : MIN(min), MAX(max), value(min)
159 {
160 assert(MIN <= MAX && "RangeNum : MINの値がMAX以上です。");
161 }
162
163 // 値型から直接構築
164 RangeNum(T min, T max, T init) : MIN(min), MAX(max)
165 {
166 assert(MIN <= MAX && "RangeNum : MINの値がMAX以上です。");
167 Assign(init);
168 }
169
170 // コピーコンストラクタ
171 RangeNum(const RangeNum& other) = default;
172
173 // 暗黙変換:T に変換できる(get() の代わり)
174 operator T() const { return value; }
175
177 {
178 Assign(_rhs);
179 return *this;
180 }
181
182
183 // 四則演算(RangeNum + T)
184 RangeNum operator+(const T& _rhs) const {
185 return RangeNum(MIN, MAX, Checked(value + _rhs));
186 }
187
188 RangeNum operator-(const T& _rhs) const {
189 return RangeNum(MIN, MAX, Checked(value - _rhs));
190 }
191
192 RangeNum operator*(const T& _rhs) const {
193 return RangeNum(MIN, MAX, Checked(value * _rhs));
194 }
195
196 RangeNum operator/(const T& _rhs) const {
197 return RangeNum(MIN, MAX, Checked(value / _rhs));
198 }
199
200 // 代入演算子
201 RangeNum& operator+=(const T& _rhs) {
202 Assign(value + _rhs);
203 return *this;
204 }
205
206 RangeNum& operator-=(const T& _rhs) {
207 Assign(value - _rhs);
208 return *this;
209 }
210
211 RangeNum& operator*=(const T& _rhs) {
212 Assign(value * _rhs);
213 return *this;
214 }
215
216 RangeNum& operator/=(const T& _rhs) {
217 Assign(value / _rhs);
218 return *this;
219 }
220
221 // 比較演算子
222 bool operator==(const RangeNum& _rhs) const { return value == _rhs.value; }
223 bool operator!=(const RangeNum& _rhs) const { return value != _rhs.value; }
224 bool operator<(const RangeNum& _rhs) const { return value < _rhs.value; }
225 bool operator<=(const RangeNum& _rhs) const { return value <= _rhs.value; }
226 bool operator>(const RangeNum& _rhs) const { return value > _rhs.value; }
227 bool operator>=(const RangeNum& _rhs) const { return value >= _rhs.value; }
228
229 // 値型との比較
230 bool operator==(const T& _rhs) const { return value == _rhs; }
231 bool operator!=(const T& _rhs) const { return value != _rhs; }
232 bool operator<(const T& _rhs) const { return value < _rhs; }
233 bool operator<=(const T& _rhs) const { return value <= _rhs; }
234 bool operator>(const T& _rhs) const { return value > _rhs; }
235 bool operator>=(const T& _rhs) const { return value >= _rhs; }
236
237 private:
238 // 値チェック付き値返却
239 T Checked(T& _result)
240 {
241 Policy::Handle(_result, MIN, MAX);
242 return _result;
243 }
244 };
245}
DebugConsole操作クラス
static void PrintAssertStatic(const std::string _in)
エラー出力用コンソール出力(文字色しか変わらない)
Definition Debug.cpp:152
bool operator>=(const T &_rhs) const
Definition RangeNum.hpp:235
RangeNum operator-(const T &_rhs) const
Definition RangeNum.hpp:188
RangeNum operator*(const T &_rhs) const
Definition RangeNum.hpp:192
bool operator<=(const T &_rhs) const
Definition RangeNum.hpp:233
bool operator<(const T &_rhs) const
Definition RangeNum.hpp:232
void Assign(T &_v)
Definition RangeNum.hpp:150
RangeNum(T min, T max)
Definition RangeNum.hpp:158
bool operator>(const T &_rhs) const
Definition RangeNum.hpp:234
RangeNum(T min, T max, T init)
Definition RangeNum.hpp:164
RangeNum(const RangeNum &other)=default
RangeNum & operator-=(const T &_rhs)
Definition RangeNum.hpp:206
RangeNum & operator*=(const T &_rhs)
Definition RangeNum.hpp:211
bool operator>=(const RangeNum &_rhs) const
Definition RangeNum.hpp:227
RangeNum operator+(const T &_rhs) const
Definition RangeNum.hpp:184
RangeNum operator/(const T &_rhs) const
Definition RangeNum.hpp:196
bool operator==(const T &_rhs) const
Definition RangeNum.hpp:230
RangeNum & operator/=(const T &_rhs)
Definition RangeNum.hpp:216
bool operator<=(const RangeNum &_rhs) const
Definition RangeNum.hpp:225
RangeNum operator=(T _rhs)
Definition RangeNum.hpp:176
bool operator<(const RangeNum &_rhs) const
Definition RangeNum.hpp:224
T Checked(T &_result)
Definition RangeNum.hpp:239
RangeNum & operator+=(const T &_rhs)
Definition RangeNum.hpp:201
bool operator==(const RangeNum &_rhs) const
Definition RangeNum.hpp:222
bool operator!=(const T &_rhs) const
Definition RangeNum.hpp:231
bool operator>(const RangeNum &_rhs) const
Definition RangeNum.hpp:226
bool operator!=(const RangeNum &_rhs) const
Definition RangeNum.hpp:223
Definition Accessor.hpp:110
範囲外が与えられたら近い範囲内に自動修正
Definition RangeNum.hpp:41
static void Handle(T &_value, const T &_min, const T &_max)
Definition RangeNum.hpp:43
範囲外の入力された値をどのように扱うかを決定するPolicyのベース型
Definition RangeNum.hpp:21
範囲外が与えられたら警告のみ出力
Definition RangeNum.hpp:61
static void Handle(const T &_value, const T &_min, const T &_max)
Definition RangeNum.hpp:63
範囲外が与えられたらループした値に戻す
Definition RangeNum.hpp:77
static void Handle(T &_value, const T &_min, const T &_max)
Definition RangeNum.hpp:80
範囲外が与えられたら即座に終了
Definition RangeNum.hpp:28
static void Handle(const T &_value, const T &_min, const T &_max)
Definition RangeNum.hpp:30