C++ 标准库已回归十五年

2026-05-24 1 阅读 alexjurkiewicz
C++ 标准库已经倒退十五年了,收据公开发布:2026 年 5 月 23 日 C++ 标准库已经倒退十五年了,收据公开了 Sandor Dargo 本月在 std::copyable_function 上发表的帖子,并以快速参考表结束。四个可调用包装器,每个推荐一个,列表底部的一个条目应该会让任何正在工作的 C++ 工程师感到冷淡:std::function : Legacy。避免在新代码中使用。 C++11 中提供了 std::function。该委员会花了十五年的时间运送应该取代它的包装纸。最新的 std::copyable_function 登陆 C++26。新版本顶部写的建议并不是“当您需要可复制的可调用对象时使用它”。就是“不要用原来的”。这并不罕见。自从 C++11 诞生以来,C++ 委员会就一直在写这句话来描述它自己的特性。有时,该句子是正式的(文件编号、标准中的弃用、一个周期后的删除)。有时,这句话是每个高级工程师在第一天告诉每个初级工程师的(“永远不要伸手去拿那个,这里是可以使用的东西”)。有时,这句话根本无法写入标准,因为损坏的东西被 ABI 兼容性锁定,因此它保留在标准库中,作为每个教程都会达到的默认值,并且每个生产代码库都会悄悄替换。该模式非常一致,值得拥有自己的目录,每个条目旁边都有论文编号,因此下次有人告诉您新的 C++ 功能是未来时,您可以要求他们估计下一篇论文弃用它之前需要多长时间。这件作品就是那个目录,分为三层。第一层是委员会写下的正式回访。第二层是委员会尚未正式确定的“每个人都知道要避免这种情况”的回访。第三层是最糟糕的,因为它是几乎每个 C++ 代码库每天都使用的标准库容器,并且委员会无法在不破坏 ABI 的情况下修复它。我们从我们自己的 Rust-vs-C++ 多书基准测试中获得了第三层的收据,该基准测试在具有相同隔离的相同工作负载上测量了 Rust 标准库和 C++ 之间 P99 延迟的 58 倍,并追踪了委员会从未正式表示损坏的三个容器的差距。第一层:委员会写下的正式回溯以下每个条目都指向工作组通过的真实文件。这些都不是论据。他们是书面录取。最干净的历史案例是 std::auto_ptr ,它是 C++98 智能指针,其复制即移动语义从发布之日起就破坏了通用代码和标准容器。在 C++11 中已弃用,在 C++17 中由 N4190“删除 auto_ptr、random_shuffle() 和旧的 内容”删除,Stephan T. Lavavej。那篇论文还从 C++98 中取出了整个 适配器动物园: std::bind1st 、 std::bind2nd 、 std::ptr_fun 、 std::mem_fun 、 std::mem_fun_ref 、 std::unary_function 、 std::binary_function 、 std::pointer_to_unary_function 、 std::pointer_to_binary_function 。替代品是 lambda,这是一种提前两个周期推出的语言功能,使得整个适配器框架变得无关紧要。 std::random_shuffle 随之而来,在 C++14 中弃用,在 C++17 中删除,由 std::shuffle 取代,因为原始版本依赖于 std::rand 和全局状态。动态异常规范( throw(X, Y) )是 C++98 机制,用于声明函数可以抛出哪些异常。在 C++11 中已弃用,在 C++17 中由 P0003R5 、 Alisdair Meredith 删除。替换: noexcept 。 noexcept(true) 残留的 throw() 同义词一直保留到 C++20,当时 P1152 最终杀死了它。十八年的标准文本花费了卸载异常模型的时间。 std::iterator 是每本“Effective C++”书教您继承的 C++98 基类,在 C++17 中已被 P0174R2 弃用(“弃用 C++17 中的残留库部分”,Meredith)。现在建议删除 P3365R1 中的 C++26。替代方案是“自己定义五个 typedef”,这是大多数工程师所做的,因为从 std::iterator 继承永远不会给您任何有用的东西。 std::aligned_storage 和 std::aligned_union 在 C++11 中提供,在 C++23 中已被 P1413R3(CJ Johnson、Google)弃用。该论文的基本原理值得引用,因为它表明委员会承认自己的工作存在设计错误。已弃用的类型需要 typename ::type 样板文件,需要 reinterpret_cast 来访问内容,将 Len == 0 视为未定义行为,并且不是 constexpr。替换是“直接使用alignas(T) std::byte[sizeof(T)]”,这就是标准可能应该首先发布的内容。 std::not1 / std::not2 和 unary_negate / binary_negate 适配器在 C++17 中已弃用,在 C++20 中删除,并由 std::not_fn ( P0005 ) 取代。 std::get_temporary_buffer 和 std::raw_stora