Skip to content

Commit

Permalink
Add a get overload taking a parameter.
Browse files Browse the repository at this point in the history
Takes an lvalue reference, and returns the same reference.

This allows non-default constructible types to be used with get.
This overload does not require CopyConstructible either.

Conversion to C arrays is possible with this overload.

Implements nlohmann#1227
  • Loading branch information
theodelrieu committed Sep 12, 2018
1 parent ebb3c03 commit 699886d
Show file tree
Hide file tree
Showing 5 changed files with 640 additions and 132 deletions.
14 changes: 12 additions & 2 deletions include/nlohmann/detail/conversions/from_json.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,16 @@ void from_json(const BasicJsonType& j, std::valarray<T>& l)
std::copy(j.m_value.array->begin(), j.m_value.array->end(), std::begin(l));
}

template <
typename BasicJsonType, typename T, std::size_t N >
auto from_json(const BasicJsonType& j, T (&arr)[N]) -> decltype(j.template get(std::declval<T&>()), void())
{
for (std::size_t i = 0; i < N; ++i)
{
j.at(i).get(arr[i]);
}
}

template<typename BasicJsonType>
void from_json_array_impl(const BasicJsonType& j, typename BasicJsonType::array_t& arr, priority_tag<3> /*unused*/)
{
Expand All @@ -165,11 +175,11 @@ void from_json_array_impl(const BasicJsonType& j, typename BasicJsonType::array_
template <typename BasicJsonType, typename T, std::size_t N>
auto from_json_array_impl(const BasicJsonType& j, std::array<T, N>& arr,
priority_tag<2> /*unused*/)
-> decltype(j.template get<T>(), void())
-> decltype(j.get(std::declval<T&>()), void())
{
for (std::size_t i = 0; i < N; ++i)
{
arr[i] = j.at(i).template get<T>();
j.at(i).get(arr[i]);
}
}

Expand Down
62 changes: 62 additions & 0 deletions include/nlohmann/json.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2623,6 +2623,68 @@ class basic_json
return JSONSerializer<ValueTypeCV>::from_json(*this);
}

/*!
@brief get a value (explicit)
Explicit type conversion between the JSON value and a compatible value.
The value is filled into the input parameter by calling the @ref json_serializer<ValueType>
`from_json()` method.
The function is equivalent to executing
@code {.cpp}
ValueType ret;
JSONSerializer<ValueType>::from_json(*this, ret);
return ret;
@endcode
This overloads is chosen if:
- @a ValueType is not @ref basic_json,
- @ref json_serializer<ValueType> has a `from_json()` method of the form
`void from_json(const basic_json&, ValueType&)`.
@tparam ValueType the input parameter type.
@return the input parameter, allowing chaining calls.
@throw what @ref json_serializer<ValueType> `from_json()` method throws
@since version 3.3.0
*/
template<typename ValueType,
detail::enable_if_t <
not detail::is_basic_json<ValueType>::value and
detail::has_from_json<basic_json_t, ValueType>::value,
int> = 0>
ValueType & get(ValueType& v) const noexcept(noexcept(
JSONSerializer<ValueType>::from_json(std::declval<const basic_json_t&>(), v)))
{
JSONSerializer<ValueType>::from_json(*this, v);
return v;
}

/*!
@brief get special-case overload
This overloads converts the current @ref basic_json in another
@ref basic_json type and fills the result into the input parameter.
@tparam BasicJsonType == @ref basic_json
@return the input parameter, allowing chaining calls.
@complexity Constant
@since version 3.3.0
*/
template<typename BasicJsonType,
detail::enable_if_t <
detail::is_basic_json<BasicJsonType>::value,
int> = 0>
BasicJsonType & get(BasicJsonType& j) const
{
return j = *this;
}

/*!
@brief get a pointer value (explicit)
Expand Down
76 changes: 74 additions & 2 deletions single_include/nlohmann/json.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -1170,6 +1170,16 @@ void from_json(const BasicJsonType& j, std::valarray<T>& l)
std::copy(j.m_value.array->begin(), j.m_value.array->end(), std::begin(l));
}

template <
typename BasicJsonType, typename T, std::size_t N >
auto from_json(const BasicJsonType& j, T (&arr)[N]) -> decltype(j.template get(std::declval<T&>()), void())
{
for (std::size_t i = 0; i < N; ++i)
{
j.at(i).get(arr[i]);
}
}

template<typename BasicJsonType>
void from_json_array_impl(const BasicJsonType& j, typename BasicJsonType::array_t& arr, priority_tag<3> /*unused*/)
{
Expand All @@ -1179,11 +1189,11 @@ void from_json_array_impl(const BasicJsonType& j, typename BasicJsonType::array_
template <typename BasicJsonType, typename T, std::size_t N>
auto from_json_array_impl(const BasicJsonType& j, std::array<T, N>& arr,
priority_tag<2> /*unused*/)
-> decltype(j.template get<T>(), void())
-> decltype(j.get(std::declval<T&>()), void())
{
for (std::size_t i = 0; i < N; ++i)
{
arr[i] = j.at(i).template get<T>();
j.at(i).get(arr[i]);
}
}

Expand Down Expand Up @@ -13693,6 +13703,68 @@ class basic_json
return JSONSerializer<ValueTypeCV>::from_json(*this);
}

/*!
@brief get a value (explicit)

Explicit type conversion between the JSON value and a compatible value.
The value is filled into the input parameter by calling the @ref json_serializer<ValueType>
`from_json()` method.

The function is equivalent to executing
@code {.cpp}
ValueType ret;
JSONSerializer<ValueType>::from_json(*this, ret);
return ret;
@endcode

This overloads is chosen if:
- @a ValueType is not @ref basic_json,
- @ref json_serializer<ValueType> has a `from_json()` method of the form
`void from_json(const basic_json&, ValueType&)`.

@tparam ValueType the input parameter type.

@return the input parameter, allowing chaining calls.

@throw what @ref json_serializer<ValueType> `from_json()` method throws

@since version 3.3.0
*/
template<typename ValueType,
detail::enable_if_t <
not detail::is_basic_json<ValueType>::value and
detail::has_from_json<basic_json_t, ValueType>::value,
int> = 0>
ValueType & get(ValueType& v) const noexcept(noexcept(
JSONSerializer<ValueType>::from_json(std::declval<const basic_json_t&>(), v)))
{
JSONSerializer<ValueType>::from_json(*this, v);
return v;
}

/*!
@brief get special-case overload

This overloads converts the current @ref basic_json in another
@ref basic_json type and fills the result into the input parameter.

@tparam BasicJsonType == @ref basic_json

@return the input parameter, allowing chaining calls.

@complexity Constant

@since version 3.3.0
*/
template<typename BasicJsonType,
detail::enable_if_t <
detail::is_basic_json<BasicJsonType>::value,
int> = 0>
BasicJsonType & get(BasicJsonType& j) const
{
return j = *this;
}

/*!
@brief get a pointer value (explicit)

Expand Down
Loading

0 comments on commit 699886d

Please sign in to comment.