From 90273e930c135a3f893ef2e303267f76b9b246b5 Mon Sep 17 00:00:00 2001 From: Niels Lohmann Date: Fri, 7 Apr 2017 15:44:41 +0200 Subject: [PATCH] :bug: fix for #512 We totally forgot to implement the comparison operators other than == and != for scalar types. Consequently, comparing a JSON value with a scalar type led to compile errors. --- src/json.hpp | 88 ++++++++++++++++++++++++++++++++++++ src/json.hpp.re2c | 88 ++++++++++++++++++++++++++++++++++++ test/src/unit-regression.cpp | 35 ++++++++++++++ 3 files changed, 211 insertions(+) diff --git a/src/json.hpp b/src/json.hpp index 5df1bacc4..98659054e 100644 --- a/src/json.hpp +++ b/src/json.hpp @@ -6385,6 +6385,28 @@ class basic_json return operator<(lhs_type, rhs_type); } + /*! + @brief comparison: less than + @copydoc operator<(const_reference, const_reference) + */ + template::value, int>::type = 0> + friend bool operator<(const_reference lhs, const ScalarType rhs) noexcept + { + return (lhs < basic_json(rhs)); + } + + /*! + @brief comparison: less than + @copydoc operator<(const_reference, const_reference) + */ + template::value, int>::type = 0> + friend bool operator<(const ScalarType lhs, const_reference rhs) noexcept + { + return (basic_json(lhs) < rhs); + } + /*! @brief comparison: less than or equal @@ -6407,6 +6429,28 @@ class basic_json return not (rhs < lhs); } + /*! + @brief comparison: less than or equal + @copydoc operator<=(const_reference, const_reference) + */ + template::value, int>::type = 0> + friend bool operator<=(const_reference lhs, const ScalarType rhs) noexcept + { + return (lhs <= basic_json(rhs)); + } + + /*! + @brief comparison: less than or equal + @copydoc operator<=(const_reference, const_reference) + */ + template::value, int>::type = 0> + friend bool operator<=(const ScalarType lhs, const_reference rhs) noexcept + { + return (basic_json(lhs) <= rhs); + } + /*! @brief comparison: greater than @@ -6429,6 +6473,28 @@ class basic_json return not (lhs <= rhs); } + /*! + @brief comparison: greater than + @copydoc operator>(const_reference, const_reference) + */ + template::value, int>::type = 0> + friend bool operator>(const_reference lhs, const ScalarType rhs) noexcept + { + return (lhs > basic_json(rhs)); + } + + /*! + @brief comparison: greater than + @copydoc operator>(const_reference, const_reference) + */ + template::value, int>::type = 0> + friend bool operator>(const ScalarType lhs, const_reference rhs) noexcept + { + return (basic_json(lhs) > rhs); + } + /*! @brief comparison: greater than or equal @@ -6451,6 +6517,28 @@ class basic_json return not (lhs < rhs); } + /*! + @brief comparison: greater than or equal + @copydoc operator>=(const_reference, const_reference) + */ + template::value, int>::type = 0> + friend bool operator>=(const_reference lhs, const ScalarType rhs) noexcept + { + return (lhs >= basic_json(rhs)); + } + + /*! + @brief comparison: greater than or equal + @copydoc operator>=(const_reference, const_reference) + */ + template::value, int>::type = 0> + friend bool operator>=(const ScalarType lhs, const_reference rhs) noexcept + { + return (basic_json(lhs) >= rhs); + } + /// @} diff --git a/src/json.hpp.re2c b/src/json.hpp.re2c index da503495d..5e90f611c 100644 --- a/src/json.hpp.re2c +++ b/src/json.hpp.re2c @@ -6385,6 +6385,28 @@ class basic_json return operator<(lhs_type, rhs_type); } + /*! + @brief comparison: less than + @copydoc operator<(const_reference, const_reference) + */ + template::value, int>::type = 0> + friend bool operator<(const_reference lhs, const ScalarType rhs) noexcept + { + return (lhs < basic_json(rhs)); + } + + /*! + @brief comparison: less than + @copydoc operator<(const_reference, const_reference) + */ + template::value, int>::type = 0> + friend bool operator<(const ScalarType lhs, const_reference rhs) noexcept + { + return (basic_json(lhs) < rhs); + } + /*! @brief comparison: less than or equal @@ -6407,6 +6429,28 @@ class basic_json return not (rhs < lhs); } + /*! + @brief comparison: less than or equal + @copydoc operator<=(const_reference, const_reference) + */ + template::value, int>::type = 0> + friend bool operator<=(const_reference lhs, const ScalarType rhs) noexcept + { + return (lhs <= basic_json(rhs)); + } + + /*! + @brief comparison: less than or equal + @copydoc operator<=(const_reference, const_reference) + */ + template::value, int>::type = 0> + friend bool operator<=(const ScalarType lhs, const_reference rhs) noexcept + { + return (basic_json(lhs) <= rhs); + } + /*! @brief comparison: greater than @@ -6429,6 +6473,28 @@ class basic_json return not (lhs <= rhs); } + /*! + @brief comparison: greater than + @copydoc operator>(const_reference, const_reference) + */ + template::value, int>::type = 0> + friend bool operator>(const_reference lhs, const ScalarType rhs) noexcept + { + return (lhs > basic_json(rhs)); + } + + /*! + @brief comparison: greater than + @copydoc operator>(const_reference, const_reference) + */ + template::value, int>::type = 0> + friend bool operator>(const ScalarType lhs, const_reference rhs) noexcept + { + return (basic_json(lhs) > rhs); + } + /*! @brief comparison: greater than or equal @@ -6451,6 +6517,28 @@ class basic_json return not (lhs < rhs); } + /*! + @brief comparison: greater than or equal + @copydoc operator>=(const_reference, const_reference) + */ + template::value, int>::type = 0> + friend bool operator>=(const_reference lhs, const ScalarType rhs) noexcept + { + return (lhs >= basic_json(rhs)); + } + + /*! + @brief comparison: greater than or equal + @copydoc operator>=(const_reference, const_reference) + */ + template::value, int>::type = 0> + friend bool operator>=(const ScalarType lhs, const_reference rhs) noexcept + { + return (basic_json(lhs) >= rhs); + } + /// @} diff --git a/test/src/unit-regression.cpp b/test/src/unit-regression.cpp index 1e8f5c230..13c884835 100644 --- a/test/src/unit-regression.cpp +++ b/test/src/unit-regression.cpp @@ -973,4 +973,39 @@ TEST_CASE("regression tests") // check if serializations match CHECK(json::to_cbor(j2) == vec2); } + + SECTION("issue #512 - use of overloaded operator '<=' is ambiguous") + { + json j; + j["a"] = 5; + + // json op scalar + CHECK(j["a"] == 5); + CHECK(j["a"] != 4); + + CHECK(j["a"] <= 7); + CHECK(j["a"] < 7); + CHECK(j["a"] >= 3); + CHECK(j["a"] > 3); + + + CHECK(not(j["a"] <= 4)); + CHECK(not(j["a"] < 4)); + CHECK(not(j["a"] >= 6)); + CHECK(not(j["a"] > 6)); + + // scalar op json + CHECK(5 == j["a"]); + CHECK(4 != j["a"]); + + CHECK(7 >= j["a"]); + CHECK(7 > j["a"]); + CHECK(3 <= j["a"]); + CHECK(3 < j["a"]); + + CHECK(not(4 >= j["a"])); + CHECK(not(4 > j["a"])); + CHECK(not(6 <= j["a"])); + CHECK(not(6 < j["a"])); + } }