32 enum class Kind { None, Integer, Float, Bool, Cont };
36 Kind kind_ = Kind::None;
44 NumericHandle() =
default;
48 if ( !node )
return {};
49 if (
dynamic_cast<IntegerObj*
>(node) )
return { node, Kind::Integer };
50 if (
dynamic_cast<FloatObj*
>(node) )
return { node, Kind::Float };
51 if (
dynamic_cast<BoolObj*
>(node) )
return { node, Kind::Bool };
52 if (
dynamic_cast<ContainerObj*
>(node) )
return { node, Kind::Cont };
56 explicit operator bool()
const {
return kind_ != Kind::None; }
57 Kind getKind()
const {
return kind_; }
66 bool operator<(
const NumericHandle& rhs)
const {
return cmpHandle(rhs, std::less<> {}); }
67 bool operator>(
const NumericHandle& rhs)
const {
return rhs < *
this; }
68 bool operator<=(
const NumericHandle& rhs)
const {
return !(rhs < *
this); }
69 bool operator>=(
const NumericHandle& rhs)
const {
return !(*
this < rhs); }
70 bool operator==(
const NumericHandle& rhs)
const {
return !(*
this < rhs) && !(rhs < *
this); }
71 bool operator!=(
const NumericHandle& rhs)
const {
return !(*
this == rhs); }
77 template <
typename T,
typename = std::enable_if_t<std::is_arithmetic_v<T>>>
78 bool operator<(T rhs)
const
80 return cmpConst(rhs, std::less<> {});
83 template <
typename T,
typename = std::enable_if_t<std::is_arithmetic_v<T>>>
84 bool operator>(T rhs)
const
86 return cmpConst(rhs, std::greater<> {});
89 template <
typename T,
typename = std::enable_if_t<std::is_arithmetic_v<T>>>
90 bool operator<=(T rhs)
const
92 return cmpConst(rhs, std::less_equal<> {});
95 template <
typename T,
typename = std::enable_if_t<std::is_arithmetic_v<T>>>
96 bool operator>=(T rhs)
const
98 return cmpConst(rhs, std::greater_equal<> {});
101 template <
typename T,
typename = std::enable_if_t<std::is_arithmetic_v<T>>>
102 bool operator==(T rhs)
const
104 return cmpConst(rhs, std::equal_to<> {});
107 template <
typename T,
typename = std::enable_if_t<std::is_arithmetic_v<T>>>
108 bool operator!=(T rhs)
const
110 return cmpConst(rhs, std::not_equal_to<> {});
115 template <
typename Cmp>
116 bool cmpHandle(
const NumericHandle& rhs, Cmp cmp)
const
118 if ( !*
this || !rhs )
return false;
121 auto visitRhs = [&](
auto lhsVal) ->
bool {
122 auto inner = [&](
auto rhsVal) ->
bool {
123 if constexpr ( std::is_integral_v<
decltype(lhsVal)> && std::is_integral_v<
decltype(rhsVal)> ) {
124 using Common = std::common_type_t<
decltype(lhsVal),
decltype(rhsVal)>;
125 return cmp(
static_cast<Common
>(lhsVal),
static_cast<Common
>(rhsVal));
128 return cmp(
static_cast<long double>(lhsVal),
static_cast<long double>(rhsVal));
131 if ( rhs.kind_ == Kind::Integer )
return rhs.asInteger()->visit(inner);
132 if ( rhs.kind_ == Kind::Float )
return rhs.asFloat()->visit(inner);
133 if ( rhs.kind_ == Kind::Bool )
return inner(
static_cast<int64_t
>(rhs.asBool()->getVal()));
134 if ( rhs.kind_ == Kind::Cont )
return inner(
static_cast<int64_t
>(rhs.asCont()->getSize()));
138 if ( kind_ == Kind::Integer )
return asInteger()->visit(visitRhs);
139 if ( kind_ == Kind::Float )
return asFloat()->visit(visitRhs);
140 if ( kind_ == Kind::Bool )
return visitRhs(
static_cast<int64_t
>(asBool()->getVal()));
141 if ( kind_ == Kind::Cont )
return visitRhs(
static_cast<int64_t
>(asCont()->getSize()));
148 template <
typename ConstT,
typename Cmp>
149 bool cmpConst(ConstT rhs, Cmp cmp)
const
151 if ( kind_ == Kind::Integer ) {
152 return asInteger()->visit([&](
auto lhs) {
153 if constexpr ( std::is_integral_v<
decltype(lhs)> && std::is_integral_v<ConstT> ) {
155 using Common = std::common_type_t<
decltype(lhs), ConstT>;
156 return cmp(
static_cast<Common
>(lhs),
static_cast<Common
>(rhs));
159 return cmp(
static_cast<long double>(lhs),
static_cast<long double>(rhs));
163 if ( kind_ == Kind::Float ) {
164 return asFloat()->visit(
165 [&](
auto lhs) {
return cmp(
static_cast<long double>(lhs),
static_cast<long double>(rhs)); });
167 if ( kind_ == Kind::Bool ) {
168 auto lhs =
static_cast<int64_t
>(asBool()->getVal());
169 if constexpr ( std::is_integral_v<ConstT> ) {
170 using Common = std::common_type_t<int64_t, ConstT>;
171 return cmp(
static_cast<Common
>(lhs),
static_cast<Common
>(rhs));
174 return cmp(
static_cast<long double>(lhs),
static_cast<long double>(rhs));
177 if ( kind_ == Kind::Cont ) {
178 auto lhs = asCont()->getSize();
179 if constexpr ( std::is_integral_v<ConstT> ) {
180 using Common = std::common_type_t<int64_t, ConstT>;
181 return cmp(
static_cast<Common
>(lhs),
static_cast<Common
>(rhs));
184 return cmp(
static_cast<long double>(lhs),
static_cast<long double>(rhs));