remove some useless checks, format a bit, added some comments
This commit is contained in:
parent
907484fb43
commit
74bb11d92c
1 changed files with 68 additions and 83 deletions
127
src/json.hpp
127
src/json.hpp
|
@ -130,11 +130,17 @@ using conditional_t = typename std::conditional<If, Then, Else>::type;
|
||||||
|
|
||||||
namespace detail
|
namespace detail
|
||||||
{
|
{
|
||||||
// implementation of 3 C++17 constructs: conjunction, disjunction, negation.
|
// Implementation of 3 C++17 constructs: conjunction, disjunction, negation.
|
||||||
// This is needed to avoid evaluating all the traits, MSVC cannot compile due
|
// This is needed to avoid evaluating all the traits in a condition
|
||||||
// to std::is_constructible<basic_json_t, void> being instantiated
|
//
|
||||||
// (void -> back_insert_iterator::value_type)
|
// For example: not std::is_same<void, T>::value and has_value_type<T>::value
|
||||||
// this could slow down compilation, since this implementation is taken from the example in cppreference...
|
// will not compile when T = void (on MSVC at least)
|
||||||
|
// Whereas conjunction<negation<std::is_same<void, T>>, has_value_type<T>>::value
|
||||||
|
// will stop evaluating if negation<...>::value == false
|
||||||
|
//
|
||||||
|
// Please note that those constructs must be used with caution, since symbols can
|
||||||
|
// become very long quickly (which can slow down compilation and cause MSVC internal compiler errors)
|
||||||
|
// Only use it when you have too (see example ahead)
|
||||||
template <class...> struct conjunction : std::true_type {};
|
template <class...> struct conjunction : std::true_type {};
|
||||||
template <class B1> struct conjunction<B1> : B1 {};
|
template <class B1> struct conjunction<B1> : B1 {};
|
||||||
template <class B1, class... Bn>
|
template <class B1, class... Bn>
|
||||||
|
@ -192,6 +198,8 @@ struct is_compatible_object_type_impl<true, RealType, CompatibleObjectType>
|
||||||
template<class RealType, class CompatibleObjectType>
|
template<class RealType, class CompatibleObjectType>
|
||||||
struct is_compatible_object_type
|
struct is_compatible_object_type
|
||||||
{
|
{
|
||||||
|
// As noted ahead, we need to stop evaluating traits if CompatibleObjectType = void
|
||||||
|
// hence the conjunction
|
||||||
static auto constexpr value = is_compatible_object_type_impl<
|
static auto constexpr value = is_compatible_object_type_impl<
|
||||||
conjunction<negation<std::is_same<void, CompatibleObjectType>>,
|
conjunction<negation<std::is_same<void, CompatibleObjectType>>,
|
||||||
has_mapped_type<CompatibleObjectType>,
|
has_mapped_type<CompatibleObjectType>,
|
||||||
|
@ -223,17 +231,14 @@ struct is_compatible_array_type_impl<true, BasicJson, CompatibleArrayType>
|
||||||
template <class BasicJson, class CompatibleArrayType>
|
template <class BasicJson, class CompatibleArrayType>
|
||||||
struct is_compatible_array_type
|
struct is_compatible_array_type
|
||||||
{
|
{
|
||||||
static auto constexpr value = disjunction<
|
// the check for CompatibleArrayType = void is done in is_compatible_object_type
|
||||||
std::is_same<BasicJson, CompatibleArrayType>,
|
// but we need the conjunction here as well
|
||||||
is_compatible_array_type_impl<
|
static auto constexpr value = is_compatible_array_type_impl<
|
||||||
conjunction<negation<
|
conjunction<negation<is_compatible_object_type<
|
||||||
// MSVC has troubles without this
|
|
||||||
std::is_same<void, CompatibleArrayType>>,
|
|
||||||
negation<is_compatible_object_type<
|
|
||||||
typename BasicJson::object_t, CompatibleArrayType>>,
|
typename BasicJson::object_t, CompatibleArrayType>>,
|
||||||
has_value_type<CompatibleArrayType>,
|
has_value_type<CompatibleArrayType>,
|
||||||
has_iterator<CompatibleArrayType>>::value,
|
has_iterator<CompatibleArrayType>>::value,
|
||||||
BasicJson, CompatibleArrayType>>::value;
|
BasicJson, CompatibleArrayType>::value;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <bool, typename, typename>
|
template <bool, typename, typename>
|
||||||
|
@ -242,11 +247,14 @@ struct is_compatible_integer_type_impl : std::false_type{};
|
||||||
template <typename RealIntegerType, typename CompatibleNumberIntegerType>
|
template <typename RealIntegerType, typename CompatibleNumberIntegerType>
|
||||||
struct is_compatible_integer_type_impl<true, RealIntegerType, CompatibleNumberIntegerType>
|
struct is_compatible_integer_type_impl<true, RealIntegerType, CompatibleNumberIntegerType>
|
||||||
{
|
{
|
||||||
|
using RealLimits = std::numeric_limits<RealIntegerType>;
|
||||||
|
using CompatibleLimits = std::numeric_limits<CompatibleNumberIntegerType>;
|
||||||
|
|
||||||
static constexpr auto value =
|
static constexpr auto value =
|
||||||
std::is_constructible<RealIntegerType,
|
std::is_constructible<RealIntegerType,
|
||||||
CompatibleNumberIntegerType>::value and
|
CompatibleNumberIntegerType>::value and
|
||||||
std::numeric_limits<CompatibleNumberIntegerType>::is_integer and
|
CompatibleLimits::is_integer and
|
||||||
std::numeric_limits<CompatibleNumberIntegerType>::is_signed;
|
RealLimits::is_signed == CompatibleLimits::is_signed;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename RealIntegerType, typename CompatibleNumberIntegerType>
|
template <typename RealIntegerType, typename CompatibleNumberIntegerType>
|
||||||
|
@ -257,27 +265,6 @@ struct is_compatible_integer_type
|
||||||
CompatibleNumberIntegerType>::value;
|
CompatibleNumberIntegerType>::value;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <bool, typename, typename>
|
|
||||||
struct is_compatible_unsigned_integer_type_impl : std::false_type{};
|
|
||||||
|
|
||||||
template <typename RealUnsignedType, typename CompatibleNumberUnsignedType>
|
|
||||||
struct is_compatible_unsigned_integer_type_impl<true, RealUnsignedType, CompatibleNumberUnsignedType>
|
|
||||||
{
|
|
||||||
static constexpr auto value =
|
|
||||||
std::is_constructible<RealUnsignedType,
|
|
||||||
CompatibleNumberUnsignedType>::value and
|
|
||||||
std::numeric_limits<CompatibleNumberUnsignedType>::is_integer and
|
|
||||||
not std::numeric_limits<CompatibleNumberUnsignedType>::is_signed;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename RealUnsignedType, typename CompatibleNumberUnsignedType>
|
|
||||||
struct is_compatible_unsigned_integer_type
|
|
||||||
{
|
|
||||||
static constexpr auto value = is_compatible_unsigned_integer_type_impl<
|
|
||||||
std::is_arithmetic<CompatibleNumberUnsignedType>::value, RealUnsignedType,
|
|
||||||
CompatibleNumberUnsignedType>::value;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename RealFloat, typename CompatibleFloat>
|
template <typename RealFloat, typename CompatibleFloat>
|
||||||
struct is_compatible_float_type
|
struct is_compatible_float_type
|
||||||
{
|
{
|
||||||
|
@ -298,7 +285,7 @@ struct is_compatible_basic_json_type
|
||||||
is_compatible_float_type<typename BasicJson::number_float_t, T>::value or
|
is_compatible_float_type<typename BasicJson::number_float_t, T>::value or
|
||||||
is_compatible_integer_type<typename BasicJson::number_integer_t,
|
is_compatible_integer_type<typename BasicJson::number_integer_t,
|
||||||
T>::value or
|
T>::value or
|
||||||
is_compatible_unsigned_integer_type<typename BasicJson::number_unsigned_t,
|
is_compatible_integer_type<typename BasicJson::number_unsigned_t,
|
||||||
T>::value;
|
T>::value;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -334,11 +321,14 @@ public:
|
||||||
detect(std::declval<JSONSerializer<T, void>>()))>::value;
|
detect(std::declval<JSONSerializer<T, void>>()))>::value;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// those declarations are needed to workaround a MSVC bug related to ADL
|
||||||
|
// (idea taken from MSVC-Ranges implementation
|
||||||
void to_json();
|
void to_json();
|
||||||
void from_json();
|
void from_json();
|
||||||
|
|
||||||
struct to_json_fn
|
struct to_json_fn
|
||||||
{
|
{
|
||||||
|
// is it really useful to mark those as constexpr?
|
||||||
template <typename Json, typename T>
|
template <typename Json, typename T>
|
||||||
constexpr auto operator()(Json &&j, T &&val) const
|
constexpr auto operator()(Json &&j, T &&val) const
|
||||||
noexcept(noexcept(to_json(std::forward<Json>(j), std::forward<T>(val))))
|
noexcept(noexcept(to_json(std::forward<Json>(j), std::forward<T>(val))))
|
||||||
|
@ -384,18 +374,18 @@ struct DecimalSeparator : std::numpunct<char>
|
||||||
// taken from ranges-v3
|
// taken from ranges-v3
|
||||||
// TODO add doc
|
// TODO add doc
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct _static_const
|
struct static_const
|
||||||
{
|
{
|
||||||
static constexpr T value{};
|
static constexpr T value{};
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
constexpr T _static_const<T>::value;
|
constexpr T static_const<T>::value;
|
||||||
|
|
||||||
inline namespace
|
inline namespace
|
||||||
{
|
{
|
||||||
constexpr auto const& to_json = _static_const<detail::to_json_fn>::value;
|
constexpr auto const& to_json = static_const<detail::to_json_fn>::value;
|
||||||
constexpr auto const& from_json = _static_const<detail::from_json_fn>::value;
|
constexpr auto const& from_json = static_const<detail::from_json_fn>::value;
|
||||||
}
|
}
|
||||||
|
|
||||||
// default JSONSerializer template argument, doesn't care about template argument
|
// default JSONSerializer template argument, doesn't care about template argument
|
||||||
|
@ -1493,9 +1483,11 @@ class basic_json
|
||||||
|
|
||||||
@since version 1.0.0
|
@since version 1.0.0
|
||||||
*/
|
*/
|
||||||
template<class CompatibleObjectType, enable_if_t<detail::is_compatible_object_type<object_t, CompatibleObjectType>::value, int> = 0>
|
template <class CompatibleObjectType,
|
||||||
basic_json(const CompatibleObjectType& val)
|
enable_if_t<detail::is_compatible_object_type<
|
||||||
: m_type(value_t::object)
|
object_t, CompatibleObjectType>::value,
|
||||||
|
int> = 0>
|
||||||
|
basic_json(const CompatibleObjectType &val) : m_type(value_t::object)
|
||||||
{
|
{
|
||||||
using std::begin;
|
using std::begin;
|
||||||
using std::end;
|
using std::end;
|
||||||
|
@ -1554,16 +1546,12 @@ class basic_json
|
||||||
|
|
||||||
@since version 1.0.0
|
@since version 1.0.0
|
||||||
*/
|
*/
|
||||||
template <
|
template <class CompatibleArrayType,
|
||||||
class CompatibleArrayType,
|
enable_if_t<detail::is_compatible_array_type<
|
||||||
enable_if_t<
|
basic_json_t, CompatibleArrayType>::value,
|
||||||
detail::disjunction<
|
|
||||||
// MSVC..
|
|
||||||
std::is_same<uncvref_t<CompatibleArrayType>, basic_json_t>,
|
|
||||||
detail::is_compatible_array_type<basic_json_t,
|
|
||||||
CompatibleArrayType>>::value,
|
|
||||||
int> = 0>
|
int> = 0>
|
||||||
basic_json(const CompatibleArrayType &val) : m_type(value_t::array) {
|
basic_json(const CompatibleArrayType &val) : m_type(value_t::array)
|
||||||
|
{
|
||||||
using std::begin;
|
using std::begin;
|
||||||
using std::end;
|
using std::end;
|
||||||
m_value.array = create<array_t>(begin(val), end(val));
|
m_value.array = create<array_t>(begin(val), end(val));
|
||||||
|
@ -1571,18 +1559,17 @@ class basic_json
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// constructor chosen when JSONSerializer::to_json exists for type T
|
// constructor chosen when:
|
||||||
// first check avoids being chosen instead of move/copy constructor
|
// - JSONSerializer::to_json exists for type T
|
||||||
|
// - T is not a istream, nor convertible to basic_json (float, vectors, etc)
|
||||||
|
// is_compatible_basic_json_type == not is_user_defined_type
|
||||||
template <
|
template <
|
||||||
typename T,
|
typename T,
|
||||||
enable_if_t<
|
enable_if_t<not std::is_base_of<std::istream, uncvref_t<T>>::value and
|
||||||
detail::conjunction<
|
not detail::is_compatible_basic_json_type<
|
||||||
detail::negation<std::is_same<uncvref_t<T>, basic_json_t>>,
|
uncvref_t<T>, basic_json_t>::value and
|
||||||
detail::negation<std::is_base_of<std::istream, uncvref_t<T>>>,
|
|
||||||
detail::negation<detail::is_compatible_basic_json_type<
|
|
||||||
uncvref_t<T>, basic_json_t>>,
|
|
||||||
detail::has_to_json<JSONSerializer, basic_json,
|
detail::has_to_json<JSONSerializer, basic_json,
|
||||||
uncvref_t<T>>>::value,
|
uncvref_t<T>>::value,
|
||||||
int> = 0>
|
int> = 0>
|
||||||
explicit basic_json(T &&val)
|
explicit basic_json(T &&val)
|
||||||
{
|
{
|
||||||
|
@ -1842,7 +1829,7 @@ class basic_json
|
||||||
*/
|
*/
|
||||||
template <
|
template <
|
||||||
typename CompatibleNumberUnsignedType,
|
typename CompatibleNumberUnsignedType,
|
||||||
enable_if_t<detail::is_compatible_unsigned_integer_type<
|
enable_if_t<detail::is_compatible_integer_type<
|
||||||
number_unsigned_t, CompatibleNumberUnsignedType>::value,
|
number_unsigned_t, CompatibleNumberUnsignedType>::value,
|
||||||
int> = 0>
|
int> = 0>
|
||||||
basic_json(const CompatibleNumberUnsignedType val) noexcept
|
basic_json(const CompatibleNumberUnsignedType val) noexcept
|
||||||
|
@ -3257,21 +3244,19 @@ class basic_json
|
||||||
@since version 1.0.0
|
@since version 1.0.0
|
||||||
*/
|
*/
|
||||||
template <typename ValueType,
|
template <typename ValueType,
|
||||||
enable_if_t<
|
enable_if_t<not std::is_pointer<ValueType>::value, int> = 0>
|
||||||
not std::is_pointer<ValueType>::value,
|
|
||||||
int> = 0>
|
|
||||||
auto get() const
|
auto get() const
|
||||||
-> decltype(this->get_impl(static_cast<ValueType *>(nullptr))) {
|
-> decltype(this->get_impl(static_cast<ValueType *>(nullptr)))
|
||||||
|
{
|
||||||
return get_impl(static_cast<ValueType *>(nullptr));
|
return get_impl(static_cast<ValueType *>(nullptr));
|
||||||
}
|
}
|
||||||
|
|
||||||
template <
|
template <
|
||||||
typename T,
|
typename T,
|
||||||
enable_if_t<detail::conjunction<
|
enable_if_t<not detail::is_compatible_basic_json_type<
|
||||||
detail::negation<detail::is_compatible_basic_json_type<
|
uncvref_t<T>, basic_json_t>::value and
|
||||||
uncvref_t<T>, basic_json_t>>,
|
|
||||||
detail::has_from_json<JSONSerializer, basic_json_t,
|
detail::has_from_json<JSONSerializer, basic_json_t,
|
||||||
uncvref_t<T>>>::value,
|
uncvref_t<T>>::value,
|
||||||
int> = 0>
|
int> = 0>
|
||||||
auto get() const -> uncvref_t<T>
|
auto get() const -> uncvref_t<T>
|
||||||
{
|
{
|
||||||
|
|
Loading…
Add table
Reference in a new issue