C++26 标准已批准

ISO C++ 语言标准化委员会已批准了构成国际标准“C++26”的最终规范版本。该规范中提出的特性已在 GCC、Clang 和 Microsoft Visual C++ 编译器中得到部分支持。支持 C++26 的标准库已在 Boost 项目中实现。

在接下来的两个月里,经批准的规范将进入文件编制阶段,期间将进行编辑修正,以解决拼写错误和错别字。11月初,最终版本的文件将提交给ISO,以正式名称ISO/IEC 14882:2026发布。

C++26 的主要特性:

  • 已实现契约编程元素(契约),允许您使用三个新运算符定义正式的接口规范:`pre`(前置条件)、`post`(后置条件)和 `contract_assert`(断言检查)。`pre` 运算符定义调用前必须满足的前置条件(输入验证);`post` 运算符定义执行后必须满足的条件(输出要求);`contract_assert` 运算符定义引发异常的条件。此功能将在 GCC 16 中提供。`int f(const int x) pre (x != 1) // 输入要求 post (r : r == x && r != 2) // 结果要求;r 是结果的值 { contract_assert (x != 3); return x; }`
  • 新增了反射支持,允许在编译时监视和修改程序元素。新增了用于获取语法结构元信息的运算符“^^”和用于执行逆变换的运算符“[:…:]”。建议使用 std::meta 库来转换和处理检查过程中获取的信息,并提供诸如常量计算等功能。反射支持将在 GCC 16 中添加。constexpr int i = 42, j = 42; constexpr std::meta::info r = ^^i, s = ^^i; static_assert(r == r && r == s); static_assert(^^i != ^^j); // 'i' 和 'j' 的值不同。static_assert(constant_of(^^i) == constant_of(^^j)); // 'i' 和 'j' 相同 static_assert(^^i != std::meta::reflect_constant(42)); // 与值 42 不同
  • 新增了“template for”功能,用于在编译时以类似常规 for 循环的方式遍历参数包、元组对象和反射结果(元对象)等元素。执行“template for”时,循环体会针对每个元素展开,并且每次迭代都在一个单独的作用域中处理,循环中变化的变量在该作用域中保持不变。在反射上下文中,“template for”可用于遍历类或枚举的属性。此功能将在 GCC 16 中可用。例如,`void f() { template for (constexpr int I : std::array{1, 2, 3}) { static_assert(I < 4); } }` 将展开为:`void f() { { constexpr auto&& __range = std::array{1, 2, 3}; constexpr auto __begin = __range.begin();` constexpr auto __expansion-size = __range.end() — __begin; // 3 { constexpr int I = *(__begin + 0); static_assert(I < 4); } { constexpr int I = *(__begin + 1); static_assert(I < 4); } { constexpr int I = *(__begin + 2); static_assert(I < 4); } } }
  • 新增了用于异步和并行代码执行的 std::execution 框架。它提供了调度器对象(定义工作调度器,例如线程、线程池、GPU 或事件循环)、发送器对象(定义要执行的工作)和接收器对象(处理结果)。using namespace std::execution; scheduler auto sch = thread_pool.scheduler(); sender auto begin = schedule(sch); sender auto hi = then(begin, []{ std::cout < "Hello world! Have an int."; return 13; }); sender auto add_42 = then(hi, [](int arg) { return arg + 42; }); auto [i] = this_thread::sync_wait(add_42).value();
  • std::simd 库已添加,用于使用标准 C++ 类型系统,通过 AVX-512 和 NEON 等 SIMD 指令集并行化数据操作。 a = {1.0f, 2.0f, 3.0f, 4.0f}; std::simd b = {5.0f, 6.0f, 7.0f, 8.0f}; std::simd result = a + b;
  • 本文提出了一种可变大小向量(数组)`std::inplace_vector` 的实现。它分配在栈上,栈的大小在编译时确定。其 API 与 `std::vector` 类似,但数组元素存储在内部,而不是堆上。`inplace_vector a(10); inplace_vector b(std::move(a)); assert(a.size() == 10);`
  • 已添加“#embed”指令,用于将二进制资源嵌入到代码中。const unsigned char icon_display_data[] = { #embed "art.png" };
  • 新增了对在编译时生成和处理 constexpr 上下文中发生错误时异常的支持。constexpr std::optional checked_divide(unsigned n, unsigned d) { try { return divide(n, d); } catch (...) { return std::nullopt; } } constexpr date parse_date(std::string_view input) { auto [correct, year, month, day] = ctre::match<“([0-9]{4})-([0-9]{1,2})-([0-9]{1,2})”>(input); if (!correct) { throw incorrect_date{input}; } return build_date(year, month, day); }
  • std::hive 数据结构专为无序数据存储和内存重用而设计,可重用已删除元素释放的内存。该结构针对高强度、任意顺序的元素添加和删除工作负载进行了优化。与数组不同,在 std::hive 中删除元素不会移动其他元素,而是将已删除的元素标记为空,并在添加新元素时填充空出的位置。
  • 添加了基于 BLAS 的线性代数 API 的 std::linalg 库。
  • 新增了对危险指针同步机制的支持,该机制可防止在未加锁的情况下释放其他线程正在访问的对象所占用的内存。当一个对象被删除时,它只会被标记为已删除,但只有当所有线程都释放了访问该对象时设置的危险指针后,该对象占用的内存才会被释放。
  • 新增了对 RCU(读取-复制-更新)同步机制的支持。写入操作会创建一个新的对象实例,而读取操作不会阻塞,而是继续使用旧实例。更改完成后,新实例变为活动状态,并对其执行新的读取操作;旧实例在读取线程完成后会被删除。
  • 为了加强标准库的安全性,我们进行了一些更改,例如检查有效值和缓冲区溢出。例如,在访问元素“constexpr reference operator[](size_type idx) const;”时,增加了对条件“idx < size()”的检查。
  • 提供了使用 constexpr 关键字和 new 运算符的变体(placement new)在编译时将对象放置到预分配内存中的功能。
  • 在“constexpr”上下文中新增了对结构化绑定的支持,这意味着对常量表达式的引用现在本身也可以是常量表达式。已实现对数组和简单结构体的支持。constexpr int arr[] = {1, 2}; constexpr auto [x, y] = arr;
  • 结构化绑定现在支持“...”语法,以指定捕获分配序列中剩余元素数的包。auto [x,y,z] = f(); // 变量 x、y、z 将包含 f() 返回的三个元素。auto [...xs] = f(); // 包 xs 将包含 f() 返回的所有元素。auto [x, ...rest] = f(); // x 将包含第一个元素,rest 将包含其余元素。auto [x, y, ...rest] = f(); // x 将包含第一个元素,y 将包含第二个元素,rest 将包含第三个元素。auto [x, ...rest, z] = f(); // x 将包含第一个元素,rest 将包含第二个元素,z 将包含第三个元素。
  • 添加了对类型的“简单可重定位性”的支持,允许通过在内存中克隆给定类型的对象而不调用构造函数或析构函数来优化其移动。为类实现了memberwise_trivially_relocatable和memberwise_replaceable属性,并添加了trivially_relocate_at和trivially_relocate函数,用于一个或多个对象的低级移动。
  • 已实现将 main() 函数附加到全局模块以及在命名模块中定义 main() 函数的功能。
  • 添加了变量运算符“friend”(“friend Ts...”)。
  • 为结构化绑定实现了属性;
  • 添加了语法“= delete("reason")”。
  • 基本字符集包括“@”、“$”和“`”。
  • 提供了在 if 和 switch 语句中使用结构化绑定作为条件的功能。
  • 添加了在一个作用域中使用多个名称为“_”的占位符变量的功能,例如,以下构造现在是正确的: struct S { int _, _; };无效 func() { int _, _; } 无效其他() { int _; // 之前在 -Wunused 模式下显示警告 }
  • 可以在上下文中使用字符串文字,在该上下文中,它们不用于初始化字符数组,也不最终出现在结果代码中,而是仅在编译时用于诊断消息和预处理,例如,作为指令和属性 _Pragma、asm、extern、static_assert、[[已弃用]] 和 [[nodiscard]]。
  • 添加了内置函数:“__builtin_is_within_lifetime” 用于检查联合体中的替代函数是否处于活动状态,以及“__builtin_is_virtual_base_of” 用于检查基类是否为虚函数。
  • 实现了简单的无限循环,没有出现未定义行为。
  • 确保在删除指向不完整类型的指针时显示错误。
  • 使用省略号且前面没有逗号来定义可变参数的语法(例如,指定“void e(int…)”而不是“void e(int, …)”)已被弃用。
  • 禁止使用宏来声明模块。
  • 算术运算中枚举值的隐式转换已被弃用。int main() { enum E1 { e }; enum E2 { f }; bool b = e <= 3.7; // 已弃用 int k = f - e; // 已弃用 int x = +f - e; // 正常 }
  • 已停止支持直接数组比较。int arr1[5]; int arr2[5]; bool same = arr1 == arr2;
  • is_trivial 模板类已被弃用。

    来源: opennet.ru
为具有 DDoS 保护、VPS VDS 服务器的站点购买可靠的主机 🔥 购买具备 DDoS 防护的可靠网站托管服务,包括 VPS 和 VDS 服务器 | ProHoster