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,57 +2485,63 @@ class basic_json ...@@ -2467,57 +2485,63 @@ class basic_json
return *this; return *this;
} }
/*! // this overload is needed, since constructor for udt is explicit
@brief destructor 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)};
}
Destroys the JSON value and frees all allocated memory. /*!
@brief destructor
@complexity Linear. Destroys the JSON value and frees all allocated memory.
@requirement This function helps `basic_json` satisfying the @complexity Linear.
[Container](http://en.cppreference.com/w/cpp/concept/Container)
requirements:
- The complexity is linear.
- All stored elements are destroyed and all memory is freed.
@since version 1.0.0 @requirement This function helps `basic_json` satisfying the
*/ [Container](http://en.cppreference.com/w/cpp/concept/Container)
~basic_json() requirements:
{ - The complexity is linear.
assert_invariant(); - All stored elements are destroyed and all memory is freed.
switch (m_type) @since version 1.0.0
{ */
case value_t::object: ~basic_json() {
{ assert_invariant();
AllocatorType<object_t> alloc;
alloc.destroy(m_value.object);
alloc.deallocate(m_value.object, 1);
break;
}
case value_t::array:
{
AllocatorType<array_t> alloc;
alloc.destroy(m_value.array);
alloc.deallocate(m_value.array, 1);
break;
}
case value_t::string:
{
AllocatorType<string_t> alloc;
alloc.destroy(m_value.string);
alloc.deallocate(m_value.string, 1);
break;
}
default: switch (m_type) {
{ case value_t::object: {
// all other types need no specific destructor AllocatorType<object_t> alloc;
break; alloc.destroy(m_value.object);
} alloc.deallocate(m_value.object, 1);
} break;
}
case value_t::array: {
AllocatorType<array_t> alloc;
alloc.destroy(m_value.array);
alloc.deallocate(m_value.array, 1);
break;
}
case value_t::string: {
AllocatorType<string_t> alloc;
alloc.destroy(m_value.string);
alloc.deallocate(m_value.string, 1);
break;
}
default: {
// all other types need no specific destructor
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