diff --git a/include/nlohmann/detail/json_pointer.hpp b/include/nlohmann/detail/json_pointer.hpp index 28de45028..ce593e843 100644 --- a/include/nlohmann/detail/json_pointer.hpp +++ b/include/nlohmann/detail/json_pointer.hpp @@ -847,7 +847,7 @@ class json_pointer } public: -#ifdef JSON_HAS_CPP_20 +#if JSON_HAS_THREE_WAY_COMPARISON /// @brief compares two JSON pointers for equality /// @sa https://json.nlohmann.me/api/json_pointer/operator_eq/ template @@ -862,6 +862,13 @@ class json_pointer { return *this == json_pointer(rhs); } + + /// @brief 3-way compares two JSON pointers + template + std::strong_ordering operator<=>(const json_pointer& rhs) const noexcept // *NOPAD* + { + return reference_tokens <=> rhs.reference_tokens; // *NOPAD* + } #else /// @brief compares two JSON pointers for equality /// @sa https://json.nlohmann.me/api/json_pointer/operator_eq/ @@ -904,6 +911,12 @@ class json_pointer // NOLINTNEXTLINE(readability-redundant-declaration) friend bool operator!=(const StringType& lhs, const json_pointer& rhs); + + /// @brief compares two JSON pointer for less-than + template + // NOLINTNEXTLINE(readability-redundant-declaration) + friend bool operator<(const json_pointer& lhs, + const json_pointer& rhs) noexcept; #endif private: @@ -911,7 +924,7 @@ class json_pointer std::vector reference_tokens; }; -#ifndef JSON_HAS_CPP_20 +#if !JSON_HAS_THREE_WAY_COMPARISON // functions cannot be defined inside class due to ODR violations template inline bool operator==(const json_pointer& lhs, @@ -958,6 +971,13 @@ inline bool operator!=(const StringType& lhs, { return !(lhs == rhs); } + +template +inline bool operator<(const json_pointer& lhs, + const json_pointer& rhs) noexcept +{ + return lhs.reference_tokens < rhs.reference_tokens; +} #endif NLOHMANN_JSON_NAMESPACE_END diff --git a/single_include/nlohmann/json.hpp b/single_include/nlohmann/json.hpp index 989c799ee..11fe57808 100644 --- a/single_include/nlohmann/json.hpp +++ b/single_include/nlohmann/json.hpp @@ -14507,7 +14507,7 @@ class json_pointer } public: -#ifdef JSON_HAS_CPP_20 +#if JSON_HAS_THREE_WAY_COMPARISON /// @brief compares two JSON pointers for equality /// @sa https://json.nlohmann.me/api/json_pointer/operator_eq/ template @@ -14522,6 +14522,13 @@ class json_pointer { return *this == json_pointer(rhs); } + + /// @brief 3-way compares two JSON pointers + template + std::strong_ordering operator<=>(const json_pointer& rhs) const noexcept // *NOPAD* + { + return reference_tokens <=> rhs.reference_tokens; // *NOPAD* + } #else /// @brief compares two JSON pointers for equality /// @sa https://json.nlohmann.me/api/json_pointer/operator_eq/ @@ -14564,6 +14571,12 @@ class json_pointer // NOLINTNEXTLINE(readability-redundant-declaration) friend bool operator!=(const StringType& lhs, const json_pointer& rhs); + + /// @brief compares two JSON pointer for less-than + template + // NOLINTNEXTLINE(readability-redundant-declaration) + friend bool operator<(const json_pointer& lhs, + const json_pointer& rhs) noexcept; #endif private: @@ -14571,7 +14584,7 @@ class json_pointer std::vector reference_tokens; }; -#ifndef JSON_HAS_CPP_20 +#if !JSON_HAS_THREE_WAY_COMPARISON // functions cannot be defined inside class due to ODR violations template inline bool operator==(const json_pointer& lhs, @@ -14618,6 +14631,13 @@ inline bool operator!=(const StringType& lhs, { return !(lhs == rhs); } + +template +inline bool operator<(const json_pointer& lhs, + const json_pointer& rhs) noexcept +{ + return lhs.reference_tokens < rhs.reference_tokens; +} #endif NLOHMANN_JSON_NAMESPACE_END diff --git a/tests/src/unit-json_pointer.cpp b/tests/src/unit-json_pointer.cpp index f6e2b00c0..cbe13bbde 100644 --- a/tests/src/unit-json_pointer.cpp +++ b/tests/src/unit-json_pointer.cpp @@ -15,6 +15,7 @@ using nlohmann::json; using namespace nlohmann::literals; // NOLINT(google-build-using-namespace) #endif +#include #include TEST_CASE("JSON pointers") @@ -697,6 +698,32 @@ TEST_CASE("JSON pointers") } } + SECTION("less-than comparison") + { + auto ptr1 = json::json_pointer("/foo/a"); + auto ptr2 = json::json_pointer("/foo/b"); + + CHECK(ptr1 < ptr2); + CHECK_FALSE(ptr2 < ptr1); + + // build with C++20 + // JSON_HAS_CPP_20 +#if JSON_HAS_THREE_WAY_COMPARISON + CHECK((ptr1 <=> ptr2) == std::strong_ordering::less); // *NOPAD* + CHECK(ptr2 > ptr1); +#endif + } + + SECTION("usable as map key") + { + auto ptr = json::json_pointer("/foo"); + std::map m; + + m[ptr] = 42; + + CHECK(m.find(ptr) != m.end()); + } + SECTION("backwards compatibility and mixing") { json j = R"(