C++ 就是 C++

在过去几年中,C++ 社区一直在应对社交媒体上的挑战、所谓继任者的呼声以及即将出台的反 C++ 安全法规的迹象。除此之外,委员会还面临着相互竞争的设计和确定优先级的困难。在这种情况下,人们很容易沉浸在烦恼中或采取激烈的防御立场。

本文试图重构那些非建设性的叙述,并坚信委员会的真正机会在于改善人们的编程工作。我们将展示这种观点如何引导委员会的参与、方向和责任。

简介

在过去的几年里,C++ 社区经历了许多事情。本文并不试图重述这段历史(上帝保佑!),而是承认目前的情况已导致委员会成员质疑 “我们为什么在这里?”、”参与 C++ 标准化工作是否仍然值得?”、”C++ 的未来如何?”以及 “我应该在哪里投入精力?”。今天对这些问题的回答将决定 C++ 未来的命运。

本文件阐述了我个人的观点以及由此产生的技术方向。我的观点来自 23 年的 C++ 行业经验和 8 年的委员会工作经历。同样,在参与 Boost 基金会、Bloomberg C++ Guild、C++ 会议和 #include<C++> 的过程中,我与工程师们进行了无数次交流。不过,我并不自诩掌握了所有答案,并保留在新信息出现时改变想法的权利。

本文件分为三个部分。第一部分考虑了 C++ 标准化委员会的不同使命,并认为最有说服力的使命是改善人们的编程工作。第二部分讨论了一些导致决策适得其反的社会模式和诱惑。最后一部分重点讨论技术偏见,并考虑委员会面临的一些直接选择。

致谢

我在这里所说的一些内容,在其他地方已有更精辟的论述。请读者特别参阅方向小组的《ISO C++ 方向》(P2000R4)和 Bjarne Stroustrup 的《在拥挤和变化的世界中茁壮成长》。我将大量引用这些文件的内容。你怎么能如此确定?(P1962R0)不断发展的 C++ 的操作原则 (P0559R0) 也涉及类似主题。

Niall Douglas、Inbal Levi、Bjarne Stroustrup 和 Herb Sutter 提供了宝贵的反馈意见,极大地改进了本文档,在此一并致谢。

使命

最大的威胁

如果我们不小心,C++ 仍然会失败”。《演进 C++ 的操作原则》提出了 “使 C++ 保持活力、健康和进步 “的原则。这些声明代表了更广泛的社区前景,暗示 C++ 是一个获得了有价值的东西的实体,而这些有价值的东西可能会失去。这究竟是什么意思呢?

不难看出,C++ 是一种适合作为通用编程语言的语言,数百万人的采用就是最好的证明。工程师们可以在合理的时间内熟练掌握并使用它来解决问题。C++ 的实用性才是最重要的。

许多人认为其他编程语言会 “威胁 “C++,或有可能 “夺走 “C++ 所拥有的一切。仔细观察就会发现,新工具的出现并不会降低现有工具的能力,反而有可能使其能力更强。

那么监管立法呢?它改变不了 C++ 的功能,就像改变不了我的锤子的功能一样。C++ 能做它能做的事,并且在使用它的地方很有用。然而,与我的锤子不同的是,有一个实体有权降低 C++ 的性能:C++ 标准化委员会。

让标准变得无关紧要的最可靠方法就是对一切都说 “是”。原因不难理解:将复杂混乱、不连贯的想法标准化,很快就会变成 “危及 C++ 未来的疯狂行为”[1]。如果我的锤子被换成了一个需要数千页指令的复杂小工具,那么它对我来说就不再有用了。然而,这正是我们使用 C++ 的趋势。

如果说 C++ 的最大威胁是标准化委员会,那么这就引出了一个问题:如何降低其风险并使其符合更大的利益。

使命

  1. 如果没有一个统一的使命,一个由数百人组成的机构就无法运作。关于 WG21 的使命有很多想法,但以下几个想法值得考虑:
    使 C++ 成为世界上最好的语言。
  2. 让 C++ 成为人们唯一使用的语言。
  3. 让 C++ 成为最流行的语言。

