32 explicit Checked(T
const value) : value{value} {}
37 std::strong_ordering operator<=>(
Checked<T> const & other)
const =
default;
38 std::strong_ordering operator<=>(T
const & other)
const
40 return value <=> other;
43 explicit operator T()
const
48 enum class OverflowKind {
57 OverflowKind overflowed_;
60 Result(T value,
bool overflowed) : value{value}, overflowed_{overflowed ? OverflowKind::Overflow : OverflowKind::NoOverflow} {}
61 Result(T value, OverflowKind overflowed) : value{value}, overflowed_{overflowed} {}
63 bool operator==(
Result other)
const
65 return value == other.value && overflowed_ == other.overflowed_;
68 std::optional<T> valueChecked()
const
70 if (overflowed_ != OverflowKind::NoOverflow) {
84 if (overflowed_ == OverflowKind::DivByZero) {
90 bool overflowed()
const
92 return overflowed_ == OverflowKind::Overflow;
95 bool divideByZero()
const
97 return overflowed_ == OverflowKind::DivByZero;
101 Result operator+(Checked<T>
const other)
const
103 return (*
this) + other.value;
105 Result operator+(T
const other)
const
108 bool overflowed = __builtin_add_overflow(value, other, &result);
109 return Result{result, overflowed};
112 Result operator-(Checked<T>
const other)
const
114 return (*
this) - other.value;
116 Result operator-(T
const other)
const
119 bool overflowed = __builtin_sub_overflow(value, other, &result);
120 return Result{result, overflowed};
123 Result operator*(Checked<T>
const other)
const
125 return (*
this) * other.value;
127 Result operator*(T
const other)
const
130 bool overflowed = __builtin_mul_overflow(value, other, &result);
131 return Result{result, overflowed};
134 Result operator/(Checked<T>
const other)
const
136 return (*
this) / other.value;
146 constexpr T
const minV = std::numeric_limits<T>::min();
152 if (std::is_signed<T>() && (value == minV && other == -1)) {
153 return Result{minV,
true};
154 }
else if (other == 0) {
155 return Result{0, OverflowKind::DivByZero};
157 T result = value / other;
158 return Result{result,
false};