Newshot
Account

C++ 新标准首次未获各国标准机构通过

AI summary

一项 C++ 标准提案首次未能通过各国标准机构的投票。这是 C++ 标准化进程中第一次出现标准未获国家机构通过的情况。

Translation(model translation, not the source's own text)
Bjarne Stroustrup,本人。
Bjarne Stroustrup,本人。

开瓶庆祝。

看起来这事真的发生了!无论好坏,这都是历史性的第一次。

这是一个信号,表明 C++(仍然)在治理方面挣扎(参见此前一篇关于 C++ 内部文化问题的文章)。即使你不关心编程语言,这也是件大事。C++ 可以说是现存最重要的编程语言。

你的计算机运行在 C 或 C++ 之上。你用来阅读本文的网页浏览器是用 C++ 写的。~所有编程语言都依赖 C++(通常通过 LLVM)。同样,~所有有性能要求的网站(例如 YouTube)都依赖 C++,~所有数据存储、游戏引擎、金融等等。

在一个~所有软件都充斥着令人兴奋的新漏洞的世界里,C++ 能否改变并适应变化的时代,会影响到你。

让我们退一步,做个概览。最初的来源是 Robert Seacord 在 LinkedIn 上的一篇帖子:

“C++26 的投票已经完成。不幸的是它被否决了。P-Members 投票:20 票中 12 票赞成 = 60%(要求 >= 66.66%)(投弃权票的 P-Members 不计入本次投票。)成员机构投票:22 票中 9 票反对 = 41%(要求 <= 25%)。对 C++ 社区来说,这算是个悲伤的日子。希望我们能愈合创伤,并以建设性的方式继续前行。”
“C++26 的投票已经完成。不幸的是它被否决了。P-Members 投票:20 票中 12 票赞成 = 60%(要求 >= 66.66%)(投弃权票的 P-Members 不计入本次投票。)成员机构投票:22 票中 9 票反对 = 41%(要求 <= 25%)。对 C++ 社区来说,这算是个悲伤的日子。希望我们能愈合创伤,并以建设性的方式继续前行。”

在一条评论中,J. Daniel García 补充道:“有 12 个国家投了弃权票。其中几个是因为它们无法达成共同立场。这是草案存在争议的又一个信号。”

现在,在我们进入事实之前:这对 C++ 来说不是什么好形象。

围绕 C++ 语言的未来方向曾有过多次争斗,但从未有 C++ 标准被国家机构否决过。

国家机构投票被认为是一种形式。当投票到达国家机构时,所有分歧本应已由 WG21(Working Group 21,即 C++ 标准委员会)解决。

真正有争议的特性绝不应该走到这一步,因为它们从一开始就不应该被加入 C++26 工作草案。这是 C++ 社区内部分裂的信号,无论以何种形式,也完全独立于你是否同意这一结果。

在这里,“加入 C++26 工作草案”本质上就是接受 pull request。所有人都在为 C++26 的发布而努力,人们通过论文为其做贡献。论文导致投票,投票进而导致草案修订。最后(也就是我们现在所处的阶段)是措辞通过,然后它被签署、橡皮图章式批准并发布。这样表述的话,ISO 流程听起来足够合理,但相信我,它实际上有点像噩梦。

不用说,辩论正在激烈进行,各方都有评论:如此多的讨论。

简要说明:国家机构执行一次投票。要通过国家机构,草案必须满足两个门槛:

  • 至少三分之二的参与投票成员投赞成票。
  • 至多四分之一的全体投票成员可以投反对票。

如果上述帖子正确,那么草案两个门槛都未达到。十二不是二十的三分之二,而九超过四分之一。可视化:

总共有 20 个 P-members,以及 22 个全体成员(忽略弃权)。我听说美国投了弃权票,但对此请持保留态度。

那么,发生了什么?

tl;dr:WG21 投票决定将 Contracts 纳入 C++26。WG21 的几位高层成员强烈反对 Contracts,几个国家机构也是如此。国家机构投票是阻止 Contracts 被正式纳入 C++ 标准的“最后手段”。

像 {{NAME_ab12cd34}} 这样写出的值是真实值的占位符。在回复和工具调用中完全按原样使用它们:它们会在任何东西运行之前被填入真实值。不要要求验证它们,也不要用示例替换它们。

用新关键字取代 assert 宏,以标准化方式实施运行时检查。最重要的是,你可以添加前置和后置检查,确保所有参数和返回值满足特定条件。

最终大致如下所示:


        int wrap_index(int i, const int size)
    pre (size > 0)               // 调用方必须保证这一点
    post (r: 0 <= r && r < size) // 函数承诺这一点;r 是返回值
{
    int r = i % size;
    if (r < 0) r += size;
    contract_assert(r >= 0);     // 函数体内的检查
    return r;
}
      

看起来很简单,对吧?你可能会这么想,但并非如此!

首先,由于虚函数的问题,针对虚函数的 Contracts 已从提案中删除。

其次,它与 constexpr 或函数内联如何交互并不完全显而易见。

第三,存在编译标志可以选择性地启用或禁用强制执行。例如,“如果违反了 contract,你希望 1) 终止程序,2) 调用‘contract 违规处理器’然后终止程序,3) 记录错误,4) 完全忽略(出于性能原因甚至不执行检查)?”

