diff --git a/include/mapnik/value.hpp b/include/mapnik/value.hpp index c6add2d0e..78299e497 100644 --- a/include/mapnik/value.hpp +++ b/include/mapnik/value.hpp @@ -38,6 +38,7 @@ #include #include #include + // icu #include #include @@ -69,339 +70,100 @@ inline void to_utf8(mapnik::value_unicode_string const& input, std::string & tar using value_base = util::variant; -namespace impl { +namespace detail { + +namespace { +template +struct both_arithmetic : std::integral_constant::value && + std::is_arithmetic::value > {}; struct equals { - bool operator() (value_integer lhs, value_double rhs) const - { - return static_cast(lhs) == rhs; - } - - bool operator() (value_bool lhs, value_double rhs) const - { - return static_cast(lhs) == rhs; - } - - bool operator() (value_double lhs, value_integer rhs) const - { - return lhs == static_cast(rhs); - } - - bool operator() (value_bool lhs, value_integer rhs) const - { - return static_cast(lhs) == rhs; - } - - bool operator() (value_integer lhs, value_bool rhs) const - { - return lhs == static_cast(rhs); - } - - bool operator() (value_double lhs, value_bool rhs) const - { - return lhs == static_cast(rhs); - } - - bool operator() (value_unicode_string const& lhs, - value_unicode_string const& rhs) const - { - return (lhs == rhs) ? true: false; - } - template - bool operator() (T lhs, T rhs) const + static bool apply(T const& lhs, T const& rhs) { - return lhs == rhs; - } - - template - bool operator() (T const&, U const&) const - { - return false; + return std::equal_to()(lhs, rhs); } }; -struct not_equals +struct not_equal { - template - bool operator() (const T &, const U &) const - { - return true; - } - template - bool operator() (T lhs, T rhs) const + static bool apply(T const& lhs, T const& rhs) { - return lhs != rhs; + return std::not_equal_to()(lhs, rhs); } - - bool operator() (value_bool lhs, value_double rhs) const - { - return static_cast(lhs) != rhs; - } - - bool operator() (value_bool lhs, value_integer rhs) const - { - return static_cast(lhs) != rhs; - } - - bool operator() (value_integer lhs, value_double rhs) const - { - return static_cast(lhs) != rhs; - } - - bool operator() (value_double lhs, value_integer rhs) const - { - return lhs != static_cast(rhs); - } - - bool operator() (value_integer lhs, value_bool rhs) const - { - return lhs != static_cast(rhs); - } - - bool operator() (value_double lhs, value_bool rhs) const - { - return lhs != static_cast(rhs); - } - - bool operator() (value_unicode_string const& lhs, - value_unicode_string const& rhs) const - { - return (lhs != rhs)? true : false; - } - - // back compatibility shim to equate empty string with null for != test - // https://github.com/mapnik/mapnik/issues/1859 - // TODO - consider removing entire specialization at Mapnik 3.x - bool operator() (value_null, value_unicode_string const& rhs) const - { - if (rhs.isEmpty()) return false; - return true; - } - }; struct greater_than { - template - bool operator()(const T &, const U &) const - { - return false; - } - template - bool operator()(T lhs, T rhs) const + static bool apply(T const& lhs, T const& rhs) { - return lhs > rhs; - } - - bool operator() (value_bool lhs, value_double rhs) const - { - return static_cast(lhs) > rhs; - } - - bool operator() (value_double lhs, value_bool rhs) const - { - return lhs > static_cast(rhs); - } - - bool operator() (value_bool lhs, value_integer rhs) const - { - return static_cast(lhs) > rhs; - } - - bool operator() (value_integer lhs, value_bool rhs) const - { - return lhs > static_cast(rhs); - } - - bool operator() (value_integer lhs, value_double rhs) const - { - return static_cast(lhs) > rhs; - } - - bool operator() (value_double lhs, value_integer rhs) const - { - return static_cast(lhs) > rhs; - } - - bool operator() (value_unicode_string const& lhs, value_unicode_string const& rhs) const - { - return (lhs > rhs) ? true : false ; - } - - bool operator() (value_null, value_null) const - { - return false; + return std::greater()(lhs, rhs); } }; struct greater_or_equal { - template - bool operator()(const T &, const U &) const - { - return false; - } - template - bool operator() (T lhs, T rhs) const + static bool apply(T const& lhs, T const& rhs) { - return lhs >= rhs; - } - - bool operator() (value_bool lhs, value_double rhs) const - { - return static_cast(lhs) >= rhs; - } - - bool operator() (value_double lhs, value_bool rhs) const - { - return lhs >= static_cast(rhs); - } - - bool operator() (value_bool lhs, value_integer rhs) const - { - return static_cast(lhs) >= rhs; - } - - bool operator() (value_integer lhs, value_bool rhs) const - { - return lhs >= static_cast(rhs); - } - - bool operator() (value_integer lhs, value_double rhs) const - { - return static_cast(lhs) >= rhs; - } - - bool operator() (value_double lhs, value_integer rhs) const - { - return lhs >= static_cast(rhs); - } - - bool operator() (value_unicode_string const& lhs, value_unicode_string const& rhs) const - { - return ( lhs >= rhs ) ? true : false ; - } - - bool operator() (value_null, value_null) const - { - return false; + return std::greater_equal()(lhs, rhs); } }; struct less_than { - template - bool operator()(const T &, const U &) const - { - return false; - } - template - bool operator()(T lhs, T rhs) const + static bool apply(T const& lhs, T const& rhs) { - return lhs < rhs; - } - - bool operator() (value_bool lhs, value_double rhs) const - { - return static_cast(lhs) < rhs; - } - - bool operator() (value_double lhs, value_bool rhs) const - { - return lhs < static_cast(rhs); - } - - bool operator() (value_bool lhs, value_integer rhs) const - { - return static_cast(lhs) < rhs; - } - - bool operator() (value_integer lhs, value_bool rhs) const - { - return lhs < static_cast(rhs); - } - - bool operator() (value_integer lhs, value_double rhs) const - { - return static_cast(lhs) < rhs; - } - - bool operator() (value_double lhs, value_integer rhs) const - { - return lhs < static_cast(rhs); - } - - bool operator()(value_unicode_string const& lhs, - value_unicode_string const& rhs ) const - { - return (lhs < rhs) ? true : false ; - } - - bool operator() (value_null, value_null) const - { - return false; + return std::less()(lhs, rhs); } }; struct less_or_equal { - template - bool operator()(const T &, const U &) const - { - return false; - } - template - bool operator()(T lhs, T rhs) const + static bool apply(T const& lhs, T const& rhs) { - return lhs <= rhs; + return std::less_equal()(lhs, rhs); + } +}; + +} + +template +struct comparison +{ + // special case for unicode_strings + bool operator() (value_unicode_string const& lhs, + value_unicode_string const& rhs) const + { + return Op::apply(lhs, rhs) ? true: false; } - bool operator() (value_bool lhs, value_double rhs) const + // same types + template + bool operator() (T lhs, T rhs) const { - return static_cast(lhs) <= rhs; + return Op::apply(lhs, rhs); } - bool operator() (value_double lhs, value_bool rhs) const + // both types are arithmetic - promote to the common type + template ::value, int>::type = 0> + bool operator() (T const& lhs, U const& rhs) const { - return lhs <= static_cast(rhs); + using common_type = typename std::common_type::type; + return Op::apply(static_cast(lhs),static_cast(rhs)); } - bool operator() (value_bool lhs, value_integer rhs) const + // + template ::value, int>::type = 0> + bool operator() (T const& lhs, U const& rhs) const { - return static_cast(lhs) <= rhs; - } - - bool operator() (value_integer lhs, value_bool rhs) const - { - return lhs <= static_cast(rhs); - } - - bool operator() (value_integer lhs, value_double rhs) const - { - return static_cast(lhs) <= rhs; - } - - bool operator() (value_double lhs, value_integer rhs) const - { - return lhs <= static_cast(rhs); - } - - bool operator()(value_unicode_string const& lhs, - value_unicode_string const& rhs ) const - { - return (lhs <= rhs) ? true : false ; - } - - bool operator() (value_null, value_null) const - { - return false; + return default_result; } }; @@ -899,7 +661,7 @@ struct convert } }; -struct to_unicode +struct to_unicode_impl { template @@ -939,9 +701,9 @@ struct to_unicode } }; -struct to_expression_string +struct to_expression_string_impl { - explicit to_expression_string(char quote = '\'') + explicit to_expression_string_impl(char quote = '\'') : quote_(quote) {} std::string operator() (value_unicode_string const& val) const @@ -967,7 +729,7 @@ struct to_expression_string std::string operator() (value_bool val) const { - return val ? "true":"false"; + return val ? "true" : "false"; } std::string operator() (value_null const&) const @@ -978,7 +740,8 @@ struct to_expression_string const char quote_; }; -} // namespace impl + +} // namespace detail namespace value_adl_barrier { @@ -1010,37 +773,37 @@ public: bool operator==(value const& other) const { - return util::apply_visitor(impl::equals(),*this,other); + return util::apply_visitor(detail::comparison(), *this, other); } bool operator!=(value const& other) const { - return util::apply_visitor(impl::not_equals(),*this,other); + return util::apply_visitor(detail::comparison(), *this, other); } bool operator>(value const& other) const { - return util::apply_visitor(impl::greater_than(),*this,other); + return util::apply_visitor(detail::comparison(), *this, other); } bool operator>=(value const& other) const { - return util::apply_visitor(impl::greater_or_equal(),*this,other); + return util::apply_visitor(detail::comparison(), *this, other); } bool operator<(value const& other) const { - return util::apply_visitor(impl::less_than(),*this,other); + return util::apply_visitor(detail::comparison(), *this, other); } bool operator<=(value const& other) const { - return util::apply_visitor(impl::less_or_equal(),*this,other); + return util::apply_visitor(detail::comparison(), *this, other); } value operator- () const { - return util::apply_visitor(impl::negate(), *this); + return util::apply_visitor(detail::negate(), *this); } bool is_null() const; @@ -1048,63 +811,63 @@ public: template T convert() const { - return util::apply_visitor(impl::convert(),*this); + return util::apply_visitor(detail::convert(),*this); } value_bool to_bool() const { - return util::apply_visitor(impl::convert(),*this); + return util::apply_visitor(detail::convert(),*this); } std::string to_expression_string(char quote = '\'') const { - return util::apply_visitor(impl::to_expression_string(quote),*this); + return util::apply_visitor(detail::to_expression_string_impl(quote),*this); } std::string to_string() const { - return util::apply_visitor(impl::convert(),*this); + return util::apply_visitor(detail::convert(),*this); } value_unicode_string to_unicode() const { - return util::apply_visitor(impl::to_unicode(),*this); + return util::apply_visitor(detail::to_unicode_impl(),*this); } value_double to_double() const { - return util::apply_visitor(impl::convert(),*this); + return util::apply_visitor(detail::convert(),*this); } value_integer to_int() const { - return util::apply_visitor(impl::convert(),*this); + return util::apply_visitor(detail::convert(),*this); } }; inline const value operator+(value const& p1,value const& p2) { - return value(util::apply_visitor(impl::add(),p1, p2)); + return value(util::apply_visitor(detail::add(),p1, p2)); } inline const value operator-(value const& p1,value const& p2) { - return value(util::apply_visitor(impl::sub(),p1, p2)); + return value(util::apply_visitor(detail::sub(),p1, p2)); } inline const value operator*(value const& p1,value const& p2) { - return value(util::apply_visitor(impl::mult(),p1, p2)); + return value(util::apply_visitor(detail::mult(),p1, p2)); } inline const value operator/(value const& p1,value const& p2) { - return value(util::apply_visitor(impl::div(),p1, p2)); + return value(util::apply_visitor(detail::div(),p1, p2)); } inline const value operator%(value const& p1,value const& p2) { - return value(util::apply_visitor(impl::mod(),p1, p2)); + return value(util::apply_visitor(detail::mod(),p1, p2)); } template