mirror of
https://github.com/nlohmann/json.git
synced 2026-07-09 12:05:10 +00:00
Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 8861d3ec5a | |||
| d8b274e7c2 |
@@ -19,10 +19,8 @@ class basic_json {
|
|||||||
};
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
1. Compares two JSON values for inequality according to the following rules:
|
1. Compares two JSON values for inequality. Returns `#!cpp !(lhs == rhs)` (until C++20) or `#!cpp !(*this == rhs)` (since C++20).
|
||||||
- The comparison always yields `#!cpp false` if (1) either operand is discarded, or (2) either operand is `NaN` and
|
- This means the comparison is simply the logical negation of `operator==`, including for special values like `NaN` and `discarded`.
|
||||||
the other operand is either `NaN` or any other number.
|
|
||||||
- Otherwise, returns the result of `#!cpp !(lhs == rhs)` (until C++20) or `#!cpp !(*this == rhs)` (since C++20).
|
|
||||||
|
|
||||||
2. Compares a JSON value and a scalar or a scalar and a JSON value for inequality by converting the scalar to a JSON
|
2. Compares a JSON value and a scalar or a scalar and a JSON value for inequality by converting the scalar to a JSON
|
||||||
value and comparing both JSON values according to 1.
|
value and comparing both JSON values according to 1.
|
||||||
@@ -54,13 +52,12 @@ Linear.
|
|||||||
|
|
||||||
## Notes
|
## Notes
|
||||||
|
|
||||||
!!! note "Comparing `NaN`"
|
!!! note "Comparing `NaN` and `discarded`"
|
||||||
|
|
||||||
`NaN` values are unordered within the domain of numbers.
|
Since `operator!=` is defined as `!(a == b)`, the behavior for special values follows that of `operator==`:
|
||||||
The following comparisons all yield `#!cpp false`:
|
|
||||||
1. Comparing a `NaN` with itself.
|
- For `NaN` values: `NaN == NaN` yields `#!cpp false`, so `NaN != NaN` yields `#!cpp true`.
|
||||||
2. Comparing a `NaN` with another `NaN`.
|
- For `discarded` values: `discarded == x` yields `#!cpp false` for any `x`, so `discarded != x` yields `#!cpp true`.
|
||||||
3. Comparing a `NaN` and any other number.
|
|
||||||
|
|
||||||
## Examples
|
## Examples
|
||||||
|
|
||||||
@@ -94,5 +91,7 @@ Linear.
|
|||||||
|
|
||||||
## Version history
|
## Version history
|
||||||
|
|
||||||
1. Added in version 1.0.0. Added C++20 member functions in version 3.11.0.
|
1. Added in version 1.0.0. Added C++20 member functions in version 3.11.0. Changed in version 3.12.x to remove
|
||||||
2. Added in version 1.0.0. Added C++20 member functions in version 3.11.0.
|
special-casing for `NaN` and `discarded` values; `operator!=` now consistently means `!(a == b)`.
|
||||||
|
2. Added in version 1.0.0. Added C++20 member functions in version 3.11.0. Changed in version 3.12.x to remove
|
||||||
|
special-casing for `NaN` and `discarded` values; `operator!=` now consistently means `!(a == b)`.
|
||||||
|
|||||||
@@ -3776,17 +3776,6 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
return *this == basic_json(rhs);
|
return *this == basic_json(rhs);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief comparison: not equal
|
|
||||||
/// @sa https://json.nlohmann.me/api/basic_json/operator_ne/
|
|
||||||
bool operator!=(const_reference rhs) const noexcept
|
|
||||||
{
|
|
||||||
if (compares_unordered(rhs, true))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return !operator==(rhs);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @brief comparison: 3-way
|
/// @brief comparison: 3-way
|
||||||
/// @sa https://json.nlohmann.me/api/basic_json/operator_spaceship/
|
/// @sa https://json.nlohmann.me/api/basic_json/operator_spaceship/
|
||||||
std::partial_ordering operator<=>(const_reference rhs) const noexcept // *NOPAD*
|
std::partial_ordering operator<=>(const_reference rhs) const noexcept // *NOPAD*
|
||||||
@@ -3892,10 +3881,6 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
/// @sa https://json.nlohmann.me/api/basic_json/operator_ne/
|
/// @sa https://json.nlohmann.me/api/basic_json/operator_ne/
|
||||||
friend bool operator!=(const_reference lhs, const_reference rhs) noexcept
|
friend bool operator!=(const_reference lhs, const_reference rhs) noexcept
|
||||||
{
|
{
|
||||||
if (compares_unordered(lhs, rhs, true))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return !(lhs == rhs);
|
return !(lhs == rhs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -24622,17 +24622,6 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
return *this == basic_json(rhs);
|
return *this == basic_json(rhs);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief comparison: not equal
|
|
||||||
/// @sa https://json.nlohmann.me/api/basic_json/operator_ne/
|
|
||||||
bool operator!=(const_reference rhs) const noexcept
|
|
||||||
{
|
|
||||||
if (compares_unordered(rhs, true))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return !operator==(rhs);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @brief comparison: 3-way
|
/// @brief comparison: 3-way
|
||||||
/// @sa https://json.nlohmann.me/api/basic_json/operator_spaceship/
|
/// @sa https://json.nlohmann.me/api/basic_json/operator_spaceship/
|
||||||
std::partial_ordering operator<=>(const_reference rhs) const noexcept // *NOPAD*
|
std::partial_ordering operator<=>(const_reference rhs) const noexcept // *NOPAD*
|
||||||
@@ -24738,10 +24727,6 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
|||||||
/// @sa https://json.nlohmann.me/api/basic_json/operator_ne/
|
/// @sa https://json.nlohmann.me/api/basic_json/operator_ne/
|
||||||
friend bool operator!=(const_reference lhs, const_reference rhs) noexcept
|
friend bool operator!=(const_reference lhs, const_reference rhs) noexcept
|
||||||
{
|
{
|
||||||
if (compares_unordered(lhs, rhs, true))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return !(lhs == rhs);
|
return !(lhs == rhs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -369,6 +369,7 @@ TEST_CASE("lexicographical comparison operators")
|
|||||||
SECTION("comparison: not equal")
|
SECTION("comparison: not equal")
|
||||||
{
|
{
|
||||||
// check that two values compare unequal as expected
|
// check that two values compare unequal as expected
|
||||||
|
// operator!= now means exactly !(a==b) without special cases for NaN/discarded
|
||||||
for (size_t i = 0; i < j_values.size(); ++i)
|
for (size_t i = 0; i < j_values.size(); ++i)
|
||||||
{
|
{
|
||||||
for (size_t j = 0; j < j_values.size(); ++j)
|
for (size_t j = 0; j < j_values.size(); ++j)
|
||||||
@@ -376,25 +377,12 @@ TEST_CASE("lexicographical comparison operators")
|
|||||||
CAPTURE(i)
|
CAPTURE(i)
|
||||||
CAPTURE(j)
|
CAPTURE(j)
|
||||||
|
|
||||||
if (json::compares_unordered(j_values[i], j_values[j], true))
|
CHECK((j_values[i] != j_values[j]) == !(j_values[i] == j_values[j]));
|
||||||
{
|
|
||||||
// if two values compare unordered,
|
|
||||||
// check that the boolean comparison result is always false
|
|
||||||
CHECK_FALSE(j_values[i] != j_values[j]);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// otherwise, check that they compare according to their definition
|
|
||||||
// as the inverse of equal
|
|
||||||
CHECK((j_values[i] != j_values[j]) == !(j_values[i] == j_values[j]));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// compare with null pointer
|
// compare with null pointer
|
||||||
const json j_null;
|
const json j_null;
|
||||||
CHECK((j_null != nullptr) == false);
|
|
||||||
CHECK((nullptr != j_null) == false);
|
|
||||||
CHECK((j_null != nullptr) == !(j_null == nullptr));
|
CHECK((j_null != nullptr) == !(j_null == nullptr));
|
||||||
CHECK((nullptr != j_null) == !(nullptr == j_null));
|
CHECK((nullptr != j_null) == !(nullptr == j_null));
|
||||||
}
|
}
|
||||||
@@ -594,3 +582,34 @@ TEST_CASE("lexicographical comparison operators")
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if JSON_HAS_THREE_WAY_COMPARISON
|
||||||
|
// JSON_HAS_CPP_20 (do not remove; see note at top of file)
|
||||||
|
|
||||||
|
TEST_CASE("regression #3868 - heterogeneous comparisons compile under C++20 (P2468R2)")
|
||||||
|
{
|
||||||
|
// Issue #3868: operator!= was preventing compiler from synthesizing reversed
|
||||||
|
// operator== candidates under C++20's P2468R2 rewritten candidate rules.
|
||||||
|
// Verify that heterogeneous comparisons now work.
|
||||||
|
|
||||||
|
SECTION("string vs json")
|
||||||
|
{
|
||||||
|
std::string s = "string";
|
||||||
|
json j = "string";
|
||||||
|
CHECK(s == j);
|
||||||
|
CHECK(j == s);
|
||||||
|
CHECK_FALSE(s != j);
|
||||||
|
CHECK_FALSE(j != s);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("other heterogeneous types")
|
||||||
|
{
|
||||||
|
int i = 42;
|
||||||
|
json j = 42;
|
||||||
|
CHECK(i == j);
|
||||||
|
CHECK(j == i);
|
||||||
|
CHECK_FALSE(i != j);
|
||||||
|
CHECK_FALSE(j != i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|||||||
@@ -278,7 +278,7 @@ TEST_CASE("constructors")
|
|||||||
const auto t = j.get<std::tuple<int, float, std::string>>();
|
const auto t = j.get<std::tuple<int, float, std::string>>();
|
||||||
CHECK(std::get<0>(t) == j[0]);
|
CHECK(std::get<0>(t) == j[0]);
|
||||||
CHECK(std::get<1>(t) == j[1]);
|
CHECK(std::get<1>(t) == j[1]);
|
||||||
// CHECK(std::get<2>(t) == j[2]); // commented out due to CI issue, see https://github.com/nlohmann/json/pull/3985 and https://github.com/nlohmann/json/issues/4025
|
CHECK(std::get<2>(t) == j[2]);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("std::tuple tie")
|
SECTION("std::tuple tie")
|
||||||
|
|||||||
@@ -942,7 +942,7 @@ TEST_CASE("iterators 2")
|
|||||||
json j_expected{5, 4, 3, 2, 1};
|
json j_expected{5, 4, 3, 2, 1};
|
||||||
|
|
||||||
auto reversed = j | std::views::reverse;
|
auto reversed = j | std::views::reverse;
|
||||||
CHECK(std::ranges::equal(reversed, j_expected));
|
CHECK(reversed == j_expected);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("transform")
|
SECTION("transform")
|
||||||
|
|||||||
Reference in New Issue
Block a user