diff --git a/include/nlohmann/detail/macro_scope.hpp b/include/nlohmann/detail/macro_scope.hpp index 2be7581d..27dddc6b 100644 --- a/include/nlohmann/detail/macro_scope.hpp +++ b/include/nlohmann/detail/macro_scope.hpp @@ -78,30 +78,30 @@ @def NLOHMANN_JSON_SERIALIZE_ENUM @since version 3.4.0 */ -#define NLOHMANN_JSON_SERIALIZE_ENUM(ENUM_TYPE, ...) \ - template \ - inline void to_json(BasicJsonType& j, const ENUM_TYPE& e) \ - { \ - static_assert(std::is_enum::value, #ENUM_TYPE " must be an enum!"); \ - static const std::pair m[] = __VA_ARGS__; \ - auto it = std::find_if(std::begin(m), std::end(m), \ - [e](const std::pair& ej_pair) -> bool \ - { \ - return ej_pair.first == e; \ - }); \ - j = ((it != std::end(m)) ? it : std::begin(m))->second; \ - } \ - template \ - inline void from_json(const BasicJsonType& j, ENUM_TYPE& e) \ - { \ - static_assert(std::is_enum::value, #ENUM_TYPE " must be an enum!"); \ - static const std::pair m[] = __VA_ARGS__; \ - auto it = std::find_if(std::begin(m), std::end(m), \ - [j](const std::pair& ej_pair) -> bool \ - { \ - return ej_pair.second == j; \ - }); \ - e = ((it != std::end(m)) ? it : std::begin(m))->first; \ +#define NLOHMANN_JSON_SERIALIZE_ENUM(ENUM_TYPE, ...) \ + template \ + inline void to_json(BasicJsonType& j, const ENUM_TYPE& e) \ + { \ + static_assert(std::is_enum::value, #ENUM_TYPE " must be an enum!"); \ + static const std::pair m[] = __VA_ARGS__; \ + auto it = std::find_if(std::begin(m), std::end(m), \ + [e](const std::pair& ej_pair) -> bool \ + { \ + return ej_pair.first == e; \ + }); \ + j = ((it != std::end(m)) ? it : std::begin(m))->second; \ + } \ + template \ + inline void from_json(const BasicJsonType& j, ENUM_TYPE& e) \ + { \ + static_assert(std::is_enum::value, #ENUM_TYPE " must be an enum!"); \ + static const std::pair m[] = __VA_ARGS__; \ + auto it = std::find_if(std::begin(m), std::end(m), \ + [&j](const std::pair& ej_pair) -> bool \ + { \ + return ej_pair.second == j; \ + }); \ + e = ((it != std::end(m)) ? it : std::begin(m))->first; \ } // Ugly macros to avoid uglier copy-paste when specializing basic_json. They diff --git a/include/nlohmann/json.hpp b/include/nlohmann/json.hpp index d63ffb92..a1958a34 100644 --- a/include/nlohmann/json.hpp +++ b/include/nlohmann/json.hpp @@ -2633,11 +2633,11 @@ class basic_json detail::has_non_default_from_json::value, int> = 0> ValueType get() const noexcept(noexcept( - JSONSerializer::from_json(std::declval()))) + JSONSerializer::from_json(std::declval()))) { static_assert(not std::is_reference::value, "get() cannot be used with reference types, you might want to use get_ref()"); - return JSONSerializer::from_json(*this); + return JSONSerializer::from_json(*this); } /*! @@ -8062,7 +8062,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 less<::nlohmann::detail::value_t> { /*! @brief compare two value_t enum values diff --git a/single_include/nlohmann/json.hpp b/single_include/nlohmann/json.hpp index b0ce05fd..891cab99 100644 --- a/single_include/nlohmann/json.hpp +++ b/single_include/nlohmann/json.hpp @@ -1782,30 +1782,30 @@ JSON_HEDLEY_DIAGNOSTIC_POP @def NLOHMANN_JSON_SERIALIZE_ENUM @since version 3.4.0 */ -#define NLOHMANN_JSON_SERIALIZE_ENUM(ENUM_TYPE, ...) \ - template \ - inline void to_json(BasicJsonType& j, const ENUM_TYPE& e) \ - { \ - static_assert(std::is_enum::value, #ENUM_TYPE " must be an enum!"); \ - static const std::pair m[] = __VA_ARGS__; \ - auto it = std::find_if(std::begin(m), std::end(m), \ - [e](const std::pair& ej_pair) -> bool \ - { \ - return ej_pair.first == e; \ - }); \ - j = ((it != std::end(m)) ? it : std::begin(m))->second; \ - } \ - template \ - inline void from_json(const BasicJsonType& j, ENUM_TYPE& e) \ - { \ - static_assert(std::is_enum::value, #ENUM_TYPE " must be an enum!"); \ - static const std::pair m[] = __VA_ARGS__; \ - auto it = std::find_if(std::begin(m), std::end(m), \ - [j](const std::pair& ej_pair) -> bool \ - { \ - return ej_pair.second == j; \ - }); \ - e = ((it != std::end(m)) ? it : std::begin(m))->first; \ +#define NLOHMANN_JSON_SERIALIZE_ENUM(ENUM_TYPE, ...) \ + template \ + inline void to_json(BasicJsonType& j, const ENUM_TYPE& e) \ + { \ + static_assert(std::is_enum::value, #ENUM_TYPE " must be an enum!"); \ + static const std::pair m[] = __VA_ARGS__; \ + auto it = std::find_if(std::begin(m), std::end(m), \ + [e](const std::pair& ej_pair) -> bool \ + { \ + return ej_pair.first == e; \ + }); \ + j = ((it != std::end(m)) ? it : std::begin(m))->second; \ + } \ + template \ + inline void from_json(const BasicJsonType& j, ENUM_TYPE& e) \ + { \ + static_assert(std::is_enum::value, #ENUM_TYPE " must be an enum!"); \ + static const std::pair m[] = __VA_ARGS__; \ + auto it = std::find_if(std::begin(m), std::end(m), \ + [&j](const std::pair& ej_pair) -> bool \ + { \ + return ej_pair.second == j; \ + }); \ + e = ((it != std::end(m)) ? it : std::begin(m))->first; \ } // Ugly macros to avoid uglier copy-paste when specializing basic_json. They @@ -17176,11 +17176,11 @@ class basic_json detail::has_non_default_from_json::value, int> = 0> ValueType get() const noexcept(noexcept( - JSONSerializer::from_json(std::declval()))) + JSONSerializer::from_json(std::declval()))) { static_assert(not std::is_reference::value, "get() cannot be used with reference types, you might want to use get_ref()"); - return JSONSerializer::from_json(*this); + return JSONSerializer::from_json(*this); } /*! diff --git a/test/src/unit-regression.cpp b/test/src/unit-regression.cpp index 1a60efdc..6b2e94a1 100644 --- a/test/src/unit-regression.cpp +++ b/test/src/unit-regression.cpp @@ -159,6 +159,39 @@ bool operator==(Data const& lhs, Data const& rhs) using float_json = nlohmann::basic_json; +///////////////////////////////////////////////////////////////////// +// for #1647 +///////////////////////////////////////////////////////////////////// +namespace +{ +struct NonDefaultFromJsonStruct { }; + +inline bool operator== (NonDefaultFromJsonStruct const& lhs, NonDefaultFromJsonStruct const& rhs) +{ + return true; +} + +enum class for_1647 { one, two }; + +NLOHMANN_JSON_SERIALIZE_ENUM(for_1647, +{ + {for_1647::one, "one"}, + {for_1647::two, "two"}, +}) +} + +namespace nlohmann +{ +template <> +struct adl_serializer +{ + static NonDefaultFromJsonStruct from_json (json const& j) + { + return {}; + } +}; +} + ///////////////////////////////////////////////////////////////////// // for #1805 ///////////////////////////////////////////////////////////////////// @@ -1836,6 +1869,13 @@ TEST_CASE("regression tests") CHECK(j.contains(jptr1)); CHECK(j.contains(jptr2)); } + + SECTION("issue #1647 - compile error when deserializing enum if both non-default from_json and non-member operator== exists for other type") + { + auto val = nlohmann::json("one").get(); + CHECK(val == for_1647::one); + } + SECTION("issue #1805 - A pair is json constructible only if T1 and T2 are json constructible") { static_assert(!std::is_constructible>::value, "");