diff --git a/include/nlohmann/json.hpp b/include/nlohmann/json.hpp index 8140702de..8d188cf58 100644 --- a/include/nlohmann/json.hpp +++ b/include/nlohmann/json.hpp @@ -4707,20 +4707,16 @@ std::string to_string(const NLOHMANN_BASIC_JSON_TPL& j) // nonmember support // /////////////////////// -// specialization of std::swap, and std::hash -namespace std -{ - /// hash value for JSON objects -template<> -struct hash +template +struct std::hash { /*! @brief return a hash value for a JSON object - @since version 1.0.0 + @since version 1.0.0, extended for arbitrary basic_json types in 3.10.5. */ - std::size_t operator()(const nlohmann::json& j) const + std::size_t operator()(const BasicJsonType& j) const { return nlohmann::detail::hash(j); } @@ -4730,7 +4726,7 @@ struct hash /// @note: do not remove the space after '<', /// see https://github.com/nlohmann/json/pull/679 template<> -struct less<::nlohmann::detail::value_t> +struct std::less< ::nlohmann::detail::value_t> { /*! @brief compare two value_t enum values @@ -4746,6 +4742,9 @@ struct less<::nlohmann::detail::value_t> // C++20 prohibit function specialization in the std namespace. #ifndef JSON_HAS_CPP_20 +namespace std +{ + /*! @brief exchanges the values of two JSON objects @@ -4760,9 +4759,9 @@ inline void swap(nlohmann::json& j1, nlohmann::json& j2) noexcep j1.swap(j2); } -#endif +// namespace std -} // namespace std +#endif /// @brief user-defined string literal for JSON values /// @sa https://json.nlohmann.me/api/basic_json/operator_literal_json/ diff --git a/single_include/nlohmann/json.hpp b/single_include/nlohmann/json.hpp index 8e933daa6..dc7cd1ff6 100644 --- a/single_include/nlohmann/json.hpp +++ b/single_include/nlohmann/json.hpp @@ -22208,20 +22208,16 @@ std::string to_string(const NLOHMANN_BASIC_JSON_TPL& j) // nonmember support // /////////////////////// -// specialization of std::swap, and std::hash -namespace std -{ - /// hash value for JSON objects -template<> -struct hash +template +struct std::hash { /*! @brief return a hash value for a JSON object - @since version 1.0.0 + @since version 1.0.0, extended for arbitrary basic_json types in 3.10.5. */ - std::size_t operator()(const nlohmann::json& j) const + std::size_t operator()(const BasicJsonType& j) const { return nlohmann::detail::hash(j); } @@ -22231,7 +22227,7 @@ struct hash /// @note: do not remove the space after '<', /// see https://github.com/nlohmann/json/pull/679 template<> -struct less<::nlohmann::detail::value_t> +struct std::less< ::nlohmann::detail::value_t> { /*! @brief compare two value_t enum values @@ -22247,6 +22243,9 @@ struct less<::nlohmann::detail::value_t> // C++20 prohibit function specialization in the std namespace. #ifndef JSON_HAS_CPP_20 +namespace std +{ + /*! @brief exchanges the values of two JSON objects @@ -22261,9 +22260,9 @@ inline void swap(nlohmann::json& j1, nlohmann::json& j2) noexcep j1.swap(j2); } -#endif +// namespace std -} // namespace std +#endif /// @brief user-defined string literal for JSON values /// @sa https://json.nlohmann.me/api/basic_json/operator_literal_json/ diff --git a/test/src/unit-hash.cpp b/test/src/unit-hash.cpp index 28970d129..7abec52d1 100644 --- a/test/src/unit-hash.cpp +++ b/test/src/unit-hash.cpp @@ -31,10 +31,11 @@ SOFTWARE. #include using json = nlohmann::json; +using ordered_json = nlohmann::ordered_json; #include -TEST_CASE("hash") +TEST_CASE("hash") { // Collect hashes for different JSON values and make sure that they are distinct // We cannot compare against fixed values, because the implementation of @@ -82,3 +83,52 @@ TEST_CASE("hash") CHECK(hashes.size() == 21); } + +TEST_CASE("hash") +{ + // Collect hashes for different JSON values and make sure that they are distinct + // We cannot compare against fixed values, because the implementation of + // std::hash may differ between compilers. + + std::set hashes; + + // null + hashes.insert(std::hash {}(ordered_json(nullptr))); + + // boolean + hashes.insert(std::hash {}(ordered_json(true))); + hashes.insert(std::hash {}(ordered_json(false))); + + // string + hashes.insert(std::hash {}(ordered_json(""))); + hashes.insert(std::hash {}(ordered_json("foo"))); + + // number + hashes.insert(std::hash {}(ordered_json(0))); + hashes.insert(std::hash {}(ordered_json(unsigned(0)))); + + hashes.insert(std::hash {}(ordered_json(-1))); + hashes.insert(std::hash {}(ordered_json(0.0))); + hashes.insert(std::hash {}(ordered_json(42.23))); + + // array + hashes.insert(std::hash {}(ordered_json::array())); + hashes.insert(std::hash {}(ordered_json::array({1, 2, 3}))); + + // object + hashes.insert(std::hash {}(ordered_json::object())); + hashes.insert(std::hash {}(ordered_json::object({{"foo", "bar"}}))); + + // binary + hashes.insert(std::hash {}(ordered_json::binary({}))); + hashes.insert(std::hash {}(ordered_json::binary({}, 0))); + hashes.insert(std::hash {}(ordered_json::binary({}, 42))); + hashes.insert(std::hash {}(ordered_json::binary({1, 2, 3}))); + hashes.insert(std::hash {}(ordered_json::binary({1, 2, 3}, 0))); + hashes.insert(std::hash {}(ordered_json::binary({1, 2, 3}, 42))); + + // discarded + hashes.insert(std::hash {}(ordered_json(ordered_json::value_t::discarded))); + + CHECK(hashes.size() == 21); +}