Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix issue #1237 #1238

Merged
merged 2 commits into from
Sep 29, 2018
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 19 additions & 5 deletions include/nlohmann/detail/meta/type_traits.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,9 @@ using to_json_function = decltype(T::to_json(std::declval<Args>()...));
template <typename T, typename... Args>
using from_json_function = decltype(T::from_json(std::declval<Args>()...));

template <typename T, typename U>
using get_template_function = decltype(std::declval<T>().template get<U>());

///////////////////
// is_ functions //
///////////////////
Expand Down Expand Up @@ -185,8 +188,12 @@ struct is_compatible_integer_type
CompatibleNumberIntegerType> {};

// trait checking if JSONSerializer<T>::from_json(json const&, udt&) exists
template<typename BasicJsonType, typename T>
struct has_from_json
template <typename BasicJsonType, typename T, typename = void>
struct has_from_json : std::false_type {};

template <typename BasicJsonType, typename T>
struct has_from_json<BasicJsonType, T,
enable_if_t<not is_basic_json<T>::value>>
{
using serializer = typename BasicJsonType::template json_serializer<T, void>;

Expand All @@ -197,8 +204,11 @@ struct has_from_json

// This trait checks if JSONSerializer<T>::from_json(json const&) exists
// this overload is used for non-default-constructible user-defined-types
template <typename BasicJsonType, typename T, typename = void>
struct has_non_default_from_json : std::false_type {};

template<typename BasicJsonType, typename T>
struct has_non_default_from_json
struct has_non_default_from_json<BasicJsonType, T, enable_if_t<not is_basic_json<T>::value>>
{
using serializer = typename BasicJsonType::template json_serializer<T, void>;

Expand All @@ -208,8 +218,12 @@ struct has_non_default_from_json
};

// This trait checks if BasicJsonType::json_serializer<T>::to_json exists
template<typename BasicJsonType, typename T>
struct has_to_json
// Do not evaluate the trait when T is a basic_json type, to avoid template instantiation infinite recursion.
template <typename BasicJsonType, typename T, typename = void>
struct has_to_json : std::false_type {};

template <typename BasicJsonType, typename T>
struct has_to_json<BasicJsonType, T, enable_if_t<not is_basic_json<T>::value>>
{
using serializer = typename BasicJsonType::template json_serializer<T, void>;

Expand Down
104 changes: 38 additions & 66 deletions include/nlohmann/json.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2624,17 +2624,18 @@ class basic_json
}

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

Explicit pointer access to the internally stored JSON value. No copies are
Implicit pointer access to the internally stored JSON value. No copies are
made.

@warning The pointer becomes invalid if the underlying JSON object
changes.
@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.
@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
Expand All @@ -2644,45 +2645,43 @@ class basic_json
@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
match.,get_ptr}

@since version 1.0.0
*/
template<typename PointerType, typename std::enable_if<
std::is_pointer<PointerType>::value, int>::type = 0>
PointerType get() noexcept
auto get_ptr() noexcept -> decltype(std::declval<basic_json_t&>().get_impl_ptr(std::declval<PointerType>()))
{
// delegate the call to get_ptr
return get_ptr<PointerType>();
// delegate the call to get_impl_ptr<>()
return get_impl_ptr(static_cast<PointerType>(nullptr));
}

/*!
@brief get a pointer value (explicit)
@copydoc get()
@brief get a pointer value (implicit)
@copydoc get_ptr()
*/
template<typename PointerType, typename std::enable_if<
std::is_pointer<PointerType>::value, int>::type = 0>
constexpr const PointerType get() const noexcept
std::is_pointer<PointerType>::value and
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_ptr
return get_ptr<PointerType>();
// delegate the call to get_impl_ptr<>() const
return get_impl_ptr(static_cast<PointerType>(nullptr));
}

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

Implicit pointer access to the internally stored JSON value. No copies are
Explicit 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.
@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. Enforced by a static
assertion.
@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
Expand All @@ -2692,59 +2691,30 @@ class basic_json
@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}
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>
PointerType get_ptr() noexcept
{
// get the type of the PointerType (remove pointer and const)
using pointee_t = typename std::remove_const<typename
std::remove_pointer<typename
std::remove_const<PointerType>::type>::type>::type;
// make sure the type matches the allowed types
static_assert(
std::is_same<object_t, pointee_t>::value
or std::is_same<array_t, pointee_t>::value
or std::is_same<string_t, pointee_t>::value
or std::is_same<boolean_t, pointee_t>::value
or std::is_same<number_integer_t, pointee_t>::value
or std::is_same<number_unsigned_t, pointee_t>::value
or std::is_same<number_float_t, pointee_t>::value
, "incompatible pointer type");

// delegate the call to get_impl_ptr<>()
return get_impl_ptr(static_cast<PointerType>(nullptr));
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 (implicit)
@copydoc get_ptr()
@brief get a pointer value (explicit)
@copydoc get()
*/
template<typename PointerType, typename std::enable_if<
std::is_pointer<PointerType>::value and
std::is_const<typename std::remove_pointer<PointerType>::type>::value, int>::type = 0>
constexpr const PointerType get_ptr() const noexcept
{
// get the type of the PointerType (remove pointer and const)
using pointee_t = typename std::remove_const<typename
std::remove_pointer<typename
std::remove_const<PointerType>::type>::type>::type;
// make sure the type matches the allowed types
static_assert(
std::is_same<object_t, pointee_t>::value
or std::is_same<array_t, pointee_t>::value
or std::is_same<string_t, pointee_t>::value
or std::is_same<boolean_t, pointee_t>::value
or std::is_same<number_integer_t, pointee_t>::value
or std::is_same<number_unsigned_t, pointee_t>::value
or std::is_same<number_float_t, pointee_t>::value
, "incompatible pointer type");

// delegate the call to get_impl_ptr<>() const
return get_impl_ptr(static_cast<PointerType>(nullptr));
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>();
}

/*!
Expand Down Expand Up @@ -2828,12 +2798,14 @@ class basic_json
not std::is_same<ValueType, detail::json_ref<basic_json>>::value and
not std::is_same<ValueType, typename string_t::value_type>::value and
not detail::is_basic_json<ValueType>::value

#ifndef _MSC_VER // fix for issue #167 operator<< ambiguity under VS2015
and not std::is_same<ValueType, std::initializer_list<typename string_t::value_type>>::value
#if defined(JSON_HAS_CPP_17) && defined(_MSC_VER) and _MSC_VER <= 1914
and not std::is_same<ValueType, typename std::string_view>::value
#endif
#endif
and detail::is_detected<detail::get_template_function, const basic_json_t&, ValueType>::value
, int >::type = 0 >
operator ValueType() const
{
Expand Down
Loading