diff --git a/include/nlohmann/adl_serializer.hpp b/include/nlohmann/adl_serializer.hpp index 53c9009f0b..54e9aac6b7 100644 --- a/include/nlohmann/adl_serializer.hpp +++ b/include/nlohmann/adl_serializer.hpp @@ -20,8 +20,10 @@ struct adl_serializer @param[in,out] val value to write to */ template - static void from_json(BasicJsonType&& j, ValueType& val) noexcept( - noexcept(::nlohmann::from_json(std::forward(j), val))) + static auto from_json(BasicJsonType&& j, ValueType& val) noexcept( + noexcept(::nlohmann::from_json(std::forward(j), val))) -> decltype( + ::nlohmann::from_json(std::forward(j), val) + ) { ::nlohmann::from_json(std::forward(j), val); } @@ -35,9 +37,11 @@ struct adl_serializer @param[in,out] j JSON value to write to @param[in] val value to read from */ - template - static void to_json(BasicJsonType& j, ValueType&& val) noexcept( + template + static auto to_json(BasicJsonType& j, ValueType&& val) noexcept( noexcept(::nlohmann::to_json(j, std::forward(val)))) + -> decltype(::nlohmann::to_json(j, std::forward(val)), + void()) { ::nlohmann::to_json(j, std::forward(val)); } diff --git a/include/nlohmann/detail/conversions/from_json.hpp b/include/nlohmann/detail/conversions/from_json.hpp index 5956352fb9..2375d0660b 100644 --- a/include/nlohmann/detail/conversions/from_json.hpp +++ b/include/nlohmann/detail/conversions/from_json.hpp @@ -127,16 +127,6 @@ void from_json(const BasicJsonType& j, EnumType& e) e = static_cast(val); } -template -void from_json(const BasicJsonType& j, typename BasicJsonType::array_t& arr) -{ - if (JSON_UNLIKELY(not j.is_array())) - { - JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name()))); - } - arr = *j.template get_ptr(); -} - // forward_list doesn't have an insert method template::value, int> = 0> @@ -166,24 +156,28 @@ void from_json(const BasicJsonType& j, std::valarray& l) std::copy(j.m_value.array->begin(), j.m_value.array->end(), std::begin(l)); } -template -void from_json_array_impl(const BasicJsonType& j, CompatibleArrayType& arr, priority_tag<0> /*unused*/) +template +void from_json_array_impl(const BasicJsonType& j, typename BasicJsonType::array_t& arr, priority_tag<3> /*unused*/) { - using std::end; + arr = *j.template get_ptr(); +} - std::transform(j.begin(), j.end(), - std::inserter(arr, end(arr)), [](const BasicJsonType & i) +template +auto from_json_array_impl(const BasicJsonType& j, std::array& arr, + priority_tag<2> /*unused*/) +-> decltype(j.template get(), void()) +{ + for (std::size_t i = 0; i < N; ++i) { - // get() returns *this, this won't call a from_json - // method when value_type is BasicJsonType - return i.template get(); - }); + arr[i] = j.at(i).template get(); + } } template auto from_json_array_impl(const BasicJsonType& j, CompatibleArrayType& arr, priority_tag<1> /*unused*/) -> decltype( arr.reserve(std::declval()), + j.template get(), void()) { using std::end; @@ -198,25 +192,34 @@ auto from_json_array_impl(const BasicJsonType& j, CompatibleArrayType& arr, prio }); } -template -void from_json_array_impl(const BasicJsonType& j, std::array& arr, priority_tag<2> /*unused*/) +template +void from_json_array_impl(const BasicJsonType& j, CompatibleArrayType& arr, + priority_tag<0> /*unused*/) { - for (std::size_t i = 0; i < N; ++i) + using std::end; + + std::transform( + j.begin(), j.end(), std::inserter(arr, end(arr)), + [](const BasicJsonType & i) { - arr[i] = j.at(i).template get(); - } + // get() returns *this, this won't call a from_json + // method when value_type is BasicJsonType + return i.template get(); + }); } -template < - typename BasicJsonType, typename CompatibleArrayType, - enable_if_t < - is_compatible_array_type::value and - not std::is_same::value and - std::is_constructible < - BasicJsonType, typename CompatibleArrayType::value_type >::value, - int > = 0 > -void from_json(const BasicJsonType& j, CompatibleArrayType& arr) +template ::value and + not is_compatible_object_type::value and + not is_compatible_string_type::value and + not is_basic_json::value, + int > = 0 > + +auto from_json(const BasicJsonType& j, CompatibleArrayType& arr) +-> decltype(from_json_array_impl(j, arr, priority_tag<3> {}), +j.template get(), +void()) { if (JSON_UNLIKELY(not j.is_array())) { @@ -224,7 +227,7 @@ void from_json(const BasicJsonType& j, CompatibleArrayType& arr) std::string(j.type_name()))); } - from_json_array_impl(j, arr, priority_tag<2> {}); + from_json_array_impl(j, arr, priority_tag<3> {}); } template - auto call(const BasicJsonType& j, T& val, priority_tag<1> /*unused*/) const + auto operator()(const BasicJsonType& j, T& val) const noexcept(noexcept(from_json(j, val))) -> decltype(from_json(j, val), void()) { return from_json(j, val); } - - template - void call(const BasicJsonType& /*unused*/, T& /*unused*/, priority_tag<0> /*unused*/) const noexcept - { - static_assert(sizeof(BasicJsonType) == 0, - "could not find from_json() method in T's namespace"); -#ifdef _MSC_VER - // MSVC does not show a stacktrace for the above assert - using decayed = uncvref_t; - static_assert(sizeof(typename decayed::force_msvc_stacktrace) == 0, - "forcing MSVC stacktrace to show which T we're talking about."); -#endif - } - - public: - template - void operator()(const BasicJsonType& j, T& val) const - noexcept(noexcept(std::declval().call(j, val, priority_tag<1> {}))) - { - return call(j, val, priority_tag<1> {}); - } }; } diff --git a/include/nlohmann/detail/conversions/to_json.hpp b/include/nlohmann/detail/conversions/to_json.hpp index 04c93be199..8f2bd2660c 100644 --- a/include/nlohmann/detail/conversions/to_json.hpp +++ b/include/nlohmann/detail/conversions/to_json.hpp @@ -252,7 +252,8 @@ template ::value and not is_compatible_object_type< - BasicJsonType, CompatibleArrayType>::value, + BasicJsonType, CompatibleArrayType>::value and + not is_compatible_string_type::value, int> = 0> void to_json(BasicJsonType& j, const CompatibleArrayType& arr) { @@ -285,9 +286,12 @@ void to_json(BasicJsonType& j, typename BasicJsonType::object_t&& obj) external_constructor::construct(j, std::move(obj)); } -template::value, int> = 0> -void to_json(BasicJsonType& j, T (&arr)[N]) +template < + typename BasicJsonType, typename T, std::size_t N, + enable_if_t::value, + int> = 0 > +void to_json(BasicJsonType& j, const T (&arr)[N]) { external_constructor::construct(j, arr); } @@ -320,35 +324,12 @@ void to_json(BasicJsonType& j, const std::tuple& t) struct to_json_fn { - private: template - auto call(BasicJsonType& j, T&& val, priority_tag<1> /*unused*/) const noexcept(noexcept(to_json(j, std::forward(val)))) + auto operator()(BasicJsonType& j, T&& val) const noexcept(noexcept(to_json(j, std::forward(val)))) -> decltype(to_json(j, std::forward(val)), void()) { return to_json(j, std::forward(val)); } - - template - void call(BasicJsonType& /*unused*/, T&& /*unused*/, priority_tag<0> /*unused*/) const noexcept - { - static_assert(sizeof(BasicJsonType) == 0, - "could not find to_json() method in T's namespace"); - -#ifdef _MSC_VER - // MSVC does not show a stacktrace for the above assert - using decayed = uncvref_t; - static_assert(sizeof(typename decayed::force_msvc_stacktrace) == 0, - "forcing MSVC stacktrace to show which T we're talking about."); -#endif - } - - public: - template - void operator()(BasicJsonType& j, T&& val) const - noexcept(noexcept(std::declval().call(j, std::forward(val), priority_tag<1> {}))) - { - return call(j, std::forward(val), priority_tag<1> {}); - } }; } diff --git a/include/nlohmann/detail/meta/type_traits.hpp b/include/nlohmann/detail/meta/type_traits.hpp index 39ef6f7545..0383472b17 100644 --- a/include/nlohmann/detail/meta/type_traits.hpp +++ b/include/nlohmann/detail/meta/type_traits.hpp @@ -127,9 +127,6 @@ struct is_compatible_array_type_impl < is_detected::value >> { static constexpr auto value = not( - is_compatible_object_type::value or - std::is_constructible::value or is_basic_json_nested_type::value); }; diff --git a/single_include/nlohmann/json.hpp b/single_include/nlohmann/json.hpp index ab3a13cdfc..0b4d46022f 100644 --- a/single_include/nlohmann/json.hpp +++ b/single_include/nlohmann/json.hpp @@ -484,9 +484,6 @@ struct is_compatible_array_type_impl < is_detected::value >> { static constexpr auto value = not( - is_compatible_object_type::value or - std::is_constructible::value or is_basic_json_nested_type::value); }; @@ -1121,16 +1118,6 @@ void from_json(const BasicJsonType& j, EnumType& e) e = static_cast(val); } -template -void from_json(const BasicJsonType& j, typename BasicJsonType::array_t& arr) -{ - if (JSON_UNLIKELY(not j.is_array())) - { - JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name()))); - } - arr = *j.template get_ptr(); -} - // forward_list doesn't have an insert method template::value, int> = 0> @@ -1160,24 +1147,28 @@ void from_json(const BasicJsonType& j, std::valarray& l) std::copy(j.m_value.array->begin(), j.m_value.array->end(), std::begin(l)); } -template -void from_json_array_impl(const BasicJsonType& j, CompatibleArrayType& arr, priority_tag<0> /*unused*/) +template +void from_json_array_impl(const BasicJsonType& j, typename BasicJsonType::array_t& arr, priority_tag<3> /*unused*/) { - using std::end; + arr = *j.template get_ptr(); +} - std::transform(j.begin(), j.end(), - std::inserter(arr, end(arr)), [](const BasicJsonType & i) +template +auto from_json_array_impl(const BasicJsonType& j, std::array& arr, + priority_tag<2> /*unused*/) +-> decltype(j.template get(), void()) +{ + for (std::size_t i = 0; i < N; ++i) { - // get() returns *this, this won't call a from_json - // method when value_type is BasicJsonType - return i.template get(); - }); + arr[i] = j.at(i).template get(); + } } template auto from_json_array_impl(const BasicJsonType& j, CompatibleArrayType& arr, priority_tag<1> /*unused*/) -> decltype( arr.reserve(std::declval()), + j.template get(), void()) { using std::end; @@ -1192,25 +1183,34 @@ auto from_json_array_impl(const BasicJsonType& j, CompatibleArrayType& arr, prio }); } -template -void from_json_array_impl(const BasicJsonType& j, std::array& arr, priority_tag<2> /*unused*/) +template +void from_json_array_impl(const BasicJsonType& j, CompatibleArrayType& arr, + priority_tag<0> /*unused*/) { - for (std::size_t i = 0; i < N; ++i) + using std::end; + + std::transform( + j.begin(), j.end(), std::inserter(arr, end(arr)), + [](const BasicJsonType & i) { - arr[i] = j.at(i).template get(); - } + // get() returns *this, this won't call a from_json + // method when value_type is BasicJsonType + return i.template get(); + }); } -template < - typename BasicJsonType, typename CompatibleArrayType, - enable_if_t < - is_compatible_array_type::value and - not std::is_same::value and - std::is_constructible < - BasicJsonType, typename CompatibleArrayType::value_type >::value, - int > = 0 > -void from_json(const BasicJsonType& j, CompatibleArrayType& arr) +template ::value and + not is_compatible_object_type::value and + not is_compatible_string_type::value and + not is_basic_json::value, + int > = 0 > + +auto from_json(const BasicJsonType& j, CompatibleArrayType& arr) +-> decltype(from_json_array_impl(j, arr, priority_tag<3> {}), +j.template get(), +void()) { if (JSON_UNLIKELY(not j.is_array())) { @@ -1218,7 +1218,7 @@ void from_json(const BasicJsonType& j, CompatibleArrayType& arr) std::string(j.type_name()))); } - from_json_array_impl(j, arr, priority_tag<2> {}); + from_json_array_impl(j, arr, priority_tag<3> {}); } template - auto call(const BasicJsonType& j, T& val, priority_tag<1> /*unused*/) const + auto operator()(const BasicJsonType& j, T& val) const noexcept(noexcept(from_json(j, val))) -> decltype(from_json(j, val), void()) { return from_json(j, val); } - - template - void call(const BasicJsonType& /*unused*/, T& /*unused*/, priority_tag<0> /*unused*/) const noexcept - { - static_assert(sizeof(BasicJsonType) == 0, - "could not find from_json() method in T's namespace"); -#ifdef _MSC_VER - // MSVC does not show a stacktrace for the above assert - using decayed = uncvref_t; - static_assert(sizeof(typename decayed::force_msvc_stacktrace) == 0, - "forcing MSVC stacktrace to show which T we're talking about."); -#endif - } - - public: - template - void operator()(const BasicJsonType& j, T& val) const - noexcept(noexcept(std::declval().call(j, val, priority_tag<1> {}))) - { - return call(j, val, priority_tag<1> {}); - } }; } @@ -1770,7 +1748,8 @@ template ::value and not is_compatible_object_type< - BasicJsonType, CompatibleArrayType>::value, + BasicJsonType, CompatibleArrayType>::value and + not is_compatible_string_type::value, int> = 0> void to_json(BasicJsonType& j, const CompatibleArrayType& arr) { @@ -1803,9 +1782,12 @@ void to_json(BasicJsonType& j, typename BasicJsonType::object_t&& obj) external_constructor::construct(j, std::move(obj)); } -template::value, int> = 0> -void to_json(BasicJsonType& j, T (&arr)[N]) +template < + typename BasicJsonType, typename T, std::size_t N, + enable_if_t::value, + int> = 0 > +void to_json(BasicJsonType& j, const T (&arr)[N]) { external_constructor::construct(j, arr); } @@ -1838,35 +1820,12 @@ void to_json(BasicJsonType& j, const std::tuple& t) struct to_json_fn { - private: template - auto call(BasicJsonType& j, T&& val, priority_tag<1> /*unused*/) const noexcept(noexcept(to_json(j, std::forward(val)))) + auto operator()(BasicJsonType& j, T&& val) const noexcept(noexcept(to_json(j, std::forward(val)))) -> decltype(to_json(j, std::forward(val)), void()) { return to_json(j, std::forward(val)); } - - template - void call(BasicJsonType& /*unused*/, T&& /*unused*/, priority_tag<0> /*unused*/) const noexcept - { - static_assert(sizeof(BasicJsonType) == 0, - "could not find to_json() method in T's namespace"); - -#ifdef _MSC_VER - // MSVC does not show a stacktrace for the above assert - using decayed = uncvref_t; - static_assert(sizeof(typename decayed::force_msvc_stacktrace) == 0, - "forcing MSVC stacktrace to show which T we're talking about."); -#endif - } - - public: - template - void operator()(BasicJsonType& j, T&& val) const - noexcept(noexcept(std::declval().call(j, std::forward(val), priority_tag<1> {}))) - { - return call(j, std::forward(val), priority_tag<1> {}); - } }; } @@ -11128,8 +11087,10 @@ struct adl_serializer @param[in,out] val value to write to */ template - static void from_json(BasicJsonType&& j, ValueType& val) noexcept( - noexcept(::nlohmann::from_json(std::forward(j), val))) + static auto from_json(BasicJsonType&& j, ValueType& val) noexcept( + noexcept(::nlohmann::from_json(std::forward(j), val))) -> decltype( + ::nlohmann::from_json(std::forward(j), val) + ) { ::nlohmann::from_json(std::forward(j), val); } @@ -11143,9 +11104,11 @@ struct adl_serializer @param[in,out] j JSON value to write to @param[in] val value to read from */ - template - static void to_json(BasicJsonType& j, ValueType&& val) noexcept( + template + static auto to_json(BasicJsonType& j, ValueType&& val) noexcept( noexcept(::nlohmann::to_json(j, std::forward(val)))) + -> decltype(::nlohmann::to_json(j, std::forward(val)), + void()) { ::nlohmann::to_json(j, std::forward(val)); }