1
0
mirror of https://github.com/nlohmann/json.git synced 2025-08-07 18:02:57 +03:00

Refactor json::get() to use priority_tag.

This commit is contained in:
Anthony VH
2021-01-12 18:28:47 +01:00
parent 6278f31d23
commit 6ef1614fa9

View File

@@ -2838,50 +2838,53 @@ class basic_json
/// @{ /// @{
/*! /*!
@brief get special-case overload @brief get a pointer value (implicit)
This overloads avoids a lot of template boilerplate, it can be seen as the Implicit pointer access to the internally stored JSON value. No copies are
identity method made.
@tparam BasicJsonType == @ref basic_json @warning Writing data to the pointee of the result yields an undefined
state.
@return a copy of *this @tparam PointerType pointer type; must be a pointer to @ref array_t, @ref
object_t, @ref string_t, @ref boolean_t, @ref number_integer_t,
@ref number_unsigned_t, or @ref number_float_t. Enforced by a static
assertion.
@return pointer to the internally stored JSON value if the requested
pointer type @a PointerType fits to the JSON value; `nullptr` otherwise
@complexity Constant. @complexity Constant.
@since version 2.1.0 @liveexample{The example below shows how pointers to internal values of a
JSON value can be requested. Note that no type conversions are made and a
`nullptr` is returned if the value and the requested pointer type does not
match.,get_ptr}
@since version 1.0.0
*/ */
template<typename BasicJsonType, detail::enable_if_t< template<typename PointerType, typename std::enable_if<
std::is_same<typename std::remove_const<BasicJsonType>::type, basic_json_t>::value, std::is_pointer<PointerType>::value, int>::type = 0>
int> = 0> auto get_ptr() noexcept -> decltype(std::declval<basic_json_t&>().get_impl_ptr(std::declval<PointerType>()))
basic_json get() const
{ {
return *this; // delegate the call to get_impl_ptr<>()
return get_impl_ptr(static_cast<PointerType>(nullptr));
} }
/*! /*!
@brief get special-case overload @brief get a pointer value (implicit)
@copydoc get_ptr()
This overloads converts the current @ref basic_json in a different
@ref basic_json type
@tparam BasicJsonType == @ref basic_json
@return a copy of *this, converted into @tparam BasicJsonType
@complexity Depending on the implementation of the called `from_json()`
method.
@since version 3.2.0
*/ */
template < typename BasicJsonType, detail::enable_if_t < template < typename PointerType, typename std::enable_if <
!std::is_same<BasicJsonType, basic_json>::value&& std::is_pointer<PointerType>::value&&
detail::is_basic_json<BasicJsonType>::value, int > = 0 > std::is_const<typename std::remove_pointer<PointerType>::type>::value, int >::type = 0 >
BasicJsonType get() const constexpr auto get_ptr() const noexcept -> decltype(std::declval<const basic_json_t&>().get_impl_ptr(std::declval<PointerType>()))
{ {
return *this; // delegate the call to get_impl_ptr<>() const
return get_impl_ptr(static_cast<PointerType>(nullptr));
} }
private:
/*! /*!
@brief get a value (explicit) @brief get a value (explicit)
@@ -2923,21 +2926,12 @@ class basic_json
*/ */
template < typename ValueTypeCV, typename ValueType = detail::uncvref_t<ValueTypeCV>, template < typename ValueTypeCV, typename ValueType = detail::uncvref_t<ValueTypeCV>,
detail::enable_if_t < detail::enable_if_t <
!detail::is_basic_json<ValueType>::value && detail::is_default_constructible<ValueType>::value &&
detail::has_from_json<basic_json_t, ValueType>::value && detail::has_from_json<basic_json_t, ValueType>::value,
!detail::has_non_default_from_json<basic_json_t, ValueType>::value,
int > = 0 > int > = 0 >
ValueType get() const noexcept(noexcept( ValueType get_impl(detail::priority_tag<0> /*unused*/) const noexcept(noexcept(
JSONSerializer<ValueType>::from_json(std::declval<const basic_json_t&>(), std::declval<ValueType&>()))) JSONSerializer<ValueType>::from_json(std::declval<const basic_json_t&>(), std::declval<ValueType&>())))
{ {
// we cannot static_assert on ValueTypeCV being non-const, because
// there is support for get<const basic_json_t>(), which is why we
// still need the uncvref
static_assert(!std::is_reference<ValueTypeCV>::value,
"get() cannot be used with reference types, you might want to use get_ref()");
static_assert(std::is_default_constructible<ValueType>::value,
"types must be DefaultConstructible when used with get()");
ValueType ret; ValueType ret;
JSONSerializer<ValueType>::from_json(*this, ret); JSONSerializer<ValueType>::from_json(*this, ret);
return ret; return ret;
@@ -2975,15 +2969,142 @@ class basic_json
@since version 2.1.0 @since version 2.1.0
*/ */
template < typename ValueTypeCV, typename ValueType = detail::uncvref_t<ValueTypeCV>, template < typename ValueTypeCV, typename ValueType = detail::uncvref_t<ValueTypeCV>,
detail::enable_if_t < !std::is_same<basic_json_t, ValueType>::value && detail::enable_if_t <
detail::has_non_default_from_json<basic_json_t, ValueType>::value, detail::has_non_default_from_json<basic_json_t, ValueType>::value,
int > = 0 > int > = 0 >
ValueType get() const noexcept(noexcept( ValueType get_impl(detail::priority_tag<1> /*unused*/) const noexcept(noexcept(
JSONSerializer<ValueType>::from_json(std::declval<const basic_json_t&>()))) JSONSerializer<ValueType>::from_json(std::declval<const basic_json_t&>())))
{ {
return JSONSerializer<ValueType>::from_json(*this);
}
/*!
@brief get special-case overload
This overloads converts the current @ref basic_json in a different
@ref basic_json type
@tparam BasicJsonType == @ref basic_json
@return a copy of *this, converted into @tparam BasicJsonType
@complexity Depending on the implementation of the called `from_json()`
method.
@since version 3.2.0
*/
template < typename BasicJsonType, detail::enable_if_t <
detail::is_basic_json<BasicJsonType>::value,
int > = 0 >
BasicJsonType get_impl(detail::priority_tag<2> /*unused*/) const
{
return *this;
}
/*!
@brief get special-case overload
This overloads avoids a lot of template boilerplate, it can be seen as the
identity method
@tparam BasicJsonType == @ref basic_json
@return a copy of *this
@complexity Constant.
@since version 2.1.0
*/
template<typename BasicJsonType, detail::enable_if_t<
std::is_same<BasicJsonType, basic_json_t>::value,
int> = 0>
basic_json get_impl(detail::priority_tag<3> /*unused*/) const
{
return *this;
}
/*!
@brief get a pointer value (explicit)
@copydoc get()
*/
template<typename PointerType, detail::enable_if_t<
std::is_pointer<PointerType>::value, int> = 0>
constexpr auto get_impl(detail::priority_tag<4> /*unused*/) const noexcept
-> decltype(std::declval<const basic_json_t&>().template get_ptr<PointerType>())
{
// delegate the call to get_ptr
return get_ptr<PointerType>();
}
public:
/*!
@brief get a (pointer) value (explicit)
Performs explicit type conversion between the JSON value and a compatible value if required.
- If the requested type is a pointer to the internally stored JSON value that pointer is returned.
No copies are made.
- If the requested type is the current @ref basic_json, or a different @ref basic_json convertible
from the current @ref basic_json.
- Otherwise the value is converted by calling the @ref json_serializer<ValueType> `from_json()`
method.
@tparam ValueTypeCV the provided value type
@tparam ValueType the returned value type
@return copy of the JSON value, converted to @tparam ValueType if necessary
@throw what @ref json_serializer<ValueType> `from_json()` method throws if conversion is required
@since version 2.1.0
*/
template < typename ValueTypeCV, typename ValueType = detail::uncvref_t<ValueTypeCV>>
constexpr auto get() const noexcept(noexcept(get_impl<ValueType>(detail::priority_tag<4> {})))
-> decltype(get_impl<ValueType>(detail::priority_tag<4> {}))
{
// we cannot static_assert on ValueTypeCV being non-const, because
// there is support for get<const basic_json_t>(), which is why we
// still need the uncvref
static_assert(!std::is_reference<ValueTypeCV>::value, static_assert(!std::is_reference<ValueTypeCV>::value,
"get() cannot be used with reference types, you might want to use get_ref()"); "get() cannot be used with reference types, you might want to use get_ref()");
return JSONSerializer<ValueType>::from_json(*this); return get_impl<ValueType>(detail::priority_tag<4> {});
}
/*!
@brief get a pointer value (explicit)
Explicit pointer access to the internally stored JSON value. No copies are
made.
@warning The pointer becomes invalid if the underlying JSON object
changes.
@tparam PointerType pointer type; must be a pointer to @ref array_t, @ref
object_t, @ref string_t, @ref boolean_t, @ref number_integer_t,
@ref number_unsigned_t, or @ref number_float_t.
@return pointer to the internally stored JSON value if the requested
pointer type @a PointerType fits to the JSON value; `nullptr` otherwise
@complexity Constant.
@liveexample{The example below shows how pointers to internal values of a
JSON value can be requested. Note that no type conversions are made and a
`nullptr` is returned if the value and the requested pointer type does not
match.,get__PointerType}
@sa @ref get_ptr() for explicit pointer-member access
@since version 1.0.0
*/
template<typename PointerType, typename std::enable_if<
std::is_pointer<PointerType>::value, int>::type = 0>
auto get() noexcept -> decltype(std::declval<basic_json_t&>().template get_ptr<PointerType>())
{
// delegate the call to get_ptr
return get_ptr<PointerType>();
} }
/*! /*!
@@ -3056,101 +3177,6 @@ class basic_json
return v; return v;
} }
/*!
@brief get a pointer value (implicit)
Implicit pointer access to the internally stored JSON value. No copies are
made.
@warning Writing data to the pointee of the result yields an undefined
state.
@tparam PointerType pointer type; must be a pointer to @ref array_t, @ref
object_t, @ref string_t, @ref boolean_t, @ref number_integer_t,
@ref number_unsigned_t, or @ref number_float_t. Enforced by a static
assertion.
@return pointer to the internally stored JSON value if the requested
pointer type @a PointerType fits to the JSON value; `nullptr` otherwise
@complexity Constant.
@liveexample{The example below shows how pointers to internal values of a
JSON value can be requested. Note that no type conversions are made and a
`nullptr` is returned if the value and the requested pointer type does not
match.,get_ptr}
@since version 1.0.0
*/
template<typename PointerType, typename std::enable_if<
std::is_pointer<PointerType>::value, int>::type = 0>
auto get_ptr() noexcept -> decltype(std::declval<basic_json_t&>().get_impl_ptr(std::declval<PointerType>()))
{
// delegate the call to get_impl_ptr<>()
return get_impl_ptr(static_cast<PointerType>(nullptr));
}
/*!
@brief get a pointer value (implicit)
@copydoc get_ptr()
*/
template < typename PointerType, typename std::enable_if <
std::is_pointer<PointerType>::value&&
std::is_const<typename std::remove_pointer<PointerType>::type>::value, int >::type = 0 >
constexpr auto get_ptr() const noexcept -> decltype(std::declval<const basic_json_t&>().get_impl_ptr(std::declval<PointerType>()))
{
// delegate the call to get_impl_ptr<>() const
return get_impl_ptr(static_cast<PointerType>(nullptr));
}
/*!
@brief get a pointer value (explicit)
Explicit pointer access to the internally stored JSON value. No copies are
made.
@warning The pointer becomes invalid if the underlying JSON object
changes.
@tparam PointerType pointer type; must be a pointer to @ref array_t, @ref
object_t, @ref string_t, @ref boolean_t, @ref number_integer_t,
@ref number_unsigned_t, or @ref number_float_t.
@return pointer to the internally stored JSON value if the requested
pointer type @a PointerType fits to the JSON value; `nullptr` otherwise
@complexity Constant.
@liveexample{The example below shows how pointers to internal values of a
JSON value can be requested. Note that no type conversions are made and a
`nullptr` is returned if the value and the requested pointer type does not
match.,get__PointerType}
@sa @ref get_ptr() for explicit pointer-member access
@since version 1.0.0
*/
template<typename PointerType, typename std::enable_if<
std::is_pointer<PointerType>::value, int>::type = 0>
auto get() noexcept -> decltype(std::declval<basic_json_t&>().template get_ptr<PointerType>())
{
// delegate the call to get_ptr
return get_ptr<PointerType>();
}
/*!
@brief get a pointer value (explicit)
@copydoc get()
*/
template<typename PointerType, typename std::enable_if<
std::is_pointer<PointerType>::value, int>::type = 0>
constexpr auto get() const noexcept -> decltype(std::declval<const basic_json_t&>().template get_ptr<PointerType>())
{
// delegate the call to get_ptr
return get_ptr<PointerType>();
}
/*! /*!
@brief get a reference value (implicit) @brief get a reference value (implicit)