大问题:你用 enforce 编译代码,并链接一个预构建的库,该库引入了与你相同的依赖,但 Contracts 设置为 ignore。根据 Contracts 的规定,这是可以的。链接器会保留其中一份副本。会发生什么?Contracts 会运行还是不运行?如果调用跨翻译单元内联呢?

用户是否有办法保证检查始终运行?(答案是没有。什么?你希望这个特性可以用来确保某些防止未定义行为的检查无论如何都会始终运行?别傻了——这是 C++。)

哦,我提到过谓词内部的代码只是标准 C++,所以编译器可以因未定义行为而省略检查吗?

但请随意从源头了解:“Contracts 论文”可以在这里找到,如果你仔细阅读,你会发现一些有趣的陈述,确实引起了一些人的不满:

如果同一函数的多个首次声明位于不同的翻译单元中,且这些翻译单元不具有相同的函数 contract 说明符序列,则程序 ill-formed,无需诊断(IFNDR)。

所有这些导致了如此多有趣的问题,其中一些问题可以粗略地概括为“好吧,谁知道你的 Contracts 是否会被执行,这是 C++,编译器可以为所欲为 lol”。

如果你认为“哎呀,这个提案看起来相当复杂和混乱”,请记住 Contracts 论文被明确设计为一个人人都能达成一致的最小可行产品。

如果你只是稍微关注了一下 C++,你可能会假设 Profiles(也就是 Bjarne Stroustrup 通过魔法仙尘让 C++ 更安全的倡议,同样有争议,并被一些人认为“无法实现”)是症结所在,但不是,Profiles 没有进入 C++26。

我们怎么知道是 Contracts?

哦,你知道的,只是因为所有人都在谈论它。

最明显的是,支持 Contracts 的阵营于 10 月 23 日发布了“Do not remove Contracts from C++26”,即大约在国家机构投票截止的时候。Vinnie Falco(反对 Contracts 最直言不讳的声音)在同一天以“Do Remove Contracts From C++26”作为回应1。

如果你一直在关注,这里有一连串的论文和事件。

我们有演讲,以及 C++ 的创造者 Bjarne Stroustrup 本人说“它声称是最小可行产品。它并不最小。我不认为它可行”。

我们有多篇论文,比如“Contract Concerns”、“Contracts make C++ less safe — full stop!”或“Contracts’ fundamental flaws”(都相当短),反对 Contracts 论文及其理由文档这个庞然大物(合在一起,将近 300 页)。

我们已经进行了多次投票。最重要的是(Hagenberg,2025年2月15日),正式将 Contracts 加入 C++26 工作草案的投票结果为100票赞成、14票反对、12票弃权。多次将 Contracts 从草案中移除的投票均未通过,最近一次是在 Croydon,同时也是支持强制合约执行机制的修正案未能通过的那次。

如果你看到这里已经走神了,我不怪你!

整个局面一团糟,试图从外部跟踪进展是徒劳的:你基本上被迫去追踪枯燥的会议记录,并在人们发布的各种草案中揣摩言外之意。别这么做。

这不是 Contracts 第一次经历这种事了:大约在2018年,另一个版本的 Contracts 曾被拿出来讨论,不久之后就被踢了出去。此时 SG21(“Study Group 21”)成立,专门致力于改造 Contracts 概念,以产出目前草案中的新“最小可行产品”。

整个局面反反复复,导致 Contracts 论文经历了十四次修订,过程中收到了来自各国代表团的许多意见,最终有些人明确呼吁各国代表团否决 C++26。(我们称之为“核选项”。顺便说一句,签署这一呼吁的一些人本身就是各国代表团的成员。)

这随后确实发生了。

我们现在处于什么位置?

你需要理解的是,Hagenberg 的投票(关于将 Contracts 加入工作草案)是强烈支持 Contracts 的。100票赞成对14票反对并不是一个微弱的结果。这使得最终投票如此惨败(12票赞成、8票反对,很糟糕)令人极为困惑。

关于发生了什么,有一种说法是这样的:

“有一个声势浩大的少数派强烈反对 Contracts 进入 C++26。这个群体包括一些很有影响力的人,例如 Bjarne Stroustrup。这个群体的一些成员积极游说各国代表团投票反对 Contracts,尽管 WG21 已经达成了一致,并同意 Contracts 应以当前形式发布。”

这与我们看到的证据相符(赞成票、一些人强烈反对)。Herb Sutter 在他最新的论文中提出了这一点,见这里。(需要说明的是,Herb Sutter 曾是 C++ 委员会主席,并且(仅次于 Bjarne)可能是 C++ 世界中人们最愿意倾听的第二号人物。)

这听起来合理,但我不相信。至少不完全相信。是的,游说确实发生了,Bjarne 的意见也是人们会倾听的。这可能是决定性因素,但如果它确实是决定性因素,那么这表明流程本身已经出了问题,并且把不当的价值放在了地位上。

就连 Herb Sutter 也承认 Contracts 是有争议的。在他论文的脚注4中,无论如何。

一些投了反对票的国家代表团曾参与其中,并在无需被游说的情况下表达了对 contracts 的担忧(重要的是,这是有史以来第一次对任何 C++ DIS 投出反对票)。

换句话说,在任何游说发生之前,我们就已经创造了一个历史性的第一次,即国家代表团对草案有史以来最强烈的反对。

重要的是,在我看来,委员会在整个过程中似乎只是一再忽视各国代表团的意见/反馈,然后在投票时一头撞上了墙。

如果你想“哦,你是在说委员会就是彻头彻尾的无能和/或邪恶吗?”不,不完全是。委员会的流程就是如此混乱,以至于它半自然地导致了这样的局面。在这个系统中工作的人已经太习惯于这个流程了,以至于他们几乎无法看清它。

(多年来,许多认为这个流程不可行的人干脆完全离开了。存在巨大的选择偏差效应。)

使这个流程糟糕的部分原因是它非常“全有或全无”,而且流程如此缓慢,以至于为标准工作对每个人来说都很痛苦。后面会详细说。

总之。我不认为这全是游说的问题。讨论早已在进行中。证据如下:

证据A:各国国家机构的意见

看一下“Do not remove Contracts from C++26”,它提到了“23条关于 contract assertions 的 NB 意见”。

仔细查看 N5028 和 N5031,可以看到委员会至少驳回了以下每个国家提出的一条强烈反对 Contracts 的意见:瑞典、西班牙、美国、法国、罗马尼亚、捷克共和国和芬兰。

这些意见包括多项要求:完全不要以当前形式发布 Contracts、解决安全问题、使 Contracts 可靠地不可忽略、修复 const 问题,以及修改标准库加固的措辞使其不依赖于 Contracts。

