摘要
C++26 周期, SG21 紧密地跟随了 P2965R1 的计划, 撰写了面向 C++26 的 C++ 标准契约设施的最小可行性提案 (Minimal Viable Product): P2900R10 - Contracts For C++. 本文作为该提案的补充, 介绍了该 MVP 提案背后的演变与逻辑, 同时讲解了其中的部分设计决策.
概述
契约 MVP 提案 介绍了契约的基本术语, 阐述了其应用范围和具体设计, 并给出了相应的 wording, 但对一些非常重要的背景, 如其中的设计决策, 考虑过的替代方案, 以及各个部分的来龙去脉, 并没有完全的展示. 本文补充了这些细节, 可以帮助大家更好地理解契约 MVP 提案,尤其能为那些希望在现有基础上进一步贡献力量的人提供参考.
本文分为两部分. 第一部分是 "概述", 主要包含了该提案的设计初衷, 我们希望通过它实现的目标, 以及对其他编程语言中相关技术的介绍,当然, 还有 C++ 标准化契约的一些历史. 第二部分是 "提议设计", 与 P2900R10 一小节一小节地对应, 包含了设计动机与尽可能完整的设计决策历史, 并引用了大量由 WG21 和 SG21 成员为此撰写的论文.
任何在 SG21 中达成了共识, 并影响了 P2900R10 的论文, 我们都会在此进行重点参考, 对它的动机和使用场景进行深入探讨, 以更好地理解它们的初衷. 有些设计决策是在 SG21 或其他相关 WG21 小组中讨论并确定的, 我们也会在这里总结这些讨论, 并附上相关的投票结果.
本文统一使用 P2900R10 第 2 节中定义的术语来指代与契约相关的概念和实体. 引用的许多论文或其他契约相关文献可能使用了不同的术语, 为了方便理解, 我们会在必要时进行特别说明.
契约的目的
P2900R10 第 2.1 节对契约进行了形式上的描述, 对 自然语言契约 与 契约断言 两个概念进行了辨析, 同时将 契约设施 定义为 "一种支持用户编写契约断言, 并指定断言的不同种类 (如前置条件断言, 后置条件断言) 的语言特性". 然而, 它并没有回答一个问题: 我们为什么要设计契约?
据 P2900R10 的描述, 契约断言的主要目的是在 C++ 程序的一定位置 (尤其包含调用函数, 从函数返回时), 允许程序员用它表述在此处对程序正确性的期望, 并且在程序求值时对上述期望进行可手动开关的验证, 进而能够 暴露程序缺陷, 同时提供灵活, 可迁移, 扩展性强的, 对程序缺陷进行缓和的手段.
当然, 我们也可以这样描述 P2900R10 的目标: 用提出的契约断言, 取代 C 中的 assert
及相关 断言宏 并取得额外的收益, 如: