improve type promotion across arithmetic ops

This commit is contained in:
artemp 2016-01-21 18:14:55 +01:00
parent a707d5cd65
commit 85c3f5dbc1

View file

@ -477,12 +477,46 @@ template <typename V>
struct sub
{
using value_type = V;
template <typename T1, typename T2>
value_type operator() (T1 const& lhs, T2 const&) const
value_type operator() (value_null const& lhs ,
value_null const& rhs) const
{
return lhs;
}
value_type operator() (value_null, value_unicode_string const& rhs) const
{
return rhs;
}
value_type operator() (value_unicode_string const& lhs, value_null) const
{
return lhs;
}
template <typename R>
value_type operator() (value_unicode_string const& lhs, R const&) const
{
return lhs;
}
template <typename L>
value_type operator() (L const&, value_unicode_string const& rhs) const
{
return rhs;
}
template <typename L>
value_type operator() (L const& lhs, value_null const&) const
{
return lhs;
}
template <typename R>
value_type operator() (value_null const&, R const& rhs) const
{
return rhs;
}
template <typename T>
value_type operator() (T lhs, T rhs) const
{
@ -495,15 +529,12 @@ struct sub
return value_type();
}
value_type operator() (value_double lhs, value_integer rhs) const
template <typename T1, typename T2>
value_type operator() (T1 const& lhs, T2 const& rhs) const
{
return lhs - rhs;
return typename std::common_type<T1,T2>::type{ lhs - rhs };
}
value_type operator() (value_integer lhs, value_double rhs) const
{
return lhs - rhs;
}
value_type operator() (value_bool lhs, value_bool rhs) const
{
@ -515,11 +546,47 @@ template <typename V>
struct mult
{
using value_type = V;
template <typename T1, typename T2>
value_type operator() (T1 const& lhs , T2 const& ) const
value_type operator() (value_null const& lhs ,
value_null const& rhs) const
{
return lhs;
}
value_type operator() (value_unicode_string const& lhs, value_null) const
{
return lhs;
}
value_type operator() (value_null, value_unicode_string const& rhs) const
{
return rhs;
}
template <typename L>
value_type operator() (L const& lhs, value_null const&) const
{
return lhs;
}
template <typename R>
value_type operator() (value_null const&, R const& rhs) const
{
return rhs;
}
template <typename R>
value_type operator() (value_unicode_string const& lhs, R const&) const
{
return lhs;
}
template <typename L>
value_type operator() (L const&, value_unicode_string const& rhs) const
{
return rhs;
}
template <typename T>
value_type operator() (T lhs, T rhs) const
{
@ -532,19 +599,15 @@ struct mult
return value_type();
}
value_type operator() (value_double lhs, value_integer rhs) const
template <typename T1, typename T2>
value_type operator() (T1 const& lhs, T2 const& rhs) const
{
return lhs * rhs;
return typename std::common_type<T1,T2>::type{ lhs * rhs };
}
value_type operator() (value_integer lhs, value_double rhs) const
value_type operator() (value_bool lhs, value_bool rhs) const
{
return lhs * rhs;
}
value_type operator() (value_bool, value_bool) const
{
return value_integer(0);
return value_integer(lhs * rhs);
}
};
@ -552,12 +615,35 @@ template <typename V>
struct div
{
using value_type = V;
template <typename T1, typename T2>
value_type operator() (T1 const& lhs, T2 const&) const
value_type operator() (value_null const& lhs ,
value_null const& rhs) const
{
return lhs;
}
value_type operator() (value_unicode_string const& lhs, value_null) const
{
return lhs;
}
value_type operator() (value_null, value_unicode_string const& rhs) const
{
return rhs;
}
template <typename L>
value_type operator() (L const& lhs, value_null const&) const
{
return lhs;
}
template <typename R>
value_type operator() (value_null const&, R const& rhs) const
{
return rhs;
}
template <typename T>
value_type operator() (T lhs, T rhs) const
{
@ -576,16 +662,23 @@ struct div
return value_type();
}
value_type operator() (value_double lhs, value_integer rhs) const
template <typename R>
value_type operator() (value_unicode_string const& lhs, R const&) const
{
if (rhs == 0) return value_type();
return lhs / rhs;
return lhs;
}
value_type operator() (value_integer lhs, value_double rhs) const
template <typename L>
value_type operator() (L const&, value_unicode_string const& rhs) const
{
return rhs;
}
template <typename T1, typename T2>
value_type operator() (T1 const& lhs, T2 const& rhs) const
{
if (rhs == 0) return value_type();
return lhs / rhs;
return typename std::common_type<T1,T2>::type{ lhs / rhs };
}
};
@ -593,10 +686,11 @@ template <typename V>
struct mod
{
using value_type = V;
template <typename T1, typename T2>
value_type operator() (T1 const& lhs, T2 const&) const
{
return lhs;
return lhs;
}
template <typename T>