“最佳”、”唯一 “或 “最流行 “语言的观点值得商榷,但其影响更令人担忧。首先,这种观点会导致对其他语言的反感,这种反感既来自自豪感,也来自对其他语言可能 “更好 “的恐惧。例如,40% 的 C++ 开发人员希望使用 Rust,22% 的开发人员已经使用 Rust;对 Rust 的无知就是对我们用户的无知。[2] 其次,将 C++ 定位为 “最好 “的语言会导致以复杂性和一致性为代价嫁接其他语言的特性。最后,我们花费了大量精力进行无用的争论,声称 “竞争 “语言的优点被夸大了,C++ 的缺点被夸大了。

我们需要一个更具建设性的使命,我认为有一个:改善人们的生活。当基于范围的 for 循环出现在编译器中时,数百万开发人员微笑着说:”啊,真不错”。这甚至可能让他们的生活变得美好。这就是 WG21 所能控制的巨大利益,而我们与之保持一致则是令人难以置信的回报。

利他主义心态消除了 “竞争对手 “的想法。如果和平队首先到达一个贫困地区,人类栖息地会因此而衰败吗?当然不会!他们会庆祝帮助的到来。当我们的用户使用不同的工具解决问题时,我们也应如此。帮助我们用户的其他语言社区是我们的盟友。我们绝不能忘记这一点。地盘争夺战不符合我们用户的利益。

社会方面

有些思维模式会阻碍改善人们生活的使命。认识到这一点非常重要,因为它们无疑会层出不穷。

作为个人和群体特征的 C++

程序员在社交场合相互询问的第一个问题就是 “你用什么语言编程?这经常会造成令人遗憾的刻板印象。”哦,写代码慢的 Java 程序员”。”哦,不会用’真正的’语言编程的 Python 程序员”。”哦,一个……的 Go 程序员”。提到 C++,我们可能会为掌握一门高难度语言、能够编写高性能代码以及与世界上最伟大的 C++ 作品之间的关系而感到自豪。

将 C++ 视为伟大和目标的源泉固然有其好处,但也要付出代价。首先,这主要是一种感性的转移,它遮蔽了理性。在我第一次参加委员会会议时,有人建议我避免提及函数式编程,以免人们一听到这个词就否定我的论点。其次,对 C++ 的深刻认同会让人产生根深蒂固的恐惧,担心 C++ 会成为一种 “传统 “语言,使自己的技能组合(甚至个人!)过时。

我之所以提到这些问题,是因为它们经常会损害旨在改善人们生活的标准化使命。我们需要对编程语言世界进行评估,避免部落主义诱使我们忽视或过度补偿问题。

适得其反的言论

C++ 经常被当作活物来书写和谈论。致命”[3]、”失败”[4]、”死亡”[5]和 “死亡”[6] 等词在我们的文献中很常见。当我们把 C++ 想象成一个生命体时,自然会联想到有限的资源(活跃用户)、竞争(其他语言)和死亡(过时)。这种想法从根本上说是不准确的。C++ 没有生命,不会死亡,也不与任何事物竞争。它只是一种有时有用的工具。

我们必须摒弃这种想法。这种思想与之前讨论过的 “转移 “结合在一起,会产生恐惧并助长敌人的想法。目前,不同语言社区之间缺乏合作和信任,这是非常不幸的。在最糟糕的情况下,人们会因为所使用的编程语言而被贬低。

让我们牢记:a) 语言不是战争,而是人的战争;b) 抹黑其他语言并不能改善人们的生活;c) C++ 长生不老不是我们的目标。

标准化是个人机遇还是管理职责

刚加入委员会时,人们很容易把参与委员会看作是获得 C++ 专业知识、与名人擦肩而过的个人机会,更糟糕的是,通过接受提案在世界上留下印记。虽然所有这些事情确实都会发生,但这里还有更重要的事情在起作用。

指导小组警告说:”我们正在为数以百万计的程序员编写一个可以依赖数十年的标准,因此需要谦虚一些。”[7] 这不是一项可以获得的特权,我们中没有人真正有资格做出这些决定,但我们却在这里。我们的责任重于个人的机遇。

