C++23已完成,C++26来了

六个月以来,国际C++标准化工作组已经召开了两次会议 。
在第一次会议上,委员会集中于完善C++23的特性,其中包括:
 

  • 静态运算符[]
  • 静态常量表达式 在 常数表达式 函数
  • 基于安全范围
  • std ::print与其他控制台输出的交互
  • 一元接口用于 std::预期
  • static_assert(false)和其他功能
 
在第二次会议上,委员会致力于开发C++26的新特性,包括:
 
  • 标准::获取 以及 标准::元组大小 用于骨料
  • 包埋数量
  • 获取 标准::堆栈跟踪从例外
  • 栈式协程
C++23静态运算符[] 
去年夏天,委员会在C++23中添加了静态运算符(),并使为多个参数定义运算符[]成为可能 。下一个合乎逻辑的步骤是给予这些操作符平等的机会,即添加写入静态操作符[]的能力 。
enum class Color { red, green, blue };struct kEnumToStringViewBimap {static constexpr std::string_view operator[](Color color) noexcept {switch(color) {case Color::red: return "red";case Color::green: return "green";case Color::blue: return "blue";static constexpr Color operator[](std::string_view color) noexcept {if (color == "red") {return Color::red;} else if (color == "green") {return Color::green;} else if (color == "blue") {return Color::blue;assert(kEnumToStringViewBimap{}["red"] == Color::red);
这段代码真的能有效地将字符串转换为枚举吗?
这可能会让人吃惊,但代码实际上非常高效 。编译器开发人员 使用类似的方法,我们在 用户服务器 框架 。我们创建了一个名为 实用程序::平凡双向映射具有更方便的界面 。
constexpr utils::TrivialBiMap kEnumToStringViewBimap = [](auto selector) {return selector().Case("red", Color::red).Case("green", Color::green).Case("blue", Color::blue);
由于现代优化编译器的特性,实现了高效率(但在编写通用解决方案时必须非常小心) 。提案P2589R1描述了所有必要的详细信息 。
constexpr函数中的静态constexpr
C ++23扩展了它的功能,增加了 常量表达式至字符/自字符 。但是,一些实施者遇到了一个问题 。一些标准库包含常量数组,用于快速转换 弦<>数,这些变量在函数中声明为静态变量 。不幸的是,这妨碍了它们在 常数表达式功能 。这个问题是可以解决的,但解决方法看起来真的很笨拙 。
【C++23已完成,C++26来了】最终,委员会通过允许使用 静态常量表达式 变量在 常数表达式 函数,如中所述 P2647R1 。一个小小的,但受欢迎的改进 。
基于安全范围
这可能是最令人兴奋的消息出来的最后两次会议!
说到这里,我们先来猜个有趣的谜语:你能找出代码中的错误吗?
class SomeData {public:const std::vector& Get() const { return data_; }private:std::vector data_;SomeData Foo();int main() {for (int v: Foo().Get()) {std::cout << v << ',';
答案就在这里 。
基于范围的for循环涉及很多底层进程,因此,这些类型的bug可能并不总是显而易见的 。虽然通过消毒剂测试可以有效地发现这些问题,但现代项目通常将其作为标准实践(在Yandex,我们也不例外) 。然而,理想的做法是尽可能避免此类错误 。
在RG21,我们在四年前首次尝试通过以下方式改善这种情况 D0890R0 。遗憾的是,这一进程在讨论阶段停滞不前 。
谢天谢地,Nicolai Josuttis掌握了主动权,在C ++23中,类似的代码将不再创建悬空引用 。属性右侧创建的所有对象 :在基于范围的for循环中,现在仅在退出循环时才被破坏 。
有关更多技术详情,请参阅文件P2718R0 。
标准::打印
在C ++23中,有一个小的但值得注意的更新 标准::打印:其输出已被调整为与其它数据输出"同步" 。虽然现代操作系统上的标准库不太可能经历任何明显的更改,但更新后的标准现在保证消息将按照它们在源代码中出现的顺序输出到控制台:
printf("first");std::print("second");应为std::的一元接口
C ++23在最后一刻添加了一个相当重要的特性: 包含了一元接口,用于 std::预期,类似于已可用于的一元接口标准::可选 。
using std::chrono::system_clock;std::expected from_iso_str(std::string_view time);std::expected to_bson(system_clock time);std::expected insert_into_db(formats::bson::Timestamp time);// Somewhere in the Application code...from_iso_str(input_data).and_then(&to_bson).and_then(&insert_into_db)// Throws “Exception” if any of the previous steps resulted in an error.transform_error([](std::string_view error) -> std::string_view {throw Exception(error);


推荐阅读