diff --git a/include/nlohmann/detail/conversions/to_json.hpp b/include/nlohmann/detail/conversions/to_json.hpp index 8f2bd266..0a802369 100644 --- a/include/nlohmann/detail/conversions/to_json.hpp +++ b/include/nlohmann/detail/conversions/to_json.hpp @@ -253,7 +253,8 @@ template ::value and not is_compatible_object_type< BasicJsonType, CompatibleArrayType>::value and - not is_compatible_string_type::value, + not is_compatible_string_type::value and + not is_basic_json::value, int> = 0> void to_json(BasicJsonType& j, const CompatibleArrayType& arr) { @@ -274,7 +275,7 @@ void to_json(BasicJsonType& j, typename BasicJsonType::array_t&& arr) } template::value, int> = 0> + enable_if_t::value and not is_basic_json::value, int> = 0> void to_json(BasicJsonType& j, const CompatibleObjectType& obj) { external_constructor::construct(j, obj); diff --git a/include/nlohmann/detail/meta/type_traits.hpp b/include/nlohmann/detail/meta/type_traits.hpp index 0383472b..b358de65 100644 --- a/include/nlohmann/detail/meta/type_traits.hpp +++ b/include/nlohmann/detail/meta/type_traits.hpp @@ -44,6 +44,18 @@ using key_type_t = typename T::key_type; template using value_type_t = typename T::value_type; +template +using difference_type_t = typename T::difference_type; + +template +using pointer_t = typename T::pointer; + +template +using reference_t = typename T::reference; + +template +using iterator_category_t = typename T::iterator_category; + template using iterator_t = typename T::iterator; @@ -57,6 +69,24 @@ using from_json_function = decltype(T::from_json(std::declval()...)); // is_ functions // /////////////////// +template +struct is_iterator_traits : std::false_type {}; + +template +struct is_iterator_traits> +{ + private: + using traits = std::iterator_traits; + + public: + static constexpr auto value = + is_detected::value && + is_detected::value && + is_detected::value && + is_detected::value && + is_detected::value; +}; + // source: https://stackoverflow.com/a/37193089/4116453 template @@ -108,15 +138,6 @@ template struct is_compatible_string_type : is_compatible_string_type_impl {}; -template -struct is_basic_json_nested_type -{ - static auto constexpr value = std::is_same::value or - std::is_same::value or - std::is_same::value or - std::is_same::value; -}; - template struct is_compatible_array_type_impl : std::false_type {}; @@ -126,8 +147,10 @@ struct is_compatible_array_type_impl < enable_if_t::value and is_detected::value >> { - static constexpr auto value = not( - is_basic_json_nested_type::value); + // This is needed because json_reverse_iterator has a ::iterator type... + // Therefore it is detected as a CompatibleArrayType. + // The real fix would be to have an Iterable concept. + static constexpr bool value = not is_iterator_traits>::value; }; template @@ -204,9 +227,6 @@ struct is_compatible_type_impl < enable_if_t::value >> { static constexpr bool value = - not std::is_base_of::value and - not is_basic_json::value and - not is_basic_json_nested_type::value and has_to_json::value; }; diff --git a/include/nlohmann/json.hpp b/include/nlohmann/json.hpp index 1f39e3ec..ee78c1c1 100644 --- a/include/nlohmann/json.hpp +++ b/include/nlohmann/json.hpp @@ -1243,7 +1243,7 @@ class basic_json template , detail::enable_if_t< - detail::is_compatible_type::value, int> = 0> + not detail::is_basic_json::value and detail::is_compatible_type::value, int> = 0> basic_json(CompatibleType && val) noexcept(noexcept( JSONSerializer::to_json(std::declval(), std::forward(val)))) diff --git a/single_include/nlohmann/json.hpp b/single_include/nlohmann/json.hpp index 1754c9a9..96e469ee 100644 --- a/single_include/nlohmann/json.hpp +++ b/single_include/nlohmann/json.hpp @@ -404,6 +404,18 @@ using key_type_t = typename T::key_type; template using value_type_t = typename T::value_type; +template +using difference_type_t = typename T::difference_type; + +template +using pointer_t = typename T::pointer; + +template +using reference_t = typename T::reference; + +template +using iterator_category_t = typename T::iterator_category; + template using iterator_t = typename T::iterator; @@ -417,6 +429,24 @@ using from_json_function = decltype(T::from_json(std::declval()...)); // is_ functions // /////////////////// +template +struct is_iterator_traits : std::false_type {}; + +template +struct is_iterator_traits> +{ + private: + using traits = std::iterator_traits; + + public: + static constexpr auto value = + is_detected::value && + is_detected::value && + is_detected::value && + is_detected::value && + is_detected::value; +}; + // source: https://stackoverflow.com/a/37193089/4116453 template @@ -468,15 +498,6 @@ template struct is_compatible_string_type : is_compatible_string_type_impl {}; -template -struct is_basic_json_nested_type -{ - static auto constexpr value = std::is_same::value or - std::is_same::value or - std::is_same::value or - std::is_same::value; -}; - template struct is_compatible_array_type_impl : std::false_type {}; @@ -486,8 +507,10 @@ struct is_compatible_array_type_impl < enable_if_t::value and is_detected::value >> { - static constexpr auto value = not( - is_basic_json_nested_type::value); + // This is needed because json_reverse_iterator has a ::iterator type... + // Therefore it is detected as a CompatibleArrayType. + // The real fix would be to have an Iterable concept. + static constexpr bool value = not is_iterator_traits>::value; }; template @@ -564,9 +587,6 @@ struct is_compatible_type_impl < enable_if_t::value >> { static constexpr bool value = - not std::is_base_of::value and - not is_basic_json::value and - not is_basic_json_nested_type::value and has_to_json::value; }; @@ -1752,7 +1772,8 @@ template ::value and not is_compatible_object_type< BasicJsonType, CompatibleArrayType>::value and - not is_compatible_string_type::value, + not is_compatible_string_type::value and + not is_basic_json::value, int> = 0> void to_json(BasicJsonType& j, const CompatibleArrayType& arr) { @@ -1773,7 +1794,7 @@ void to_json(BasicJsonType& j, typename BasicJsonType::array_t&& arr) } template::value, int> = 0> + enable_if_t::value and not is_basic_json::value, int> = 0> void to_json(BasicJsonType& j, const CompatibleObjectType& obj) { external_constructor::construct(j, obj); @@ -12292,7 +12313,7 @@ class basic_json template , detail::enable_if_t< - detail::is_compatible_type::value, int> = 0> + not detail::is_basic_json::value and detail::is_compatible_type::value, int> = 0> basic_json(CompatibleType && val) noexcept(noexcept( JSONSerializer::to_json(std::declval(), std::forward(val))))