Skip to content

Commit

Permalink
🐛 fix for #512
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
nlohmann committed Apr 7, 2017
1 parent 4f6b63e commit 90273e9
Show file tree
Hide file tree
Showing 3 changed files with 211 additions and 0 deletions.
88 changes: 88 additions & 0 deletions src/json.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -6385,6 +6385,28 @@ class basic_json
return operator<(lhs_type, rhs_type);
}

/*!
@brief comparison: less than
@copydoc operator<(const_reference, const_reference)
*/
template<typename ScalarType, typename std::enable_if<
std::is_scalar<ScalarType>::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<typename ScalarType, typename std::enable_if<
std::is_scalar<ScalarType>::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
Expand All @@ -6407,6 +6429,28 @@ class basic_json
return not (rhs < lhs);
}

/*!
@brief comparison: less than or equal
@copydoc operator<=(const_reference, const_reference)
*/
template<typename ScalarType, typename std::enable_if<
std::is_scalar<ScalarType>::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<typename ScalarType, typename std::enable_if<
std::is_scalar<ScalarType>::value, int>::type = 0>
friend bool operator<=(const ScalarType lhs, const_reference rhs) noexcept
{
return (basic_json(lhs) <= rhs);
}

/*!
@brief comparison: greater than
Expand All @@ -6429,6 +6473,28 @@ class basic_json
return not (lhs <= rhs);
}

/*!
@brief comparison: greater than
@copydoc operator>(const_reference, const_reference)
*/
template<typename ScalarType, typename std::enable_if<
std::is_scalar<ScalarType>::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<typename ScalarType, typename std::enable_if<
std::is_scalar<ScalarType>::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
Expand All @@ -6451,6 +6517,28 @@ class basic_json
return not (lhs < rhs);
}

/*!
@brief comparison: greater than or equal
@copydoc operator>=(const_reference, const_reference)
*/
template<typename ScalarType, typename std::enable_if<
std::is_scalar<ScalarType>::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<typename ScalarType, typename std::enable_if<
std::is_scalar<ScalarType>::value, int>::type = 0>
friend bool operator>=(const ScalarType lhs, const_reference rhs) noexcept
{
return (basic_json(lhs) >= rhs);
}

/// @}


Expand Down
88 changes: 88 additions & 0 deletions src/json.hpp.re2c
Original file line number Diff line number Diff line change
Expand Up @@ -6385,6 +6385,28 @@ class basic_json
return operator<(lhs_type, rhs_type);
}

/*!
@brief comparison: less than
@copydoc operator<(const_reference, const_reference)
*/
template<typename ScalarType, typename std::enable_if<
std::is_scalar<ScalarType>::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<typename ScalarType, typename std::enable_if<
std::is_scalar<ScalarType>::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

Expand All @@ -6407,6 +6429,28 @@ class basic_json
return not (rhs < lhs);
}

/*!
@brief comparison: less than or equal
@copydoc operator<=(const_reference, const_reference)
*/
template<typename ScalarType, typename std::enable_if<
std::is_scalar<ScalarType>::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<typename ScalarType, typename std::enable_if<
std::is_scalar<ScalarType>::value, int>::type = 0>
friend bool operator<=(const ScalarType lhs, const_reference rhs) noexcept
{
return (basic_json(lhs) <= rhs);
}

/*!
@brief comparison: greater than

Expand All @@ -6429,6 +6473,28 @@ class basic_json
return not (lhs <= rhs);
}

/*!
@brief comparison: greater than
@copydoc operator>(const_reference, const_reference)
*/
template<typename ScalarType, typename std::enable_if<
std::is_scalar<ScalarType>::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<typename ScalarType, typename std::enable_if<
std::is_scalar<ScalarType>::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

Expand All @@ -6451,6 +6517,28 @@ class basic_json
return not (lhs < rhs);
}

/*!
@brief comparison: greater than or equal
@copydoc operator>=(const_reference, const_reference)
*/
template<typename ScalarType, typename std::enable_if<
std::is_scalar<ScalarType>::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<typename ScalarType, typename std::enable_if<
std::is_scalar<ScalarType>::value, int>::type = 0>
friend bool operator>=(const ScalarType lhs, const_reference rhs) noexcept
{
return (basic_json(lhs) >= rhs);
}

/// @}


Expand Down
35 changes: 35 additions & 0 deletions test/src/unit-regression.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"]));
}
}

0 comments on commit 90273e9

Please sign in to comment.