Add scalar-on-left overloads for legacy discarded comparisons in C++20

With JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON=1 and C++20, a scalar on
the left-hand side of <= or >= (e.g., `1 <= discarded`) yielded false
instead of the documented true. The C++20 legacy block only had member
operators, which are only candidates when the basic_json is the left
operand; for a scalar on the left, overload resolution picked the
candidate rewritten from operator<=>, which does not emulate the legacy
behavior. The C++17 branch already has scalar-on-the-left friend
overloads for <= and >=; add the equivalent pair to the C++20 legacy
block.

Added a regression test to tests/src/unit-comparison.cpp covering all
four operand orders for both operators.

Fixes #5665.

Signed-off-by: Niels Lohmann <mail@nlohmann.me>
This commit is contained in:
Niels Lohmann
2026-09-29 23:16:44 +02:00
parent 633de8e44b
commit 864ac37cdb
4 changed files with 67 additions and 0 deletions
+21
View File
@@ -4673,6 +4673,27 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
{
return *this >= basic_json(rhs);
}
// a scalar on the left-hand side would otherwise select the candidate
// rewritten from operator<=>, which does not emulate the legacy behavior
/// @brief comparison: less than or equal
/// @sa https://json.nlohmann.me/api/basic_json/operator_le/
template<typename ScalarType>
requires std::is_scalar_v<ScalarType>
friend bool operator<=(ScalarType lhs, const_reference rhs) noexcept
{
return basic_json(lhs) <= rhs;
}
/// @brief comparison: greater than or equal
/// @sa https://json.nlohmann.me/api/basic_json/operator_ge/
template<typename ScalarType>
requires std::is_scalar_v<ScalarType>
friend bool operator>=(ScalarType lhs, const_reference rhs) noexcept
{
return basic_json(lhs) >= rhs;
}
#endif
#else
/// @brief comparison: equal