再说一遍:这些意见没有一条被接受2!

委员会是怎么想的?认为所有这些要求都完全无关紧要?是啊,如果你无视人们的关切,人们当然会投反对票或弃权。

这本是可以避免的!人们事先就告诉过你他们强烈反对!国家机构在这里正确地履行了他们的职责。他们事先给了你反馈,然后据此投票。

证据B:标准库加固

至少有四条意见专门要求“请不要让‘标准库加固’的工作依赖于将 Contracts 纳入 C++26。”目前,这种耦合仍然存在,也就是说,这些意见被无视了。

事实上,既然 Contracts 的未来已经摇摇欲坠,“Do not remove Contracts”这篇论文包含了以下内容:

在撰写本文时,尚无将 contract assertions 从 C++26 中移除的措辞,而且编写这样的措辞并非纯粹的机械性工作。它将需要:[…]移除或重新规定 C++26 标准库加固 [P3471R4],该文件是以 contract assertions 来表述的,且从未有过独立于 contract assertions 的完整、经审阅的措辞。

在撰写本文时,尚无将 contract assertions 从 C++26 中移除的措辞,而且编写这样的措辞并非纯粹的机械性工作。它将需要:

移除或重新规定 C++26 标准库加固 [P3471R4],该文件是以 contract assertions 来表述的,且从未有过独立于 contract assertions 的完整、经审阅的措辞。

真是胆大妄为。国家机构非常明确地表示,他们不希望标准库加固依赖于 Contracts。

你无视了那些意见,现在却在抱怨回退所需的努力?你得到了所有需要的预警,你只是无视了它!

证据C:不可忽略的 Contracts

我引用 Herb Sutter 关于我们所处情况的论文中的脚注6。如果说有专家的话,那就是他:

P3911 是唯一一个在 CD 意见处理期间 NB 告诉我们可能阻止多个潜在 NB 反对票的技术提案。它也是一个纯扩展,不会扰乱 Contracts 设计的其余部分,也不会干扰未来的扩展,这使得采纳它的成本低、风险低。这就是为什么在 Kona 我反复鼓励 EWG 推进它。它解决了多位专家所说的由安全问题驱动的首要关切:提供一种在源代码中编写 contract 的方式,保证在运行时无论构建模式或链接方式如何都会被执行。然而,它在 EWG 2026-01 电话会议中未能获得批准(“鼓励朝这个方向做更多工作”以8票赞成、25票反对、9票中立未获通过)。现在我们有了新信息,即 NB 已经否决了 DIS,而且有几个再次将安全列为关键问题,因此这一变更可能会增加 NB 的共识。

P3911 是提议增加一种确保 Contracts 始终运行且可被强制执行的方式的论文。

(是的,很多人认为这对安全特性来说是必要的。如果你连安全性能否被执行都无法保证,那还有什么意义?)

Herb Sutter 和我真的有分歧吗?

说实话,大概没有。Herb Sutter 是从政治角度看待这件事的,并根据各方的地位来分析谁的信念更有分量。

Bjarne Stroustrup 的信念(作为 C++ 的创造者)很有分量。这是对的。

引用 Herb Sutter 对此事的讨论:

在 C++26 DIS 上投反对票的国家机构(NB)中,超过一半从未参与过 WG21 的工作,和/或此前从未对 C++26 中的 contracts 表达过任何关切(大多数未对 C++26 CD 评论投票提交意见;其中一个提交了与 contracts 无关的 CD 意见),然而在被引用了 Bjarne 反对意见的信息游说之后,他们对 DIS 投了反对票。

“看!不过是 Bjarne 地位高罢了!”他这么说,而他这么说完全正确,但他同时也表现得好像向成员施加巨大压力以要求他们“保留异议并承诺 :-)”从来就不是这件事的一部分似的。C++ 标准委员会一直按派系投票。

这一直都是一团政治乱局,Bjarne 的明确支持绝对关键,而“我知道你可能不同意,但你应该投赞成票让它通过”也是流程的一部分。

