恒美微站 Logo 恒美微站
  • 首页
  • 关于我们
  • 建站服务
  • 主题模板
  • 案例展示
  • 资讯中心
  • 联系我们

JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON 详解:nlohmann/json 中 discarded 值的比较语义宏

  • 首页
  • 资讯中心
  • /
  • JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON 详解:nlohmann/json 中 discarded 值的比较语义宏

相关资讯

MindSpore花卉识别实战:小样本本地部署指南 2026/9/10 14:10:57
YOLOv8烟头识别实战:从数据标注到部署优化全指南 2026/9/10 14:10:57
基于电影知识图谱与微信小程序的智能问答系统实践 2026/9/10 14:10:57

最新资讯

【亲测免费】 Ffmpeg.js 项目推荐
Wayland + NVIDIA 环境下 CC Switch 主界面点击无响应怎么解决?
TVBoxOSC 上手指南:不编译也能拿到最新电视盒子版 TVBox
Python面向对象编程:类与对象、三大特性及实战应用
Kivy跨平台应用开发实战:从环境搭建到发布
tldraw 修改默认样式指南:用 StyleProp.setDefaultValue 控制新形状的默认 size、color、dash 与 fill

今日推荐

AI搜索重构内容生态:企业从“流量争夺”转向“答案共建”
AI搜索的信任缺口:企业内容如何在答案时代自证可信
Spring Boot+Vue+Node.js售后服务系统开发实战

本周热门

超人会飞不算本事:系统稳定依赖清晰规则与边界设计
超人VS蜘蛛侠:拆解超级IP的影响力与传播方法论
基于CNN的调制信号识别:MATLAB实现时频图分类实战

本月精选

自研推理加速器Redwood:两周内实现PyTorch模型高效部署的实战教程
V4L2摄像头采集实战:从camera_client.rar到出图全流程解析
从“谁发明了钢琴键”到知识问答智能体:RAG与记忆工程实践

JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON 详解:nlohmann/json 中 discarded 值的比较语义宏

