From 536672e927b3fd7f911e7fb39ce775ca4722709e Mon Sep 17 00:00:00 2001 From: Niels Lohmann Date: Fri, 23 Oct 2026 09:44:39 +0200 Subject: [PATCH] Dispatch on the compile-time conditions of the json_view comparison MSVC (/W4 /WX) reported C4127 (conditional expression is constant) for the template parameter EA and the object type's ordering in an if condition; both are now tag-dispatched. Signed-off-by: Niels Lohmann --- include/nlohmann/detail/view/compare.hpp | 32 +++++++++++++++++++++--- single_include/nlohmann/json_view.hpp | 32 +++++++++++++++++++++--- 2 files changed, 58 insertions(+), 6 deletions(-) diff --git a/include/nlohmann/detail/view/compare.hpp b/include/nlohmann/detail/view/compare.hpp index 42501f918..62d965937 100644 --- a/include/nlohmann/detail/view/compare.hpp +++ b/include/nlohmann/detail/view/compare.hpp @@ -721,6 +721,18 @@ class lockstep } } + /// whether the object @a a of a document that cannot be edited has scalar values only + static bool scalar_values_only(const node* a, std::false_type /*editable*/) noexcept + { + return a->next == 1 + (2 * static_cast(a->len)); + } + + /// (the nodes of an editable document can be elsewhere: not decided) + static bool scalar_values_only(const node* /*a*/, std::true_type /*editable*/) noexcept + { + return false; + } + /// Whether the comparison that follows visits the members of the object a in the /// order of the document: if the object type keeps the order, if the keys /// ascend (it sorts by key), or if all values are scalars (then the walk costs @@ -733,9 +745,9 @@ class lockstep { return true; } - if (!EA && a->next == 1 + (2 * static_cast(a->len))) + if (scalar_values_only(a, std::integral_constant {})) { - return true; // (scalar values only) + return true; } const node* k = nav_a::first(m_a, a); string_ref previous(m_a.str(*k), k->len); @@ -897,6 +909,20 @@ bool keys_differ_early(const SideA& a, const SideB& b) return false; } +/// keys_differ_early() for a type that keeps the order of the members +template +bool keys_differ_early(const SideA& a, const SideB& b, std::true_type /*ordered*/) +{ + return keys_differ_early(a, b); +} + +/// (a type that sorts the members by key: not decided early) +template +bool keys_differ_early(const SideA& /*a*/, const SideB& /*b*/, std::false_type /*ordered*/) noexcept +{ + return false; +} + inline bool is_number(value_t t) noexcept { return t == value_t::number_integer || t == value_t::number_unsigned || t == value_t::number_float; @@ -987,7 +1013,7 @@ bool equal(const A& a0, const B& b0) { return false; } - if (ordered && ta == value_t::object && keys_differ_early(a, b)) + if (ta == value_t::object && keys_differ_early(a, b, std::integral_constant::value> {})) { return false; } diff --git a/single_include/nlohmann/json_view.hpp b/single_include/nlohmann/json_view.hpp index b3b6260e8..ea598720f 100644 --- a/single_include/nlohmann/json_view.hpp +++ b/single_include/nlohmann/json_view.hpp @@ -3341,6 +3341,18 @@ class lockstep } } + /// whether the object @a a of a document that cannot be edited has scalar values only + static bool scalar_values_only(const node* a, std::false_type /*editable*/) noexcept + { + return a->next == 1 + (2 * static_cast(a->len)); + } + + /// (the nodes of an editable document can be elsewhere: not decided) + static bool scalar_values_only(const node* /*a*/, std::true_type /*editable*/) noexcept + { + return false; + } + /// Whether the comparison that follows visits the members of the object a in the /// order of the document: if the object type keeps the order, if the keys /// ascend (it sorts by key), or if all values are scalars (then the walk costs @@ -3353,9 +3365,9 @@ class lockstep { return true; } - if (!EA && a->next == 1 + (2 * static_cast(a->len))) + if (scalar_values_only(a, std::integral_constant {})) { - return true; // (scalar values only) + return true; } const node* k = nav_a::first(m_a, a); string_ref previous(m_a.str(*k), k->len); @@ -3517,6 +3529,20 @@ bool keys_differ_early(const SideA& a, const SideB& b) return false; } +/// keys_differ_early() for a type that keeps the order of the members +template +bool keys_differ_early(const SideA& a, const SideB& b, std::true_type /*ordered*/) +{ + return keys_differ_early(a, b); +} + +/// (a type that sorts the members by key: not decided early) +template +bool keys_differ_early(const SideA& /*a*/, const SideB& /*b*/, std::false_type /*ordered*/) noexcept +{ + return false; +} + inline bool is_number(value_t t) noexcept { return t == value_t::number_integer || t == value_t::number_unsigned || t == value_t::number_float; @@ -3607,7 +3633,7 @@ bool equal(const A& a0, const B& b0) { return false; } - if (ordered && ta == value_t::object && keys_differ_early(a, b)) + if (ta == value_t::object && keys_differ_early(a, b, std::integral_constant::value> {})) { return false; }