Commit 60e6f822 authored by Théo DELRIEU's avatar Théo DELRIEU

add support for non-default-constructible udt

parent e5999c6c
...@@ -290,14 +290,32 @@ struct is_compatible_basic_json_type ...@@ -290,14 +290,32 @@ struct is_compatible_basic_json_type
}; };
// This trait checks if JSONSerializer<T>::from_json exists // This trait checks if JSONSerializer<T>::from_json(json const&, udt&) exists
template <template <typename, typename> class JSONSerializer, typename Json, template <template <typename, typename> class JSONSerializer, typename Json,
typename T> typename T>
struct has_from_json struct has_from_json
{ {
private: private:
template <typename U, typename = decltype(uncvref_t<U>::from_json( // also check the return type of from_json
std::declval<Json>(), std::declval<T &>()))> template <typename U, typename = enable_if_t<std::is_same<void, decltype(uncvref_t<U>::from_json(
std::declval<Json>(), std::declval<T &>()))>::value>>
static int detect(U &&);
static void detect(...);
public:
static constexpr bool value = std::is_integral<decltype(
detect(std::declval<JSONSerializer<T, void>>()))>::value;
};
// This trait checks if JSONSerializer<T>::from_json(json const&) exists
// this overload is used for non-default-constructible user-defined-types
template <template <typename, typename> class JSONSerializer, typename Json,
typename T>
struct has_non_default_from_json
{
private:
template <typename U, typename = enable_if_t<std::is_same<T, decltype(uncvref_t<U>::from_json(std::declval<Json>()))>::value>>
static int detect(U &&); static int detect(U &&);
static void detect(...); static void detect(...);
...@@ -326,8 +344,8 @@ public: ...@@ -326,8 +344,8 @@ public:
// those declarations are needed to workaround a MSVC bug related to ADL // those declarations are needed to workaround a MSVC bug related to ADL
// (taken from MSVC-Ranges implementation) // (taken from MSVC-Ranges implementation)
void to_json(); //void to_json();
void from_json(); //void from_json();
struct to_json_fn struct to_json_fn
{ {
...@@ -2467,6 +2485,18 @@ class basic_json ...@@ -2467,6 +2485,18 @@ class basic_json
return *this; return *this;
} }
// this overload is needed, since constructor for udt is explicit
template <typename T, enable_if_t<not detail::is_compatible_basic_json_type<
uncvref_t<T>, basic_json_t>::value and
detail::has_to_json<JSONSerializer, basic_json_t, uncvref_t<T>>::value>>
reference &operator=(T &&val) noexcept(std::is_nothrow_constructible<basic_json_t, uncvref_t<T>>::value and
std::is_nothrow_move_assignable<uncvref_t<T>>::value)
{
static_assert(sizeof(T) == 0 , "");
// I'm not sure this a is good practice...
return *this = basic_json_t{std::forward<T>(val)};
}
/*! /*!
@brief destructor @brief destructor
...@@ -2482,38 +2512,32 @@ class basic_json ...@@ -2482,38 +2512,32 @@ class basic_json
@since version 1.0.0 @since version 1.0.0
*/ */
~basic_json() ~basic_json() {
{
assert_invariant(); assert_invariant();
switch (m_type) switch (m_type) {
{ case value_t::object: {
case value_t::object:
{
AllocatorType<object_t> alloc; AllocatorType<object_t> alloc;
alloc.destroy(m_value.object); alloc.destroy(m_value.object);
alloc.deallocate(m_value.object, 1); alloc.deallocate(m_value.object, 1);
break; break;
} }
case value_t::array: case value_t::array: {
{
AllocatorType<array_t> alloc; AllocatorType<array_t> alloc;
alloc.destroy(m_value.array); alloc.destroy(m_value.array);
alloc.deallocate(m_value.array, 1); alloc.deallocate(m_value.array, 1);
break; break;
} }
case value_t::string: case value_t::string: {
{
AllocatorType<string_t> alloc; AllocatorType<string_t> alloc;
alloc.destroy(m_value.string); alloc.destroy(m_value.string);
alloc.deallocate(m_value.string, 1); alloc.deallocate(m_value.string, 1);
break; break;
} }
default: default: {
{
// all other types need no specific destructor // all other types need no specific destructor
break; break;
} }
...@@ -3273,6 +3297,19 @@ class basic_json ...@@ -3273,6 +3297,19 @@ class basic_json
return ret; return ret;
} }
// This overload is chosen for non-default constructible user-defined-types
template <
typename T,
enable_if_t<not detail::is_compatible_basic_json_type<
T, basic_json_t>::value and
detail::has_non_default_from_json<JSONSerializer, basic_json_t,
T>::value,
short> = 0>
T get() const
{
return JSONSerializer<T>::from_json(*this);
}
/*! /*!
@brief get a pointer value (explicit) @brief get a pointer value (explicit)
......
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment