diff --git a/src/json.hpp b/src/json.hpp index 1e7f1c5a..f3464894 100644 --- a/src/json.hpp +++ b/src/json.hpp @@ -248,6 +248,18 @@ struct external_constructor } }; +template <> +struct external_constructor +{ + template + static void construct(Json &j, typename Json::number_unsigned_t val) noexcept + { + j.m_type = value_t::number_unsigned; + j.m_value = val; + j.assert_invariant(); + } +}; + // very useful construct against boilerplate (more boilerplate needed than in // C++17: http://en.cppreference.com/w/cpp/types/void_t) template struct make_void @@ -411,9 +423,7 @@ struct is_compatible_basic_json_type std::is_same::value or is_compatible_array_type::value or is_compatible_object_type::value or - is_compatible_integer_type::value or - is_compatible_integer_type::value; + is_compatible_integer_type::value; }; template @@ -526,6 +536,17 @@ void to_json(Json &j, CompatibleNumberFloatType val) noexcept external_constructor::construct(j, val); } + +template < + typename Json, typename CompatibleNumberUnsignedType, + enable_if_t::value, + int> = 0> +void to_json(Json &j, CompatibleNumberUnsignedType val) noexcept +{ + external_constructor::construct(j, val); +} + template void from_json(Json const& j, typename Json::boolean_t& b) { @@ -548,6 +569,12 @@ void from_json(Json const& j, typename Json::number_float_t& val) get_arithmetic_value(j, val); } +template +void from_json(Json const& j, typename Json::number_unsigned_t& val) +{ + get_arithmetic_value(j, val); +} + // 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.. @@ -1897,64 +1924,6 @@ class basic_json assert_invariant(); } - /*! - @brief create an unsigned integer number (explicit) - - Create an unsigned integer number JSON value with a given content. - - @tparam T helper type to compare number_unsigned_t and unsigned int (not - visible in) the interface. - - @param[in] val an integer to create a JSON number from - - @complexity Constant. - - @sa @ref basic_json(const CompatibleNumberUnsignedType) -- create a number - value (unsigned integer) from a compatible number type - - @since version 2.0.0 - */ - template::value) and - std::is_same::value, int>::type = 0> - basic_json(const number_unsigned_t val) noexcept - : m_type(value_t::number_unsigned), m_value(val) - { - assert_invariant(); - } - - /*! - @brief create an unsigned number (implicit) - - Create an unsigned number JSON value with a given content. This - constructor allows any type @a CompatibleNumberUnsignedType that can be - used to construct values of type @ref number_unsigned_t. - - @tparam CompatibleNumberUnsignedType An integer type which is compatible - to @ref number_unsigned_t. Examples may include the types `unsigned int`, - `uint32_t`, or `unsigned short`. - - @param[in] val an unsigned integer to create a JSON number from - - @complexity Constant. - - @sa @ref basic_json(const number_unsigned_t) -- create a number value - (unsigned) - - @since version 2.0.0 - */ - template < - typename CompatibleNumberUnsignedType, - enable_if_t::value, - int> = 0 > - basic_json(const CompatibleNumberUnsignedType val) noexcept - : m_type(value_t::number_unsigned), - m_value(static_cast(val)) - { - assert_invariant(); - } - /*! @brief create a container (array or object) from an initializer list diff --git a/src/json.hpp.re2c b/src/json.hpp.re2c index 74697ab2..a7841f6f 100644 --- a/src/json.hpp.re2c +++ b/src/json.hpp.re2c @@ -248,6 +248,18 @@ struct external_constructor } }; +template <> +struct external_constructor +{ + template + static void construct(Json &j, typename Json::number_unsigned_t val) noexcept + { + j.m_type = value_t::number_unsigned; + j.m_value = val; + j.assert_invariant(); + } +}; + // very useful construct against boilerplate (more boilerplate needed than in // C++17: http://en.cppreference.com/w/cpp/types/void_t) template struct make_void @@ -411,9 +423,7 @@ struct is_compatible_basic_json_type std::is_same::value or is_compatible_array_type::value or is_compatible_object_type::value or - is_compatible_integer_type::value or - is_compatible_integer_type::value; + is_compatible_integer_type::value; }; template @@ -526,6 +536,17 @@ void to_json(Json &j, CompatibleNumberFloatType val) noexcept external_constructor::construct(j, val); } + +template < + typename Json, typename CompatibleNumberUnsignedType, + enable_if_t::value, + int> = 0> +void to_json(Json &j, CompatibleNumberUnsignedType val) noexcept +{ + external_constructor::construct(j, val); +} + template void from_json(Json const& j, typename Json::boolean_t& b) { @@ -548,6 +569,12 @@ void from_json(Json const& j, typename Json::number_float_t& val) get_arithmetic_value(j, val); } +template +void from_json(Json const& j, typename Json::number_unsigned_t& val) +{ + get_arithmetic_value(j, val); +} + // 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.. @@ -1898,64 +1925,6 @@ class basic_json assert_invariant(); } - /*! - @brief create an unsigned integer number (explicit) - - Create an unsigned integer number JSON value with a given content. - - @tparam T helper type to compare number_unsigned_t and unsigned int (not - visible in) the interface. - - @param[in] val an integer to create a JSON number from - - @complexity Constant. - - @sa @ref basic_json(const CompatibleNumberUnsignedType) -- create a number - value (unsigned integer) from a compatible number type - - @since version 2.0.0 - */ - template::value) and - std::is_same::value, int>::type = 0> - basic_json(const number_unsigned_t val) noexcept - : m_type(value_t::number_unsigned), m_value(val) - { - assert_invariant(); - } - - /*! - @brief create an unsigned number (implicit) - - Create an unsigned number JSON value with a given content. This - constructor allows any type @a CompatibleNumberUnsignedType that can be - used to construct values of type @ref number_unsigned_t. - - @tparam CompatibleNumberUnsignedType An integer type which is compatible - to @ref number_unsigned_t. Examples may include the types `unsigned int`, - `uint32_t`, or `unsigned short`. - - @param[in] val an unsigned integer to create a JSON number from - - @complexity Constant. - - @sa @ref basic_json(const number_unsigned_t) -- create a number value - (unsigned) - - @since version 2.0.0 - */ - template < - typename CompatibleNumberUnsignedType, - enable_if_t::value, - int> = 0 > - basic_json(const CompatibleNumberUnsignedType val) noexcept - : m_type(value_t::number_unsigned), - m_value(static_cast(val)) - { - assert_invariant(); - } - /*! @brief create a container (array or object) from an initializer list diff --git a/test/src/unit-udt.cpp b/test/src/unit-udt.cpp index 0cd834d6..382b0ed5 100644 --- a/test/src/unit-udt.cpp +++ b/test/src/unit-udt.cpp @@ -483,13 +483,20 @@ TEST_CASE("Non-copyable types", "[udt]") template ::value>::type> struct pod_serializer { - // I could forward-declare this struct, and add a basic_json alias template static void from_json(Json const& j , T& t) { - auto value = j.template get(); - auto bytes = static_cast(static_cast(&value)); - std::memcpy(&t, bytes, sizeof(value)); + std::uint64_t value; + // Why cannot we simply use: j.get() ? + // Well, with the current experiment, the get method looks for a from_json function, which we are currently defining! + // This would end up in a stack overflow. Calling nlohmann::from_json is a workaround. + // I shall find a good way to avoid this once all constructors are converted to free methods + // + // In short, constructing a json by constructor calls to_json + // calling get calls from_json, for now, we cannot do this in custom serializers + nlohmann::from_json(j, value); + auto bytes = static_cast(static_cast(&value)); + std::memcpy(&t, bytes, sizeof(value)); } template @@ -501,8 +508,8 @@ struct pod_serializer { value |= bytes[i] << 8 * i; } - - j = value; + // same thing here + nlohmann::to_json(j, value); } };