这种责任意味着什么?它意味着拒绝没有可理解的价值主张的建议。这意味着当你反对某件事情时,要抵制社会压力。这意味着要通过阅读论文、测试功能和与他人合作来形成明智的观点。这意味着只有在风险最小的时候才说 “是”。最重要的是,它意味着管理:你是超越自我的东西的看管者和守护者。

如果您确实要撰写提案,请寻求经验丰富的设计师和措辞专家的帮助,以节省时间和挫折感。他们愿意提供帮助!此外,请仔细考虑您要解决的问题是否需要额外的复杂性和风险。C++ 是一种 “试图做得太多太快”[8]的语言,需要 “变得更加克制和有选择性”[9]。

技术方面

与我们的社会倾向同样重要的,还有与我们背道而驰的技术倾向。本节列出了几种反模式,其中没有一种是新的[10]。

Neophilia

Bjarne 简明扼要地指出:”热情有利于新事物”[11]。技术创新和流行遵循着一条我们熟悉的炒作曲线[12],从期望膨胀的高峰期开始。我们有可能被热情所迷惑,将一些功能标准化,但回过头来看,这些功能并没有兑现它们的承诺,与语言的其他部分整合不佳,还增加了学习成本。

考虑一下 Rust traits,它能解决与 C++ 概念类似的问题。traits 的显式选择语义提供了多种优势,包括单独类型检查的泛型。我们是否应该在 C++ 中加入 traits?如果我们这样做,最终就会有两种方法来解决同一个问题,数百万行代码将使用旧方法。此外,大多数开发人员需要同时熟悉这两种方法,才能在现有的大型代码库中有效地工作,从而增加了 C++ 的学习成本。

另一种语言有可能比 C++ 更好,但这并不意味着我们就应该采用它。”跟风 “是一种有害的做法。我们应该问问自己,当第一次在别人的代码中看到某个功能时,非专业人员(我们的大多数用户)会有什么反应。通常情况下,他们会因为不得不花时间学习一些与替代功能相比微不足道的功能而感到沮丧。

功能和优先级偏向专家

C++ 委员会主要由专家组成,普通程序员 “代表性严重不足”[13]。这 “使委员会偏向于语言法律、高级功能和实现问题,而不是直接解决广大 C++ 开发人员的需求,许多委员会成员对这些需求只是间接了解”[14]。

花在专家功能上的时间浪费了大规模改善生活的机会。当我们对一项提案进行优先排序时,我们应该问 “这是在为专家解决问题,还是在为普通开发人员解决问题?如果是前者,我们就应该认真考虑继续前进。

我们的专家失衡也导致了过于复杂的解决方案,简单的任务需要高级技能。与旧的流运算符相比,要使 std::print 能够在自定义类型下工作,需要跳过重重障碍。专家很容易与新手和专业工程师脱节,因为他们不会把业余时间花在学习复杂的 C++ 高级知识上,尤其是当周围都是专家的时候。

委员会成员能做的最有价值的事情之一就是与应用工程师讨论提案。”这是你会用的东西吗?”这符合人体工程学吗?”这有多难学?”这值得在 C++ 书中再写一章吗?这种反馈应该比抽象的理想开发人员理论更重要。

复杂性

指导小组认为,”由于基于不同的、有时是相互矛盾的设计理念和不同的风格品味而提出的建议,C++ 有可能失去连贯性”。[15] Bjarne 怀疑这是由于委员会的壮大、新人的涌入、成员的专业化以及成员对 C++ 历史了解的减少等综合因素造成的。

减少一致性的变化会增加复杂性,从而提高培训成本。招聘 C++ 开发人员比招聘其他开发人员更具挑战性,这不是因为需求,而是因为入门门槛太高。想学 C++ 的人越来越少,想教 C++ 的学校也越来越少。我们改善人们生活的重要方法之一就是帮助用户找到同事。

指导小组忆及亚历克斯-斯捷潘诺夫(Alex Stepanov)将 C++ 从灾难中拯救出来,为标准库带来了一致性和连贯性[17]。最近,我们用了不少于三种替代方法来替换一个简单的 std::function 模板:std::copyable_functionstd::function_refstd::move_only_function。这对我们的复杂性问题毫无帮助!

