From aea648bb7a89dcb99ed683825f7e4a42d678077c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9o=20DELRIEU?= <theo.delrieu@tanker.io> Date: Fri, 7 Sep 2018 12:42:49 +0200 Subject: [PATCH] remove now-useless traits. check for is_basic_json where needed --- .../nlohmann/detail/conversions/to_json.hpp | 5 +- include/nlohmann/detail/meta/type_traits.hpp | 48 +++++++++++----- include/nlohmann/json.hpp | 2 +- single_include/nlohmann/json.hpp | 55 +++++++++++++------ 4 files changed, 76 insertions(+), 34 deletions(-) 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 <typename BasicJsonType, typename CompatibleArrayType, CompatibleArrayType>::value and not is_compatible_object_type< BasicJsonType, CompatibleArrayType>::value and - not is_compatible_string_type<BasicJsonType, CompatibleArrayType>::value, + not is_compatible_string_type<BasicJsonType, CompatibleArrayType>::value and + not is_basic_json<CompatibleArrayType>::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<typename BasicJsonType, typename CompatibleObjectType, - enable_if_t<is_compatible_object_type<BasicJsonType, CompatibleObjectType>::value, int> = 0> + enable_if_t<is_compatible_object_type<BasicJsonType, CompatibleObjectType>::value and not is_basic_json<CompatibleObjectType>::value, int> = 0> void to_json(BasicJsonType& j, const CompatibleObjectType& obj) { external_constructor<value_t::object>::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 <typename T> using value_type_t = typename T::value_type; +template <typename T> +using difference_type_t = typename T::difference_type; + +template <typename T> +using pointer_t = typename T::pointer; + +template <typename T> +using reference_t = typename T::reference; + +template <typename T> +using iterator_category_t = typename T::iterator_category; + template <typename T> using iterator_t = typename T::iterator; @@ -57,6 +69,24 @@ using from_json_function = decltype(T::from_json(std::declval<Args>()...)); // is_ functions // /////////////////// +template <typename T, typename = void> +struct is_iterator_traits : std::false_type {}; + +template <typename T> +struct is_iterator_traits<std::iterator_traits<T>> +{ + private: + using traits = std::iterator_traits<T>; + + public: + static constexpr auto value = + is_detected<value_type_t, traits>::value && + is_detected<difference_type_t, traits>::value && + is_detected<pointer_t, traits>::value && + is_detected<iterator_category_t, traits>::value && + is_detected<reference_t, traits>::value; +}; + // source: https://stackoverflow.com/a/37193089/4116453 template <typename T, typename = void> @@ -108,15 +138,6 @@ template <typename BasicJsonType, typename CompatibleStringType> struct is_compatible_string_type : is_compatible_string_type_impl<BasicJsonType, CompatibleStringType> {}; -template<typename BasicJsonType, typename T> -struct is_basic_json_nested_type -{ - static auto constexpr value = std::is_same<T, typename BasicJsonType::iterator>::value or - std::is_same<T, typename BasicJsonType::const_iterator>::value or - std::is_same<T, typename BasicJsonType::reverse_iterator>::value or - std::is_same<T, typename BasicJsonType::const_reverse_iterator>::value; -}; - template <typename BasicJsonType, typename CompatibleArrayType, typename = void> struct is_compatible_array_type_impl : std::false_type {}; @@ -126,8 +147,10 @@ struct is_compatible_array_type_impl < enable_if_t<is_detected<value_type_t, CompatibleArrayType>::value and is_detected<iterator_t, CompatibleArrayType>::value >> { - static constexpr auto value = not( - is_basic_json_nested_type<BasicJsonType, CompatibleArrayType>::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<std::iterator_traits<CompatibleArrayType>>::value; }; template <typename BasicJsonType, typename CompatibleArrayType> @@ -204,9 +227,6 @@ struct is_compatible_type_impl < enable_if_t<is_complete_type<CompatibleType>::value >> { static constexpr bool value = - not std::is_base_of<std::istream, CompatibleType>::value and - not is_basic_json<CompatibleType>::value and - not is_basic_json_nested_type<BasicJsonType, CompatibleType>::value and has_to_json<BasicJsonType, CompatibleType>::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 <typename CompatibleType, typename U = detail::uncvref_t<CompatibleType>, detail::enable_if_t< - detail::is_compatible_type<basic_json_t, U>::value, int> = 0> + not detail::is_basic_json<U>::value and detail::is_compatible_type<basic_json_t, U>::value, int> = 0> basic_json(CompatibleType && val) noexcept(noexcept( JSONSerializer<U>::to_json(std::declval<basic_json_t&>(), std::forward<CompatibleType>(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 <typename T> using value_type_t = typename T::value_type; +template <typename T> +using difference_type_t = typename T::difference_type; + +template <typename T> +using pointer_t = typename T::pointer; + +template <typename T> +using reference_t = typename T::reference; + +template <typename T> +using iterator_category_t = typename T::iterator_category; + template <typename T> using iterator_t = typename T::iterator; @@ -417,6 +429,24 @@ using from_json_function = decltype(T::from_json(std::declval<Args>()...)); // is_ functions // /////////////////// +template <typename T, typename = void> +struct is_iterator_traits : std::false_type {}; + +template <typename T> +struct is_iterator_traits<std::iterator_traits<T>> +{ + private: + using traits = std::iterator_traits<T>; + + public: + static constexpr auto value = + is_detected<value_type_t, traits>::value && + is_detected<difference_type_t, traits>::value && + is_detected<pointer_t, traits>::value && + is_detected<iterator_category_t, traits>::value && + is_detected<reference_t, traits>::value; +}; + // source: https://stackoverflow.com/a/37193089/4116453 template <typename T, typename = void> @@ -468,15 +498,6 @@ template <typename BasicJsonType, typename CompatibleStringType> struct is_compatible_string_type : is_compatible_string_type_impl<BasicJsonType, CompatibleStringType> {}; -template<typename BasicJsonType, typename T> -struct is_basic_json_nested_type -{ - static auto constexpr value = std::is_same<T, typename BasicJsonType::iterator>::value or - std::is_same<T, typename BasicJsonType::const_iterator>::value or - std::is_same<T, typename BasicJsonType::reverse_iterator>::value or - std::is_same<T, typename BasicJsonType::const_reverse_iterator>::value; -}; - template <typename BasicJsonType, typename CompatibleArrayType, typename = void> struct is_compatible_array_type_impl : std::false_type {}; @@ -486,8 +507,10 @@ struct is_compatible_array_type_impl < enable_if_t<is_detected<value_type_t, CompatibleArrayType>::value and is_detected<iterator_t, CompatibleArrayType>::value >> { - static constexpr auto value = not( - is_basic_json_nested_type<BasicJsonType, CompatibleArrayType>::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<std::iterator_traits<CompatibleArrayType>>::value; }; template <typename BasicJsonType, typename CompatibleArrayType> @@ -564,9 +587,6 @@ struct is_compatible_type_impl < enable_if_t<is_complete_type<CompatibleType>::value >> { static constexpr bool value = - not std::is_base_of<std::istream, CompatibleType>::value and - not is_basic_json<CompatibleType>::value and - not is_basic_json_nested_type<BasicJsonType, CompatibleType>::value and has_to_json<BasicJsonType, CompatibleType>::value; }; @@ -1752,7 +1772,8 @@ template <typename BasicJsonType, typename CompatibleArrayType, CompatibleArrayType>::value and not is_compatible_object_type< BasicJsonType, CompatibleArrayType>::value and - not is_compatible_string_type<BasicJsonType, CompatibleArrayType>::value, + not is_compatible_string_type<BasicJsonType, CompatibleArrayType>::value and + not is_basic_json<CompatibleArrayType>::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<typename BasicJsonType, typename CompatibleObjectType, - enable_if_t<is_compatible_object_type<BasicJsonType, CompatibleObjectType>::value, int> = 0> + enable_if_t<is_compatible_object_type<BasicJsonType, CompatibleObjectType>::value and not is_basic_json<CompatibleObjectType>::value, int> = 0> void to_json(BasicJsonType& j, const CompatibleObjectType& obj) { external_constructor<value_t::object>::construct(j, obj); @@ -12292,7 +12313,7 @@ class basic_json template <typename CompatibleType, typename U = detail::uncvref_t<CompatibleType>, detail::enable_if_t< - detail::is_compatible_type<basic_json_t, U>::value, int> = 0> + not detail::is_basic_json<U>::value and detail::is_compatible_type<basic_json_t, U>::value, int> = 0> basic_json(CompatibleType && val) noexcept(noexcept( JSONSerializer<U>::to_json(std::declval<basic_json_t&>(), std::forward<CompatibleType>(val))))