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 struct sub
{ {
using value_type = V; 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; 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> template <typename T>
value_type operator() (T lhs, T rhs) const value_type operator() (T lhs, T rhs) const
{ {
@ -495,15 +529,12 @@ struct sub
return value_type(); 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 value_type operator() (value_bool lhs, value_bool rhs) const
{ {
@ -515,11 +546,47 @@ template <typename V>
struct mult struct mult
{ {
using value_type = V; 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; 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> template <typename T>
value_type operator() (T lhs, T rhs) const value_type operator() (T lhs, T rhs) const
{ {
@ -532,19 +599,15 @@ struct mult
return value_type(); 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; return value_integer(lhs * rhs);
}
value_type operator() (value_bool, value_bool) const
{
return value_integer(0);
} }
}; };
@ -552,12 +615,35 @@ template <typename V>
struct div struct div
{ {
using value_type = V; 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; 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> template <typename T>
value_type operator() (T lhs, T rhs) const value_type operator() (T lhs, T rhs) const
{ {
@ -576,16 +662,23 @@ struct div
return value_type(); 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;
return lhs / rhs;
} }
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(); 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 struct mod
{ {
using value_type = V; using value_type = V;
template <typename T1, typename T2> template <typename T1, typename T2>
value_type operator() (T1 const& lhs, T2 const&) const value_type operator() (T1 const& lhs, T2 const&) const
{ {
return lhs; return lhs;
} }
template <typename T> template <typename T>