diff --git a/include/nlohmann/detail/meta/type_traits.hpp b/include/nlohmann/detail/meta/type_traits.hpp index 7036a4ef0..1d5092742 100644 --- a/include/nlohmann/detail/meta/type_traits.hpp +++ b/include/nlohmann/detail/meta/type_traits.hpp @@ -699,21 +699,35 @@ struct is_json_pointer_of> : std::true_type {}; template struct is_json_pointer_of&> : std::true_type {}; -// checks if A and B are comparable using Compare functor +// checks if A and B are comparable using Compare functor, assuming that +// neither A nor B is a json_pointer type (that case is handled by +// is_comparable below, which never instantiates this helper otherwise) template -struct is_comparable : std::false_type {}; +struct is_comparable_no_json_pointer : std::false_type {}; -// We exclude json_pointer here, because the checks using Compare(A, B) will -// use json_pointer::operator string_t() which triggers a deprecation warning -// for GCC. See https://github.com/nlohmann/json/issues/4621. The call to -// is_json_pointer_of can be removed once the deprecated function has been -// removed. template -struct is_comparable < Compare, A, B, enable_if_t < !is_json_pointer_of::value -&& std::is_constructible ()(std::declval(), std::declval()))>::value +struct is_comparable_no_json_pointer < Compare, A, B, enable_if_t < +std::is_constructible ()(std::declval(), std::declval()))>::value && std::is_constructible ()(std::declval(), std::declval()))>::value >> : std::true_type {}; +// checks if A and B are comparable using Compare functor +// We dispatch on is_json_pointer_of as a plain bool (rather than folding it +// into a single enable_if_t condition together with the checks below) so +// that the Compare(A, B) checks are only ever written - and thus only ever +// instantiated - when A/B are not a json_pointer/string pair. Those checks +// use json_pointer::operator string_t() (GCC, see #4621) resp. the +// deprecated json_pointer/string operator== (Clang, see #5288), and merely +// naming them as later operands of a plain && chain is not sufficient to +// avoid their instantiation on all compilers, even when the first operand +// is false. The dispatch on is_json_pointer_of can be removed once the +// deprecated json_pointer comparison operators have been removed. +template::value> +struct is_comparable : std::false_type {}; + +template +struct is_comparable : is_comparable_no_json_pointer {}; + template using detect_is_transparent = typename T::is_transparent; diff --git a/single_include/nlohmann/json.hpp b/single_include/nlohmann/json.hpp index 580b9bd02..5eca64153 100644 --- a/single_include/nlohmann/json.hpp +++ b/single_include/nlohmann/json.hpp @@ -4462,21 +4462,35 @@ struct is_json_pointer_of> : std::true_type {}; template struct is_json_pointer_of&> : std::true_type {}; -// checks if A and B are comparable using Compare functor +// checks if A and B are comparable using Compare functor, assuming that +// neither A nor B is a json_pointer type (that case is handled by +// is_comparable below, which never instantiates this helper otherwise) template -struct is_comparable : std::false_type {}; +struct is_comparable_no_json_pointer : std::false_type {}; -// We exclude json_pointer here, because the checks using Compare(A, B) will -// use json_pointer::operator string_t() which triggers a deprecation warning -// for GCC. See https://github.com/nlohmann/json/issues/4621. The call to -// is_json_pointer_of can be removed once the deprecated function has been -// removed. template -struct is_comparable < Compare, A, B, enable_if_t < !is_json_pointer_of::value -&& std::is_constructible ()(std::declval(), std::declval()))>::value +struct is_comparable_no_json_pointer < Compare, A, B, enable_if_t < +std::is_constructible ()(std::declval(), std::declval()))>::value && std::is_constructible ()(std::declval(), std::declval()))>::value >> : std::true_type {}; +// checks if A and B are comparable using Compare functor +// We dispatch on is_json_pointer_of as a plain bool (rather than folding it +// into a single enable_if_t condition together with the checks below) so +// that the Compare(A, B) checks are only ever written - and thus only ever +// instantiated - when A/B are not a json_pointer/string pair. Those checks +// use json_pointer::operator string_t() (GCC, see #4621) resp. the +// deprecated json_pointer/string operator== (Clang, see #5288), and merely +// naming them as later operands of a plain && chain is not sufficient to +// avoid their instantiation on all compilers, even when the first operand +// is false. The dispatch on is_json_pointer_of can be removed once the +// deprecated json_pointer comparison operators have been removed. +template::value> +struct is_comparable : std::false_type {}; + +template +struct is_comparable : is_comparable_no_json_pointer {}; + template using detect_is_transparent = typename T::is_transparent;