发布时间:2026/9/10 14:10:57
JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON 详解:nlohmann/json 中 discarded 值的比较语义宏 JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON 详解nlohmann/json 中 discarded 值的比较语义宏【免费下载链接】jsonJSON for Modern C项目地址: https://gitcode.com/GitHub_Trending/js/json本文基于 JSON for Modern Cnlohmann/json官方文档 JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON结合仓库源码与单元测试完整讲解该宏的默认定义、行为差异、源码实现原理、CMake 开关方式、C20 下的不一致风险以及迁移建议。读完本文你将清楚何时需要开启该宏、它会产生什么样的历史兼容行为以及为什么新代码应当避免依赖它。一、背景什么是 discarded 值为什么它的比较很特殊nlohmann::json在内部用value_t::discarded表示一种占位 / 待定状态在 value_t.hpp 定义的类型枚举中discarded与null、boolean、number_integer、number_unsigned、number_float、object、array、string、binary并列。从源码与测试看解析器在处理数组/对象元素时、以及部分内部流程中会临时用到该状态开发者也可以通过构造函数json j(json::value_t::discarded);显式构造这样的值并可用is_discarded()成员进行判别。问题在于一个 discarded 值既不是 null也不是任何有意义的 JSON 数据它在逻辑上与任何值包括它自身都无法比较。这给比较运算符、!、、、、的设计带来了语义分叉现代默认语义比较时一旦任一方是 discarded比较结果一律视为不可比较不给出任何有意义的真/假关系旧版legacy语义在早期版本中部分运算符会碰巧返回特定结果例如!为true、为true这正是该宏要复刻的历史行为。而JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON宏就是用来在这两套语义之间切换的开关。二、宏声明与行为对照表宏的声明形式如下#define JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON /* value */可取值值含义1启用incorrect 的legacy 比较行为0禁用默认值2.1 启用 legacy 行为时的比较结果当宏被定义为1时只要比较中的至少一方是 discarded 值各运算符的结果如下运算符结果#!cpp false!#!cpp true#!cpp false#!cpp true#!cpp true#!cpp false这组结果对 discarded 值参与的任何比较都成立无论另一侧是 null、数字、字符串、数组、对象还是另一个 discarded 值。2.2 关闭该宏默认时的比较结果宏取值为0即默认关闭时只要比较中涉及至少一个 discarded 值所有比较运算符一律返回#!cpp false。也就是说默认语义下 discarded 值不满足相等、不满足不等、也不满足任何大小关系是最纯粹的不可比较语义。三、默认定义与宏的未定义即回退机制官方文档规定默认值为0#define JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON 0在源码中这一默认值由 abi_macros.hpp 兜底实现#ifndef JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON #define JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON 0 #endif也就是说即使用户没有预先定义该宏库也会在编译头文件时自动将其赋值为默认的0因此该宏在正常情况下始终存在一个确定值不会出现未定义的悬空状态。需要特别注意的还有两个派生影响ABI 命名空间标记同一文件 abi_macros.hpp 中启用该宏会使 ABI 标签组件变成_ldvcmp#if JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON #define NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON _ldvcmp #else #define NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON #endif从源码结构看该标签会拼入NLOHMANN_JSON_ABI_TAGS见同文件 L59-L68并作为库内联命名空间的一部分。因此开启与关闭该宏编译出的nlohmann::json分属不同 inline namespace二者混链例如把用宏编译的 ABI 测试目标与未用宏编译的目标放在一起会引发 ODR/ABI 不匹配必须全工程一致后再使用。头文件尾部清理在 macro_unscope.hpp 中存在对该宏的#undef。这保证了库不会把自己的配置宏泄漏到用户代码的预处理环境中也意味着每次启用都必须在包含nlohmann/json.hpp之前先完成#define详见本文第六节示例。四、如何在工程中开启源码宏与 CMake 选项4.1 方式一源码级#define在任何包含nlohmann/json.hpp或单头版本 single_include/nlohmann/json.hpp的编译单元中于 include 之前写入#define JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON 1 #include nlohmann/json.hpp // ...官方文档给出的示例即为这种先定义宏、再包含头文件的标准用法#define JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON 1 #include nlohmann/json.hpp ...4.2 方式二CMake 选项JSON_LegacyDiscardedValueComparison相比手写宏官方更推荐在 CMake 工程中使用配套选项统一控制。仓库根目录 CMakeLists.txt 中声明了该选项option(JSON_LegacyDiscardedValueComparison Enable legacy discarded value comparison. OFF)其默认值为OFF。当该选项开启时工程会在编译目标上注入对应的编译定义相关定义位于 CMakeLists.txt 与 CMakeLists.txt例如通过类似下面的方式向目标附加宏$$BOOL:${JSON_LegacyDiscardedValueComparison}:JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON1即JSON_LegacyDiscardedValueComparison只是该宏在 CMake 层的转发开关默认OFF最终效果完全等同于源码级定义JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON1。相关选项文档见 integration/cmake.md。典型用法示例cmake -DJSON_LegacyDiscardedValueComparisonON ..五、源码级原理compares_unordered与运算符宏要理解该宏为什么能产生上面那张行为表需要回到 json.hpp 中比较运算符的统一实现。库内部通过JSON_IMPLEMENT_OPERATOR宏展开各比较运算符其整体逻辑是先做类型化的数值比较若遇到无法比较的情形任一操作数是 NaN 相关的浮点、或任一操作数是 discarded则落到 unordered 分支返回预先指定的结果见 json.hpp 附近的宏结尾。关键函数是compares_unorderedjson.hppstatic bool compares_unordered(const_reference lhs, const_reference rhs, bool inverse false) noexcept { if ((lhs.is_number_float() std::isnan(lhs.m_data.m_value.number_float) rhs.is_number()) || (rhs.is_number_float() std::isnan(rhs.m_data.m_value.number_float) lhs.is_number())) { return true; } #if JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON return (lhs.is_discarded() || rhs.is_discarded()) !inverse; #else static_castvoid(inverse); return lhs.is_discarded() || rhs.is_discarded(); #endif }这里可以看到两套逻辑的差别宏关闭默认只要任一方是 discardedcompares_unordered恒返回true对应所有运算符都落入 unordered 分支并得到false——这正是文档所说的比较总是返回 false。宏开启legacy引入了inverse参数。注释json.hpp明确写道legacy 模式下当某个运算在语义上相当于对其他运算符取奇数次逆运算时discarded 值会被视为有序。所谓奇数次逆运算直接对应与在实现上是!(rhs *this)一次取反 交换属于对的一次逆是!(*this rhs)。于是 legacy 模式专门为和补了额外重载见 json.hpp核心逻辑为先用带inversetrue的compares_unordered判断若为 false 则按!(rhs *this)/!(*this rhs)计算。这样 discarded 与其它值比较时、各自通过取反一次小于关系得到true而、仍因 unordered 返回false最终合成出行为表中 true / true / false / false的组合。这些额外重载还带有自 3.11.0 起的弃用标注JSON_HEDLEY_DEPRECATED_FOR(3.11.0, ...)。该行为在测试中得到验证开启宏时unit-comparison.cpp 会打印using legacy comparison并专门为compares_unordered(..., true)准备了 22×22 的期望矩阵见 unit-comparison.cpp其j_values向量中同样纳入了json(json::value_t::discarded)作为比较对象见 unit-comparison.cpp 的类型矩阵与 unit-comparison.cpp 附近的值矩阵。此外测试注释还指出当前实现中!就是!(a b)不再为 discarded/NaN 设置特殊例外见 unit-comparison.cpp这些都可以作为阅读与调试该宏行为的直接依据。六、完整可运行示例下面是一个把宏切换为1的最小程序。它显式构造一个 discarded 值并与普通数值比较输出将严格符合 legacy 行为表#define JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON 1 #include nlohmann/json.hpp #include iostream int main() { using nlohmann::json; // 显式构造 discarded 值解析过程中也可能临时出现该状态 const json discarded json(json::value_t::discarded); const json number 42; std::cout std::boolalpha; std::cout discarded 42 : (discarded number) \n; // false std::cout discarded ! 42 : (discarded ! number) \n; // true std::cout discarded 42 : (discarded number) \n; // false std::cout discarded 42 : (discarded number) \n; // true std::cout discarded 42 : (discarded number) \n; // true std::cout discarded 42 : (discarded number) \n; // false }如果删除文件开头的#define ... 1保持默认0上面六个表达式将全部输出false。将该代码与官方 单元测试用例 中的期望矩阵对照即可直观体会到两套语义的差异。编译方式仓库为 header-only 库只需指向头文件目录g -stdc17 -I include example.cpp -o example # 若使用单头版本可改为 -I single_include提示开启 legacy 行为后最好全工程统一通过 CMake 选项JSON_LegacyDiscardedValueComparisonON管理避免各编译单元宏状态不一致引发 ABI 命名空间_ldvcmp标签冲突。七、C20 及以上的不一致警告官方文档对 C20 及更高标准给出强烈警告在此类模式下开启 legacy 比较行为会非常危险原因有二三路比较运算符永远返回正确结果。无论JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON取值如何涉及 discarded 值的恒返回std::partial_ordering::unordered相等与关系运算符的重载却模拟 legacy 行为本文第五节介绍的、专用重载即在此生效。也就是说在 C20 工程里你以为的 和 与 别人代码里用 推导出的结果 可能相互矛盾同一份数据在不同代码路径下会得到不一致且难以预测的结果。这本质上是历史怪癖 现代语义在同一头文件内共存带来的割裂。因此凡是代码不属于你能完全控制的范围都不应开启该宏。关于三路比较的完整语义可进一步参考 operator3-way comparison 文档页。八、弃用声明与迁移建议文档同时明确指出该 legacy 比较行为已被弃用并可能在未来主版本发布中被移除。因此新代码不应依赖它不要在业务逻辑里以 discarded 值的比较结果作为分支依据已有代码应尽早改写如果线上代码里存在依赖discarded!为 true /为 true之类结果的地方应逐条审计并重写为显式判空 显式类型检查例如用is_discarded()、is_null()等谓词先行分流再决定是否进入比较逻辑在 C20 代码库中应保持宏关闭默认0让所有比较统一走的unordered语义。从何时引入、何时弃用的时间线看该宏自3.11.0版本加入见本文件 Version history 部分自加入之初即被标记为 deprecated源码中额外重载上的JSON_HEDLEY_DEPRECATED_FOR(3.11.0, ...)注解与此一致足以说明它只是为平滑迁移提供的过渡开关而非长期支持的 API。九、总结一句话概括JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON的定位它是一个编译期行为开关用来在discarded 值一律不可比较默认、语义正确与复刻早期版本中!//碰巧返回 true 的历史怪癖legacy、已弃用之间切换。它的默认值为0官方不鼓励开启若确需开启应优先使用 CMake 选项 JSON_LegacyDiscardedValueComparison默认OFF并在全工程保持一致同时避开 C20 及以上代码路径且规划好未来对依赖它的旧表达式进行清除。参见JSON_LegacyDiscardedValueComparison CMake 选项——用于在 CMake 工程中控制本宏的等价开关operator3-way comparison——C20 下不受本宏影响的比较实现宏总览——nlohmann/json 全部配置宏的索引宏默认值定义 与 ABI 标签组装——默认值兜底与_ldvcmp标签的源码实现比较运算符核心实现——compares_unordered与 legacy 专用重载的源码位置比较行为单元测试——含 discarded 在内的全类型比较期望矩阵与验证逻辑版本历史该宏于3.11.0版本加入同时自该版本起被标注为 deprecated。【免费下载链接】jsonJSON for Modern C项目地址: https://gitcode.com/GitHub_Trending/js/json创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

关于恒美微站

恒美微站专注于为个体商户、工作室提供极简自助建站服务,让每个人都能轻松拥有专业网站。

快速链接

  • 关于我们
  • 建站服务
  • 主题模板
  • 案例展示
  • 资讯中心

服务项目

  • 可视化建站
  • 拖拽编辑
  • 主题定制
  • SEO 优化
  • 网站托管

联系方式

  • 📍 地址:北京市朝阳区建国路 88 号
  • 📞 电话:400-888-8888
  • ✉️ 邮箱:info@hmyw.cn
  • 🕐 时间:周一至周日 9:00-18:00

© 2024 恒美微站 hmyw.cn 版权所有 | 京 ICP 备 12345678 号