From 6b89785fba1fb2387ce640121ed17866ceae79ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9o=20DELRIEU?= Date: Sat, 7 Jan 2017 17:01:17 +0100 Subject: [PATCH] replace constructor by from/to_json: boolean_t --- src/json.hpp | 71 ++++++++++++++++++++++++++++------------------- src/json.hpp.re2c | 71 ++++++++++++++++++++++++++++------------------- 2 files changed, 86 insertions(+), 56 deletions(-) diff --git a/src/json.hpp b/src/json.hpp index 3b00d80e..00556604 100644 --- a/src/json.hpp +++ b/src/json.hpp @@ -202,6 +202,21 @@ template std::string type_name(Json const &j) } } +// This is an experiment. I need this to move constructors out of basic_json. +// I'm sure there is a better way, but this might need a big basic_json refactoring +template struct external_constructor; + +template <> +struct external_constructor +{ + template + static void construct(Json &j, typename Json::boolean_t b) noexcept + { + j.m_type = value_t::boolean; + j.m_value = b; + 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 @@ -340,9 +355,11 @@ struct is_compatible_integer_type_impl struct is_compatible_integer_type { - static constexpr auto value = is_compatible_integer_type_impl < - std::is_arithmetic::value, RealIntegerType, - CompatibleNumberIntegerType >::value; + static constexpr auto + value = is_compatible_integer_type_impl < + std::is_arithmetic::value and + not std::is_same::value, + RealIntegerType, CompatibleNumberIntegerType > ::value; }; template @@ -360,7 +377,6 @@ struct is_compatible_basic_json_type is_unscoped_enum::value or std::is_same::value or std::is_constructible::value or - std::is_same::value or is_compatible_array_type::value or is_compatible_object_type::value or is_compatible_float_type::value or @@ -433,6 +449,22 @@ struct has_to_json void to_json(); void from_json(); +// overloads for basic_json template parameters + +template +void to_json(Json &j, typename Json::boolean_t b) noexcept +{ + external_constructor::construct(j, b); +} + +template +void from_json(Json const& j, typename Json::boolean_t& b) +{ + if (!j.is_boolean()) + throw std::domain_error("type must be boolean, but is " + type_name(j)); + b = *const_cast(j).template get_ptr(); +} + struct to_json_fn { // is it really useful to mark those as constexpr? @@ -606,6 +638,7 @@ template < class basic_json { private: + template <::nlohmann::value_t> friend struct detail::external_constructor; template friend std::string detail::type_name(Json const &); /// workaround type for MSVC using basic_json_t = basic_json::value, int> = 0> + enable_if_t::value and + detail::is_compatible_basic_json_type< + uncvref_t, basic_json_t>::value, + int> = 0> auto get() const - -> decltype(this->get_impl(static_cast(nullptr))) - { - return get_impl(static_cast(nullptr)); + -> decltype(this->get_impl(static_cast(nullptr))) { + return get_impl(static_cast(nullptr)); } template < diff --git a/src/json.hpp.re2c b/src/json.hpp.re2c index ed9075ac..067ad1a6 100644 --- a/src/json.hpp.re2c +++ b/src/json.hpp.re2c @@ -202,6 +202,21 @@ template std::string type_name(Json const &j) } } +// This is an experiment. I need this to move constructors out of basic_json. +// I'm sure there is a better way, but this might need a big basic_json refactoring +template struct external_constructor; + +template <> +struct external_constructor +{ + template + static void construct(Json &j, typename Json::boolean_t b) noexcept + { + j.m_type = value_t::boolean; + j.m_value = b; + 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 @@ -340,9 +355,11 @@ struct is_compatible_integer_type_impl struct is_compatible_integer_type { - static constexpr auto value = is_compatible_integer_type_impl < - std::is_arithmetic::value, RealIntegerType, - CompatibleNumberIntegerType >::value; + static constexpr auto + value = is_compatible_integer_type_impl < + std::is_arithmetic::value and + not std::is_same::value, + RealIntegerType, CompatibleNumberIntegerType > ::value; }; template @@ -360,7 +377,6 @@ struct is_compatible_basic_json_type is_unscoped_enum::value or std::is_same::value or std::is_constructible::value or - std::is_same::value or is_compatible_array_type::value or is_compatible_object_type::value or is_compatible_float_type::value or @@ -433,6 +449,22 @@ struct has_to_json void to_json(); void from_json(); +// overloads for basic_json template parameters + +template +void to_json(Json &j, typename Json::boolean_t b) noexcept +{ + external_constructor::construct(j, b); +} + +template +void from_json(Json const& j, typename Json::boolean_t& b) +{ + if (!j.is_boolean()) + throw std::domain_error("type must be boolean, but is " + type_name(j)); + b = *const_cast(j).template get_ptr(); +} + struct to_json_fn { // is it really useful to mark those as constexpr? @@ -607,6 +639,7 @@ template < class basic_json { private: + template <::nlohmann::value_t> friend struct detail::external_constructor; template friend std::string detail::type_name(Json const &); /// workaround type for MSVC using basic_json_t = basic_json::value, int> = 0> + enable_if_t::value and + detail::is_compatible_basic_json_type< + uncvref_t, basic_json_t>::value, + int> = 0> auto get() const - -> decltype(this->get_impl(static_cast(nullptr))) - { - return get_impl(static_cast(nullptr)); + -> decltype(this->get_impl(static_cast(nullptr))) { + return get_impl(static_cast(nullptr)); } template <