Fix issue #1237
* Make the conversion operator SFINAE correct. * Workaround a GCC bug with some traits in type_traits.hpp The first bullet-point implies that every `get`/`get_ptr` be SFINAE correct as well.
This commit is contained in:
parent
e4bc98d036
commit
4e52277b70
4 changed files with 146 additions and 168 deletions
|
@ -65,6 +65,9 @@ using to_json_function = decltype(T::to_json(std::declval<Args>()...));
|
||||||
template <typename T, typename... Args>
|
template <typename T, typename... Args>
|
||||||
using from_json_function = decltype(T::from_json(std::declval<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 //
|
// is_ functions //
|
||||||
///////////////////
|
///////////////////
|
||||||
|
@ -185,8 +188,12 @@ struct is_compatible_integer_type
|
||||||
CompatibleNumberIntegerType> {};
|
CompatibleNumberIntegerType> {};
|
||||||
|
|
||||||
// trait checking if JSONSerializer<T>::from_json(json const&, udt&) exists
|
// trait checking if JSONSerializer<T>::from_json(json const&, udt&) exists
|
||||||
template<typename BasicJsonType, typename T>
|
template <typename BasicJsonType, typename T, typename = void>
|
||||||
struct has_from_json
|
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>;
|
using serializer = typename BasicJsonType::template json_serializer<T, void>;
|
||||||
|
|
||||||
|
@ -197,8 +204,11 @@ struct has_from_json
|
||||||
|
|
||||||
// This trait checks if JSONSerializer<T>::from_json(json const&) exists
|
// This trait checks if JSONSerializer<T>::from_json(json const&) exists
|
||||||
// this overload is used for non-default-constructible user-defined-types
|
// 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>
|
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>;
|
using serializer = typename BasicJsonType::template json_serializer<T, void>;
|
||||||
|
|
||||||
|
@ -208,8 +218,12 @@ struct has_non_default_from_json
|
||||||
};
|
};
|
||||||
|
|
||||||
// This trait checks if BasicJsonType::json_serializer<T>::to_json exists
|
// This trait checks if BasicJsonType::json_serializer<T>::to_json exists
|
||||||
template<typename BasicJsonType, typename T>
|
// Do not evaluate the trait when T is a basic_json type, to avoid template instantiation infinite recursion.
|
||||||
struct has_to_json
|
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>;
|
using serializer = typename BasicJsonType::template json_serializer<T, void>;
|
||||||
|
|
||||||
|
|
|
@ -2623,6 +2623,53 @@ class basic_json
|
||||||
return JSONSerializer<ValueTypeCV>::from_json(*this);
|
return JSONSerializer<ValueTypeCV>::from_json(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
@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 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_impl_ptr<>() const
|
||||||
|
return get_impl_ptr(static_cast<PointerType>(nullptr));
|
||||||
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@brief get a pointer value (explicit)
|
@brief get a pointer value (explicit)
|
||||||
|
|
||||||
|
@ -2652,7 +2699,7 @@ class basic_json
|
||||||
*/
|
*/
|
||||||
template<typename PointerType, typename std::enable_if<
|
template<typename PointerType, typename std::enable_if<
|
||||||
std::is_pointer<PointerType>::value, int>::type = 0>
|
std::is_pointer<PointerType>::value, int>::type = 0>
|
||||||
PointerType get() noexcept
|
auto get() noexcept -> decltype(std::declval<basic_json_t&>().template get_ptr<PointerType>())
|
||||||
{
|
{
|
||||||
// delegate the call to get_ptr
|
// delegate the call to get_ptr
|
||||||
return get_ptr<PointerType>();
|
return get_ptr<PointerType>();
|
||||||
|
@ -2664,89 +2711,12 @@ class basic_json
|
||||||
*/
|
*/
|
||||||
template<typename PointerType, typename std::enable_if<
|
template<typename PointerType, typename std::enable_if<
|
||||||
std::is_pointer<PointerType>::value, int>::type = 0>
|
std::is_pointer<PointerType>::value, int>::type = 0>
|
||||||
constexpr const PointerType get() const noexcept
|
constexpr auto get() const noexcept -> decltype(std::declval<const basic_json_t&>().template get_ptr<PointerType>())
|
||||||
{
|
{
|
||||||
// delegate the call to get_ptr
|
// delegate the call to get_ptr
|
||||||
return get_ptr<PointerType>();
|
return get_ptr<PointerType>();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
|
||||||
@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>
|
|
||||||
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));
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
@brief get a pointer value (implicit)
|
|
||||||
@copydoc get_ptr()
|
|
||||||
*/
|
|
||||||
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));
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@brief get a reference value (implicit)
|
@brief get a reference value (implicit)
|
||||||
|
|
||||||
|
@ -2828,12 +2798,14 @@ class basic_json
|
||||||
not std::is_same<ValueType, detail::json_ref<basic_json>>::value and
|
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 std::is_same<ValueType, typename string_t::value_type>::value and
|
||||||
not detail::is_basic_json<ValueType>::value
|
not detail::is_basic_json<ValueType>::value
|
||||||
|
|
||||||
#ifndef _MSC_VER // fix for issue #167 operator<< ambiguity under VS2015
|
#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
|
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
|
#if defined(JSON_HAS_CPP_17) && defined(_MSC_VER) and _MSC_VER <= 1914
|
||||||
and not std::is_same<ValueType, typename std::string_view>::value
|
and not std::is_same<ValueType, typename std::string_view>::value
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
and detail::is_detected<detail::get_template_function, const basic_json_t&, ValueType>::value
|
||||||
, int >::type = 0 >
|
, int >::type = 0 >
|
||||||
operator ValueType() const
|
operator ValueType() const
|
||||||
{
|
{
|
||||||
|
|
|
@ -425,6 +425,9 @@ using to_json_function = decltype(T::to_json(std::declval<Args>()...));
|
||||||
template <typename T, typename... Args>
|
template <typename T, typename... Args>
|
||||||
using from_json_function = decltype(T::from_json(std::declval<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 //
|
// is_ functions //
|
||||||
///////////////////
|
///////////////////
|
||||||
|
@ -545,8 +548,12 @@ struct is_compatible_integer_type
|
||||||
CompatibleNumberIntegerType> {};
|
CompatibleNumberIntegerType> {};
|
||||||
|
|
||||||
// trait checking if JSONSerializer<T>::from_json(json const&, udt&) exists
|
// trait checking if JSONSerializer<T>::from_json(json const&, udt&) exists
|
||||||
template<typename BasicJsonType, typename T>
|
template <typename BasicJsonType, typename T, typename = void>
|
||||||
struct has_from_json
|
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>;
|
using serializer = typename BasicJsonType::template json_serializer<T, void>;
|
||||||
|
|
||||||
|
@ -557,8 +564,11 @@ struct has_from_json
|
||||||
|
|
||||||
// This trait checks if JSONSerializer<T>::from_json(json const&) exists
|
// This trait checks if JSONSerializer<T>::from_json(json const&) exists
|
||||||
// this overload is used for non-default-constructible user-defined-types
|
// 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>
|
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>;
|
using serializer = typename BasicJsonType::template json_serializer<T, void>;
|
||||||
|
|
||||||
|
@ -568,8 +578,12 @@ struct has_non_default_from_json
|
||||||
};
|
};
|
||||||
|
|
||||||
// This trait checks if BasicJsonType::json_serializer<T>::to_json exists
|
// This trait checks if BasicJsonType::json_serializer<T>::to_json exists
|
||||||
template<typename BasicJsonType, typename T>
|
// Do not evaluate the trait when T is a basic_json type, to avoid template instantiation infinite recursion.
|
||||||
struct has_to_json
|
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>;
|
using serializer = typename BasicJsonType::template json_serializer<T, void>;
|
||||||
|
|
||||||
|
@ -13696,6 +13710,53 @@ class basic_json
|
||||||
return JSONSerializer<ValueTypeCV>::from_json(*this);
|
return JSONSerializer<ValueTypeCV>::from_json(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
@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 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_impl_ptr<>() const
|
||||||
|
return get_impl_ptr(static_cast<PointerType>(nullptr));
|
||||||
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@brief get a pointer value (explicit)
|
@brief get a pointer value (explicit)
|
||||||
|
|
||||||
|
@ -13725,7 +13786,7 @@ class basic_json
|
||||||
*/
|
*/
|
||||||
template<typename PointerType, typename std::enable_if<
|
template<typename PointerType, typename std::enable_if<
|
||||||
std::is_pointer<PointerType>::value, int>::type = 0>
|
std::is_pointer<PointerType>::value, int>::type = 0>
|
||||||
PointerType get() noexcept
|
auto get() noexcept -> decltype(std::declval<basic_json_t&>().template get_ptr<PointerType>())
|
||||||
{
|
{
|
||||||
// delegate the call to get_ptr
|
// delegate the call to get_ptr
|
||||||
return get_ptr<PointerType>();
|
return get_ptr<PointerType>();
|
||||||
|
@ -13737,89 +13798,12 @@ class basic_json
|
||||||
*/
|
*/
|
||||||
template<typename PointerType, typename std::enable_if<
|
template<typename PointerType, typename std::enable_if<
|
||||||
std::is_pointer<PointerType>::value, int>::type = 0>
|
std::is_pointer<PointerType>::value, int>::type = 0>
|
||||||
constexpr const PointerType get() const noexcept
|
constexpr auto get() const noexcept -> decltype(std::declval<const basic_json_t&>().template get_ptr<PointerType>())
|
||||||
{
|
{
|
||||||
// delegate the call to get_ptr
|
// delegate the call to get_ptr
|
||||||
return get_ptr<PointerType>();
|
return get_ptr<PointerType>();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
|
||||||
@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>
|
|
||||||
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));
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
|
||||||
@brief get a pointer value (implicit)
|
|
||||||
@copydoc get_ptr()
|
|
||||||
*/
|
|
||||||
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));
|
|
||||||
}
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@brief get a reference value (implicit)
|
@brief get a reference value (implicit)
|
||||||
|
|
||||||
|
@ -13901,12 +13885,14 @@ class basic_json
|
||||||
not std::is_same<ValueType, detail::json_ref<basic_json>>::value and
|
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 std::is_same<ValueType, typename string_t::value_type>::value and
|
||||||
not detail::is_basic_json<ValueType>::value
|
not detail::is_basic_json<ValueType>::value
|
||||||
|
|
||||||
#ifndef _MSC_VER // fix for issue #167 operator<< ambiguity under VS2015
|
#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
|
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
|
#if defined(JSON_HAS_CPP_17) && defined(_MSC_VER) and _MSC_VER <= 1914
|
||||||
and not std::is_same<ValueType, typename std::string_view>::value
|
and not std::is_same<ValueType, typename std::string_view>::value
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
and detail::is_detected<detail::get_template_function, const basic_json_t&, ValueType>::value
|
||||||
, int >::type = 0 >
|
, int >::type = 0 >
|
||||||
operator ValueType() const
|
operator ValueType() const
|
||||||
{
|
{
|
||||||
|
|
|
@ -811,3 +811,9 @@ TEST_CASE("Issue #924")
|
||||||
CHECK_NOTHROW(j.get<Evil>());
|
CHECK_NOTHROW(j.get<Evil>());
|
||||||
CHECK_NOTHROW(j.get<std::vector<Evil>>());
|
CHECK_NOTHROW(j.get<std::vector<Evil>>());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_CASE("Issue #1237")
|
||||||
|
{
|
||||||
|
struct non_convertible_type {};
|
||||||
|
static_assert(not std::is_convertible<json, non_convertible_type>::value, "");
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue