1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107 | #pragma once
#include <utility>
#include "numeric/arithmetic.hpp"
namespace uni {
template<class T, T INF, T SUP>
struct static_restrictor {
using restrictor = static_restrictor;
protected:
T _v = INF;
inline void _clamp() noexcept(NO_EXCEPT) { this->_v = std::clamp(this->_v, INF, SUP); }
inline restrictor& _assign(const T& v) noexcept(NO_EXCEPT) {
this->_v = std::clamp(v, INF, SUP);
return *this;
}
inline restrictor& _assign_raw(const T& v) noexcept(NO_EXCEPT) {
this->_v = v;
return *this;
}
public:
static_restrictor() noexcept(NO_EXCEPT) = default;
static_restrictor(T v) noexcept(NO_EXCEPT) : _v(v) { this->_clamp(); }<--- Struct 'static_restrictor' has a constructor with 1 argument that is not explicit. [+]Struct 'static_restrictor' has a constructor with 1 argument that is not explicit. Such, so called "Converting constructors", should in general be explicit for type safety reasons as that prevents unintended implicit conversions.
inline T val() const noexcept(NO_EXCEPT) { return this->_v; }
static inline static_restrictor raw(const T& v) noexcept(NO_EXCEPT) {
static_restrictor res;
res._assign_raw(v);
return res;
}
restrictor& operator++() noexcept(NO_EXCEPT) { return this->_assign(this->_v + 1); }
restrictor& operator--() noexcept(NO_EXCEPT) { return this->_assign(this->_v - 1); }
restrictor operator++(int) noexcept(NO_EXCEPT) { auto res = *this; return ++(*this), res; }
restrictor operator--(int) noexcept(NO_EXCEPT) { auto res = *this; return --(*this), res; }
restrictor& operator+=(const restrictor& rhs) noexcept(NO_EXCEPT) {
return this->_assign_raw(add_clamp(this->_v, rhs._v, INF, SUP));
}
restrictor& operator-=(const restrictor& rhs) noexcept(NO_EXCEPT) {
return this->_assign_raw(sub_clamp(this->_v, rhs._v, INF, SUP));
}
restrictor& operator*=(const restrictor& rhs) noexcept(NO_EXCEPT) {
return this->_assign_raw(mul_clamp(this->_v, rhs._v, INF, SUP));
}
restrictor& operator/=(const restrictor& rhs) noexcept(NO_EXCEPT) {
return this->_assign(this->_v / rhs.val());
}
restrictor operator+() const noexcept(NO_EXCEPT) { return *this; }
restrictor operator-() const noexcept(NO_EXCEPT) { return restrictor(-this->_v); }
friend restrictor operator+(restrictor lhs, const restrictor& rhs) noexcept(NO_EXCEPT) {
return lhs += rhs;
}
friend restrictor operator-(restrictor lhs, const restrictor& rhs) noexcept(NO_EXCEPT) {
return lhs -= rhs;
}
friend restrictor operator*(restrictor lhs, const restrictor& rhs) noexcept(NO_EXCEPT) {
return lhs *= rhs;
}
friend restrictor operator/(restrictor lhs, const restrictor& rhs) noexcept(NO_EXCEPT) {
return lhs /= rhs;
}
friend bool operator==(const restrictor& lhs, const restrictor& rhs) noexcept(NO_EXCEPT) {
return lhs._v == rhs._v;
}
friend bool operator!=(const restrictor& lhs, const restrictor& rhs) noexcept(NO_EXCEPT) {
return lhs._v != rhs._v;
}
friend bool operator<(const restrictor& lhs, const restrictor& rhs) noexcept(NO_EXCEPT) {
return lhs._v < rhs._v;
}
friend bool operator>(const restrictor& lhs, const restrictor& rhs) noexcept(NO_EXCEPT) {
return lhs._v > rhs._v;
}
friend bool operator<=(const restrictor& lhs, const restrictor& rhs) noexcept(NO_EXCEPT) {
return lhs._v <= rhs._v;
}
friend bool operator>=(const restrictor& lhs, const restrictor& rhs) noexcept(NO_EXCEPT) {
return lhs._v >= rhs._v;
}
friend bool operator<=>(const restrictor& lhs, const restrictor& rhs) noexcept(NO_EXCEPT) {
return lhs._v <=> rhs._v;
}
};
} // namespace uni
namespace std {
template<class T, T INF, T SUP>
T abs(const uni::static_restrictor<T,INF,SUP>& v) noexcept(NO_EXCEPT) { return std::abs(v.val()); }
}
|