我同意设计小组的观点,即我们必须 “力求协调一致”[18]。以下是实现这一目标的三个具体建议:

  1. 遏制将提案讨论集中在一个狭窄的问题领域的倾向,询问它如何与整个 C++ 产品相匹配。”这符合 C++ 的通用风格吗?”这是否会提高 C++ 的入门门槛?这会对假设的 “C++ 书籍 “产生什么影响?
  2. 鼓励研究小组及早从演进小组(EWG 和 LEWG)获取有关功能可取性的反馈意见。在研究小组广泛迭代之前获得这种反馈,可以防止不可取的功能获得难以阻挡的发展势头。
  3. 克服不愿意说 “我认为这不属于 C++”的想法。我们为最终不可取的建议提供改进反馈对作者没有任何好处。

利基(niche)问题比利基(niche)努力更重要

很难记住,一种语言不可能面面俱到。更难接受的是,它甚至无法解决每个成员最迫切的问题。
–Bjarne Stroustrup, Thriving in a Crowded and Changing World

在委员会中,我们经常把时间花在只有少数人关心的事情上。当某个人、某个地方会从中受益时,很难说 “不”。在这些讨论中,我们也有一种精神退缩的倾向,这导致提案得不到适当的严谨性。

当我们陷入这些陷阱时,我们会:1)剥夺更多用户花在可以改善他们生活的提案上的时间;2)不必要地增加语言和图书馆的复杂性;3)鼓励更多的小众提案。

解决这些问题,归根结底就是要经常说 “不”,必要时还要反复说 “不”。撇开修正错误不谈,委员会应该把时间花在数量更少、影响更大的提案上。撰写论文解决 C++ 中的 “小毛病”,还不如为影响更大的提案撰写分析和经验报告。我们应该更多地肯定这些工作。

展望

本节将根据本文的原则,对内存安全和 C++ 进行重大调整。

内存安全

由于 “内存不安全”,讨论针对 C++ 立法的官方文件在社区引起了轩然大波。我们看到了大量的电子邮件线程、一个致力于安全问题的新研究小组,以及在 C++ 会议上举行的众多会谈。但普通 C++ 用户对内存安全特性的需求却少得多,他们更关心的是编译速度。当大多数 C++ 开发人员还没有采用 Coverity 和 C++ 核心指南检查器这样的工具时,至少从他们的角度来看,很难说内存安全特性能实质性地改善他们的生活。

当内存安全成为一个严重问题时,我们就会看到关键组件采用 Rust。然而,即使是这些开发人员,我们也很少看到他们对 C++ 安全特性的需求。他们的问题已经解决了。

指导小组指出:”没有一种语言能满足所有人的一切需求”[20],我对此深表赞同。Rust 和其他语言成功地满足了关键组件对内存安全保证的工程需求。这并不是用户要求我们涉足的领域,这样做既有可能失败,也有可能带来更多的复杂性。

C++ 大修

在过去两年中,谈论 “C++ 后继者 “已成为一种时尚,其范围从语法的巨大变化到用另一个组织取代 C++ 委员会。委员会应该如何应对这一现象?

对于在委员会之外尝试新语言的团体,我认为我们的回应应该是支持。如果这些举措不会混淆或损害我们的用户,那么它们就与我们有着共同的目标,即改善人们的生活。如果它们成功了,那就是一件好事。即使它们失败了,它们产生的想法最终可能会帮助我们的用户。

那么,在 WG21 的背景下,彻底改变 C++ 面貌的选择又是什么呢?也许是 C++ 2.0?如果你问一个典型的 C++ 开发人员,我们如何才能改善他们的生活,那么现代化的、时髦的新语法并不会排在他们的首位。是的,template 和 typename 的阅读和键入很乏味,但这是他们所熟悉的,他们宁愿不对其进行改动。这不仅仅是不愿意改变–我们的用户希望他们的 C++ 代码库保持一致,就像我们希望标准保持一致一样。

如果 C++ 的后继者获得成功,我们的用户会希望它是最好的。委员会的组成并没有神奇的魔力,使其比任何其他实体更适合构建后续版本。C++ 1.0 被采用的惯性甚至可能导致 C++ 2.0 被采用,而其他后继者的尝试则更适合目的。这对我们的用户来说可不是什么好事。