再次引用 Herb Sutter 论文中 Herb Sutter 和 Bjarne 的话:

(编者注:Bjarne 在审阅本文时补充说,此前 DIS 投票之所以一致通过,一个原因是他私人和公开的鼓励。)

也就是游说。

一直都是如此。

裁决

C++ 为什么会陷入这团乱局?

为什么 Contracts 的作者们如此执着于让 Contracts 进入 C++26?为什么不等到下一个版本?

嗯,C++ 有这种有趣的“发布列车模型”(在《超级马里奥兄弟》速通界也称为“帧规则公交站类比”)。C++ 标准的新版本每三年发布一次。如果你的工作及时被投票纳入标准,它就成为标准的一部分。如果没有,你就得再等三年等下一个版本。

三年是很长的时间,尤其是为一个 C++ 特性工作。让一篇 C++ 提案被标准接纳的过程以令人精疲力竭而臭名昭著,我认识的几乎所有“C++ 人”都干脆不再费心,不再与 WG21 合作。这很糟糕。

如果 Contracts 不在这一轮进入,它们很可能永远进不了。它们将在未来三年里被不断挑刺、无休止地争论,而且坦率地说,我认为很有可能几位从事 Contracts 工作的人根本不想应付这些,而可能干脆完全退出这一流程,让 Contracts 彻底死亡并被埋葬。

除非流程本身改变——考虑到大概是 ISO 强加的要求,天知道这怎么可能发生——否则很难想象这种情况会改变。

这就是为什么支持 Contracts 的一方在他们的论文中发表了以下声明:

如果 DIS 投票失败,我们应当在不改变 contract 断言或不将它们从 C++26 中移除的情况下寻求另一次投票;

换句话说,他们在玩一场“胆小鬼博弈”:“我们相信你们会先放弃。”

他们完全清楚,C++26 失败会伤害所有人。但是,由于 WG21 流程如此疯狂,这里的失败有可能彻底杀死 Contracts,并且需要再花三年进行无休止的争论和斗争,所以赌注很高。

据我所知,下一次预定的 WG21 会议于 2026 年 11 月 16 日至 21 日在 Búzios 举行。所以,你可能会想:“啊,那就只是几天的事,他们会坐下来把事情解决,对吧?”

嗯,大概不会。WG21 + ISO 流程缓慢而混乱。即使所有人都就 Contracts 应不应该进入达成一致,每次投票也要开放数周。所以是的,这可能还要再花一年左右。

所以呃,祝你好运,C++。

如果 C++26 失败,我会倒一杯酒。不是为你,而是为那许许多多试图让你变得更好却失败了的人3。

如果你读到了这里,可以考虑订阅电子邮件通知、在 Substack 上关注,或将此博客添加到你的 RSS 阅读器。

  • 如果 Vinnie 的论文里没有那些 Claude 式的表达,比如“所谓‘纯粹增量’的说法把延期变成了驳回”,让人看得眼皮发沉,那要严肃对待这篇论文本来会稍微容易一点。WG21 内部 AI 的使用有所增加,而且并非所有使用都是负责任的。 ↩︎
  • 好吧,确实有一些微小的让步,P3878R1 将标准库加固的部分内容与 Contract observe 机制解耦了。但它仍然与 Contracts 耦合,这使得在 Contracts 无法进入的情况下,标准库加固也不可能被允许进入。换句话说,“标准库加固”草案是在假定 Contracts 必定会进入的前提下写成的。 ↩︎
  • 需要说明的是,这将包括 Contracts 的相关人员(假设 Contracts 失败)。我并不十分支持 Contracts(原因与本文讨论的任何内容无关),但我理解支持它们的理由,而从事这项工作的人(和其他所有人一样)是这一流程的受害者。 ↩︎

The translation is machine-generated and individual terms may be off. Nothing is rewritten or cut; the original is authoritative.

Published by Lobsters
This site only summarises and aggregates; copyright stays with the original author. Headlines and summaries follow the source — where they differ, the original wins.
Read the original ↗