1
0
mirror of https://github.com/nlohmann/json synced 2024-11-22 12:00:05 +00: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
identity method
Implicit pointer access to the internally stored JSON value. No copies are
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.
@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<
std::is_same<typename std::remove_const<BasicJsonType>::type, basic_json_t>::value,
int> = 0>
basic_json get() const
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>()))
{
return *this;
// delegate the call to get_impl_ptr<>()
return get_impl_ptr(static_cast<PointerType>(nullptr));
}
/*!
@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
@brief get a pointer value (implicit)
@copydoc get_ptr()
*/
template < typename BasicJsonType, detail::enable_if_t <
!std::is_same<BasicJsonType, basic_json>::value&&
detail::is_basic_json<BasicJsonType>::value, int > = 0 >
BasicJsonType get() const
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>()))
{
return *this;
// delegate the call to get_impl_ptr<>() const
return get_impl_ptr(static_cast<PointerType>(nullptr));
}
private:
/*!
@brief get a value (explicit)
@ -2923,21 +2926,12 @@ class basic_json
*/
template < typename ValueTypeCV, typename ValueType = detail::uncvref_t<ValueTypeCV>,
detail::enable_if_t <
!detail::is_basic_json<ValueType>::value &&
detail::has_from_json<basic_json_t, ValueType>::value &&
!detail::has_non_default_from_json<basic_json_t, ValueType>::value,
detail::is_default_constructible<ValueType>::value &&
detail::has_from_json<basic_json_t, ValueType>::value,
int > = 0 >
ValueType get() const noexcept(noexcept(
JSONSerializer<ValueType>::from_json(std::declval<const basic_json_t&>(), std::declval<ValueType&>())))
ValueType get_impl(detail::priority_tag<0> /*unused*/) const noexcept(noexcept(
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;
JSONSerializer<ValueType>::from_json(*this, ret);
return ret;
@ -2975,15 +2969,142 @@ class basic_json
@since version 2.1.0
*/
template < typename ValueTypeCV, typename ValueType = detail::uncvref_t<ValueTypeCV>,
detail::enable_if_t < !std::is_same<basic_json_t, ValueType>::value &&
detail::has_non_default_from_json<basic_json_t, ValueType>::value,
int > = 0 >
ValueType get() const noexcept(noexcept(
JSONSerializer<ValueType>::from_json(std::declval<const basic_json_t&>())))
detail::enable_if_t <
detail::has_non_default_from_json<basic_json_t, ValueType>::value,
int > = 0 >
ValueType get_impl(detail::priority_tag<1> /*unused*/) const noexcept(noexcept(
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,
"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;
}
/*!
@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)