总之,C++ 委员会改善人们生活的最大机会就是专注于 C++ 的现状,以便在几年后在兼容性的限制下为我们提供更好的服务。让我们把投机性的后续项目留给外部实体吧。我们已经够分心了。

我们该怎么办?

我已经说了很多我们不应该做的事情。这是故意的–我们需要做得更少。但是,我并不想给人留下我们应该拒绝所有建议的印象。通过提案改善用户生活的机会很多。下面是几个具体的例子:

  • 更快的散列和散列组合器。标准库的散列映射和散列集接口已有几十年的历史。在此期间,我们看到它们的实用性和许多算法都有了突飞猛进的发展,而这些发展都需要接口的改变。通过在标准中添加更现代的散列数据结构,我们可以大幅提高新编写代码的性能,并减少对环境的影响。我们的用户也迫切需要一种标准化的方式,将哈希值组合到他们自己的哈希函数中。
  • JSON 解析。一个简单、符合人体工程学、标准化的 JSON 解析和序列化库将为许多用户节省搜索库或编写自定义格式的时间。我们的目标不是成为世界上最快的 JSON 解析器。
  • 命令行解析。一个简单、标准化的命令行解析库还将取代小型应用程序中常见的 argv[1] 解析,从而改善 99% 用户的生活。

类似的想法还有很多。我们的目标是让尽可能多的人产生 “啊,真不错 “的反应。

结论

本文倡导 C++ 标准化的使命:改善人们的编程工作。它还指出了阻碍这一使命的社会和技术偏见。最后,它考虑了 WG21 正在进行的主要讨论,并对未来工作提出了建议。

最后,当我说 “C++ 就应该是 C++”时我的意思是说,C++ 是一个非常有用的工具–剧烈的变化并无益处。为了避免它变得面目全非,我们需要经常说 “不”,认识到我们的偏见,最重要的是,把用户放在第一位。

参考文献

“2023 Developer Survey.” Stack Overflow, 2023, https://survey.stackoverflow.co/2023/.

Hinnant, Howard et al. “Direction for ISO C++.” 15 October 2022, https://wg21.link/P2000R4.

Stroustrup, Bjarne. “How can you be so certain?” 18 November 2019, https://wg21.link/P1962R0.

Stroustrup, Bjarne. “Remember the Vasa!” 6 March 2018, https://wg21.link/P0977R0.

Stroustrup, Bjarne. “Thriving in a Crowded and Changing World: C++ 2006-2020.” Proc. ACM Program. Lang., vol. 4, HOPL, June 2020, Article 70, pp. 1-167, https://doi.org/10.1145/3386320.

van Winkel, J.C. et al. “Operating principles for evolving C++” 31 Janurary 2017, https://wg21.link/P0559R0.


  1. Remember the Vasa! (P0977R0↩︎
  2. The Stack Overflow 2023 survey had 89,184 respondents. 19,634 indicated they did “extensive development work” C++ over the past year and 4,269 claimed extensive development work in both Rust and C++ over the past year. Of those who used C++, 7,918 indicated a desire to work in Rust over the next year. ↩︎
  3. Direction for ISO C++ (P2000R4 ↩︎
  4. How can you be so certain (P1962R0↩︎
  5. Operating principles for evolving C++ (P0559R0↩︎
  6. ibid. ↩︎
  7. Direction for ISO C++ (P2000R4↩︎
  8. How can you be so certain? (P1962R0↩︎
  9. ibid. ↩︎
  10. See Thriving in a Crowded and Changing World and Direction for ISO C++ (P2000R4↩︎
  11. Thriving in a Crowded and Changing World ↩︎
  12. https://en.wikipedia.org/wiki/Gartner_hype_cycle ↩︎
  13. Direction for ISO C++ (P2000R4↩︎
  14. Thriving in a Crowded and Changing World ↩︎
  15. Direction for ISO C++ (P2000R4↩︎
  16. Thriving in a Crowded and Changing World ↩︎
  17. Direction for ISO C++ (P2000R4↩︎
  18. ibid. ↩︎
  19. Credit to Niall Douglas for this idea ↩︎
  20. Direction for ISO C++ (P2000R4↩︎

本文文字及图片出自 C++ Should Be C++

余下全文(1/3)
分享这篇文章:

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注