概述

C++26为std::span带来了四项针对性改进,使其成为标准库中更完整和一致的工具。

1. P2447R6: std::span支持初始化列表

之前,将花括号初始化列表(如{1, 2, 3})传递给span函数参数会失败,需要双层花括号。

void take(std::span<const int> v);

take({1, 2, 3}); // C++26之前:错误
take({1, 2, 3}); // C++26:正常工作

2. P2821R5: span.at()

这是最简单的补充——可以说是std::span一开始就应有的功能。它为span添加了边界检查的查找。

其他所有连续容器和视图(std::string、std::string_view、std::vector、std::array、std::deque)都同时提供不安全的operator[]和安全抛出异常的at(),span是唯一的例外。

std::array<int, 4> arr = {1, 2, 3, 4};
std::span<int> s{arr};

s[10];    // 未定义行为
s.at(10); // 抛出 std::out_of_range

3. P2833R2: Freestanding Library支持span

将span(以及expected、out_ptr、inout_ptr、mdspan)添加到freestanding实现中。这些功能可以在嵌入式系统、内核或裸金属环境中使用。

注意:由于freestanding环境通常不支持异常,span::at()被排除在freestanding子集之外。

4. P3029R1: 更好的mdspan CTAD

改进类模板参数推导(CTAD),保留编译时大小信息。

int arr[5] = {1, 2, 3, 4, 5};
int* p = arr;

// C++26之前:推导为 span<int, dynamic_extent>
std::span s1(p, std::integral_constant<std::size_t, 5>{});

// C++26:推导为 span<int, 5>
std::span s2(p, std::integral_constant<std::size_t, 5>{});

总结

C++26为span及其生态系统带来了四项针对性改进:

  • 通过新的initializer_list构造函数实现更人体工程学的初始化
  • 迟到已久的at()用于边界检查访问
  • 在freestanding环境中支持span
  • 更智能的CTAD,保留编译时大小信息

这些都不是突破性的变化,但它们消除了粗糙边缘,使span成为标准库中更完整和一致的工具。