diff --git a/src/json.hpp b/src/json.hpp index 29c1a7ab..2bc35c4a 100644 --- a/src/json.hpp +++ b/src/json.hpp @@ -204,14 +204,14 @@ using enable_if_t = typename std::enable_if::type; template using uncvref_t = typename std::remove_cv::type>::type; -// Taken from http://stackoverflow.com/questions/26936640/how-to-implement-is-enum-class-type-trait +// taken from http://stackoverflow.com/a/26936864/266378 template using is_unscoped_enum = std::integral_constant::value and std::is_enum::value>; /* -Implementation of 2 C++17 constructs: conjunction, negation. This is needed +Implementation of two C++17 constructs: conjunction, negation. This is needed to avoid evaluating all the traits in a condition For example: not std::is_same::value and has_value_type::value @@ -393,6 +393,7 @@ NLOHMANN_JSON_HAS_HELPER(iterator); #undef NLOHMANN_JSON_HAS_HELPER + template struct is_compatible_object_type_impl : std::false_type {}; @@ -468,7 +469,7 @@ struct is_compatible_integer_type }; -// This trait checks if JSONSerializer::from_json(json const&, udt&) exists +// trait checking if JSONSerializer::from_json(json const&, udt&) exists template struct has_from_json { @@ -530,8 +531,7 @@ void to_json(BasicJsonType& j, typename BasicJsonType::boolean_t b) noexcept template::value, - int> = 0> + CompatibleString>::value, int> = 0> void to_json(BasicJsonType& j, const CompatibleString& s) { external_constructor::construct(j, s); @@ -547,8 +547,7 @@ void to_json(BasicJsonType& j, FloatType val) noexcept template < typename BasicJsonType, typename CompatibleNumberUnsignedType, enable_if_t::value, - int> = 0 > + CompatibleNumberUnsignedType>::value, int> = 0 > void to_json(BasicJsonType& j, CompatibleNumberUnsignedType val) noexcept { external_constructor::construct(j, static_cast(val)); @@ -557,8 +556,7 @@ void to_json(BasicJsonType& j, CompatibleNumberUnsignedType val) noexcept template < typename BasicJsonType, typename CompatibleNumberIntegerType, enable_if_t::value, - int> = 0 > + CompatibleNumberIntegerType>::value, int> = 0 > void to_json(BasicJsonType& j, CompatibleNumberIntegerType val) noexcept { external_constructor::construct(j, static_cast(val)); @@ -690,7 +688,6 @@ void from_json(const BasicJsonType& j, typename BasicJsonType::array_t& arr) } // forward_list doesn't have an insert method -// TODO find a way to avoid including forward_list template void from_json(const BasicJsonType& j, std::forward_list& l) { @@ -781,14 +778,15 @@ void from_json(const BasicJsonType& j, CompatibleObjectType& obj) using std::begin; using std::end; // we could avoid the assignment, but this might require a for loop, which - // might be less efficient than the container constructor for some containers (would it?) + // might be less efficient than the container constructor for some + // containers (would it?) obj = CompatibleObjectType(begin(*inner_object), end(*inner_object)); } -// overload for arithmetic types, not chosen for basic_json template arguments (BooleanType, etc..) -// -// note: Is it really necessary to provide explicit overloads for boolean_t etc.. -// in case of a custom BooleanType which is not an arithmetic type? +// overload for arithmetic types, not chosen for basic_json template arguments +// (BooleanType, etc..); note: Is it really necessary to provide explicit +// overloads for boolean_t etc. in case of a custom BooleanType which is not +// an arithmetic type? template::value and @@ -802,19 +800,29 @@ void from_json(const BasicJsonType& j, ArithmeticType& val) switch (static_cast(j)) { case value_t::number_unsigned: + { val = static_cast(*j.template get_ptr()); break; + } case value_t::number_integer: + { val = static_cast(*j.template get_ptr()); break; + } case value_t::number_float: + { val = static_cast(*j.template get_ptr()); break; + } case value_t::boolean: + { val = static_cast(*j.template get_ptr()); break; + } default: + { JSON_THROW(std::domain_error("type must be number, but is " + j.type_name())); + } } } @@ -3160,8 +3168,7 @@ class basic_json detail::enable_if_t < not std::is_same::value and detail::has_from_json::value and - not detail::has_non_default_from_json::value, + not detail::has_non_default_from_json::value, int > = 0 > U get() const noexcept(noexcept(JSONSerializer::from_json( std::declval(), std::declval()))) @@ -3196,8 +3203,7 @@ class basic_json typename U = detail::uncvref_t, detail::enable_if_t::value and detail::has_non_default_from_json::value, - int> = 0 > + U>::value, int> = 0 > U get() const noexcept(noexcept(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"); diff --git a/src/json.hpp.re2c b/src/json.hpp.re2c index ab180d9f..5a9d2f88 100644 --- a/src/json.hpp.re2c +++ b/src/json.hpp.re2c @@ -204,14 +204,14 @@ using enable_if_t = typename std::enable_if::type; template using uncvref_t = typename std::remove_cv::type>::type; -// Taken from http://stackoverflow.com/questions/26936640/how-to-implement-is-enum-class-type-trait +// taken from http://stackoverflow.com/a/26936864/266378 template using is_unscoped_enum = std::integral_constant::value and std::is_enum::value>; /* -Implementation of 2 C++17 constructs: conjunction, negation. This is needed +Implementation of two C++17 constructs: conjunction, negation. This is needed to avoid evaluating all the traits in a condition For example: not std::is_same::value and has_value_type::value @@ -393,6 +393,7 @@ NLOHMANN_JSON_HAS_HELPER(iterator); #undef NLOHMANN_JSON_HAS_HELPER + template struct is_compatible_object_type_impl : std::false_type {}; @@ -468,7 +469,7 @@ struct is_compatible_integer_type }; -// This trait checks if JSONSerializer::from_json(json const&, udt&) exists +// trait checking if JSONSerializer::from_json(json const&, udt&) exists template struct has_from_json { @@ -530,8 +531,7 @@ void to_json(BasicJsonType& j, typename BasicJsonType::boolean_t b) noexcept template::value, - int> = 0> + CompatibleString>::value, int> = 0> void to_json(BasicJsonType& j, const CompatibleString& s) { external_constructor::construct(j, s); @@ -547,8 +547,7 @@ void to_json(BasicJsonType& j, FloatType val) noexcept template < typename BasicJsonType, typename CompatibleNumberUnsignedType, enable_if_t::value, - int> = 0 > + CompatibleNumberUnsignedType>::value, int> = 0 > void to_json(BasicJsonType& j, CompatibleNumberUnsignedType val) noexcept { external_constructor::construct(j, static_cast(val)); @@ -557,8 +556,7 @@ void to_json(BasicJsonType& j, CompatibleNumberUnsignedType val) noexcept template < typename BasicJsonType, typename CompatibleNumberIntegerType, enable_if_t::value, - int> = 0 > + CompatibleNumberIntegerType>::value, int> = 0 > void to_json(BasicJsonType& j, CompatibleNumberIntegerType val) noexcept { external_constructor::construct(j, static_cast(val)); @@ -690,7 +688,6 @@ void from_json(const BasicJsonType& j, typename BasicJsonType::array_t& arr) } // forward_list doesn't have an insert method -// TODO find a way to avoid including forward_list template void from_json(const BasicJsonType& j, std::forward_list& l) { @@ -781,14 +778,15 @@ void from_json(const BasicJsonType& j, CompatibleObjectType& obj) using std::begin; using std::end; // we could avoid the assignment, but this might require a for loop, which - // might be less efficient than the container constructor for some containers (would it?) + // might be less efficient than the container constructor for some + // containers (would it?) obj = CompatibleObjectType(begin(*inner_object), end(*inner_object)); } -// overload for arithmetic types, not chosen for basic_json template arguments (BooleanType, etc..) -// -// note: Is it really necessary to provide explicit overloads for boolean_t etc.. -// in case of a custom BooleanType which is not an arithmetic type? +// overload for arithmetic types, not chosen for basic_json template arguments +// (BooleanType, etc..); note: Is it really necessary to provide explicit +// overloads for boolean_t etc. in case of a custom BooleanType which is not +// an arithmetic type? template::value and @@ -802,19 +800,29 @@ void from_json(const BasicJsonType& j, ArithmeticType& val) switch (static_cast(j)) { case value_t::number_unsigned: + { val = static_cast(*j.template get_ptr()); break; + } case value_t::number_integer: + { val = static_cast(*j.template get_ptr()); break; + } case value_t::number_float: + { val = static_cast(*j.template get_ptr()); break; + } case value_t::boolean: + { val = static_cast(*j.template get_ptr()); break; + } default: + { JSON_THROW(std::domain_error("type must be number, but is " + j.type_name())); + } } } @@ -3160,8 +3168,7 @@ class basic_json detail::enable_if_t < not std::is_same::value and detail::has_from_json::value and - not detail::has_non_default_from_json::value, + not detail::has_non_default_from_json::value, int > = 0 > U get() const noexcept(noexcept(JSONSerializer::from_json( std::declval(), std::declval()))) @@ -3196,8 +3203,7 @@ class basic_json typename U = detail::uncvref_t, detail::enable_if_t::value and detail::has_non_default_from_json::value, - int> = 0 > + U>::value, int> = 0 > U get() const noexcept(noexcept(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");