diff --git a/src/json.hpp b/src/json.hpp index 2ab6efd96..109691380 100644 --- a/src/json.hpp +++ b/src/json.hpp @@ -130,11 +130,17 @@ using conditional_t = typename std::conditional::type; namespace detail { -// implementation of 3 C++17 constructs: conjunction, disjunction, negation. -// This is needed to avoid evaluating all the traits, MSVC cannot compile due -// to std::is_constructible being instantiated -// (void -> back_insert_iterator::value_type) -// this could slow down compilation, since this implementation is taken from the example in cppreference... +// Implementation of 3 C++17 constructs: conjunction, disjunction, negation. +// This is needed to avoid evaluating all the traits in a condition +// +// For example: not std::is_same::value and has_value_type::value +// will not compile when T = void (on MSVC at least) +// Whereas conjunction>, has_value_type>::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 struct conjunction : std::true_type {}; template struct conjunction : B1 {}; template @@ -192,6 +198,8 @@ struct is_compatible_object_type_impl template 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< conjunction>, has_mapped_type, @@ -223,17 +231,14 @@ struct is_compatible_array_type_impl template struct is_compatible_array_type { - static auto constexpr value = disjunction< - std::is_same, - is_compatible_array_type_impl< - conjunction>, - negation>, - has_value_type, - has_iterator>::value, - BasicJson, CompatibleArrayType>>::value; + // the check for CompatibleArrayType = void is done in is_compatible_object_type + // but we need the conjunction here as well + static auto constexpr value = is_compatible_array_type_impl< + conjunction>, + has_value_type, + has_iterator>::value, + BasicJson, CompatibleArrayType>::value; }; template @@ -242,11 +247,14 @@ struct is_compatible_integer_type_impl : std::false_type{}; template struct is_compatible_integer_type_impl { + using RealLimits = std::numeric_limits; + using CompatibleLimits = std::numeric_limits; + static constexpr auto value = std::is_constructible::value and - std::numeric_limits::is_integer and - std::numeric_limits::is_signed; + CompatibleLimits::is_integer and + RealLimits::is_signed == CompatibleLimits::is_signed; }; template @@ -257,27 +265,6 @@ struct is_compatible_integer_type CompatibleNumberIntegerType>::value; }; -template -struct is_compatible_unsigned_integer_type_impl : std::false_type{}; - -template -struct is_compatible_unsigned_integer_type_impl -{ - static constexpr auto value = - std::is_constructible::value and - std::numeric_limits::is_integer and - not std::numeric_limits::is_signed; -}; - -template -struct is_compatible_unsigned_integer_type -{ - static constexpr auto value = is_compatible_unsigned_integer_type_impl< - std::is_arithmetic::value, RealUnsignedType, - CompatibleNumberUnsignedType>::value; -}; - template struct is_compatible_float_type { @@ -298,8 +285,8 @@ struct is_compatible_basic_json_type is_compatible_float_type::value or is_compatible_integer_type::value or - is_compatible_unsigned_integer_type::value; + is_compatible_integer_type::value; }; template