std::mdspan
来自cppreference.com
在标头 <mdspan> 定义
|
||
template< class T, |
(C++23 起) | |
std::mdspan
是一种到对象的连续序列的视图,它将其重新解释为多维数组。
mdspan
的每种特化 MDS
均实现 copyable
,并且满足:
- std::is_nothrow_move_constructible_v<MDS> 为 true,
- std::is_nothrow_move_assignable_v<MDS> 为 true,且
- std::is_nothrow_swappable_v<MDS> 为 true。
mdspan
的特化,若其 accessor_type
、mapping_type
和 data_handle_type
均为可平凡复制 (TriviallyCopyable) 类型,则它是可平凡复制 (TriviallyCopyable) 类型。
模板形参
T | - | 元素类型;既不是抽象类也不是数组类型的完整对象类型。 |
Extents | - | 指定维数及各维大小,均为编译时已知。必须是 std::extents 的特化。 |
LayoutPolicy | - | 指定如何将多维索引转换为底层的一维索引(列优先三维数组、对称三角二维矩阵等)。必须满足布局映射策略 (LayoutMappingPolicy) 。 |
AccessorPolicy | - | 指定如何将底层一维索引转换为对 T 的引用。必须满足 std::is_same_v<T, typename AccessorPolicy::element_type> 为 true 的约束条件。必须满足访问器策略 (AccessorPolicy) |
成员类型
成员类型 | 定义 |
extents_type
|
Extents
|
layout_type
|
LayoutPolicy
|
accessor_type
|
AccessorPolicy
|
mapping_type
|
LayoutPolicy::mapping<Extents> |
element_type
|
T
|
value_type
|
std::remove_cv_t<T> |
index_type
|
Extents::index_type |
size_type
|
Extents::size_type |
rank_type
|
Extents::rank_type |
data_handle_type
|
AccessorPolicy::data_handle_type |
reference
|
AccessorPolicy::reference |
成员对象
成员名字 | 定义 |
acc_ (私有)
|
accessor_type 类型的访问器(仅用于阐述的成员对象*) |
map_ (私有)
|
mapping_type 类型的布局映射(仅用于阐述的成员对象*) |
ptr_ (私有)
|
data_handle_type 类型的底层数据句柄(仅用于阐述的成员对象*) |
成员函数
构造一个 mdspan (公开成员函数) | |
给一个 mdspan 赋值 (公开成员函数) | |
元素访问 | |
访问指定多维索引处的元素 (公开成员函数) | |
观察器 | |
返回多维索引空间的大小 (公开成员函数) | |
检查索引空间大小是否为零 (公开成员函数) | |
获取沿指定维度的步长 (公开成员函数) | |
获取范围(extent)对象 (公开成员函数) | |
获取指向底层一维序列的指针 (公开成员函数) | |
获取映射(mapping)对象 (公开成员函数) | |
获取访问器策略对象 (公开成员函数) | |
确定此 mdspan 的映射是否唯一(每个索引组合映射到不同的基础元素) (公开成员函数) | |
确定此 mdspan 的映射是否详尽(exhaustive)(可以使用某些索引组合访问每个底层元素) (公开成员函数) | |
确定此 mdspan 的映射是否跨步(在每个维度中,每次递增索引都会跳过相同数量的基础元素) (公开成员函数) | |
[静态] |
确定此 mdspan 的布局映射是否始终唯一(unique) (公开静态成员函数) |
确定此 mdspan 的布局映射(layout mapping)是否总是详尽的 (公开静态成员函数) | |
确定此 mdspan 的布局映射是否始终跨步(strided) (公开静态成员函数) |
非成员函数
(C++23) |
针对 mdspan 特化的 std::swap 算法 (函数模板) |
子视图 | |
(C++26) |
返回现存 mdspan 的子集上的视图 (函数模板) |
(C++26) |
从现存 extents 和分片说明符创建新的 extents (函数模板) |
辅助类型和模板
(C++23) |
某秩多维索引空间的一个描述符 (类模板) |
(C++23)(C++26) |
全动态 std::extents 的方便别名模板 (别名模板) |
(C++23) |
指示索引访问 mdspan 元素的方式的类型 (类模板) |
布局映射策略 | |
(C++23) |
列优先多维数组布局映射策略;最左边的尺度具有步幅 1 (类) |
(C++23) |
行优先多维数组布局映射策略;最右边的尺度具有步幅 1 (类) |
(C++23) |
具有用户自定义步长的布局映射策略 (类) |
(C++26) |
具有可大于或等于最左侧尺度的填充跨步的列主序布局映射策略 (类) |
(C++26) |
具有可大于或等于最右侧尺度的填充跨步的行主序布局映射策略 (类) |
子视图辅助项 | |
(C++26) |
切片说明符标签,描述指定尺度的全部索引范围 (标签) |
(C++26) |
切片说明符,表示一组按照偏移量、尺度和跨步三值指定的有规律分布的索引 (类模板) |
(C++26) |
各 submdspan_mapping 重载的返回类型 (类模板) |
推导指引
注解
功能特性测试宏 | 值 | 标准 | 功能特性 |
---|---|---|---|
__cpp_lib_mdspan |
202207L | (C++23) | std::mdspan
|
__cpp_lib_submdspan |
202306L | (C++26) | std::submdspan |
202403L | (C++26) | std::mdspan 的有填充布局
|
示例
可以在 Compiler Explorer 中预览
运行此代码
#include <cstddef> #include <mdspan> #include <print> #include <vector> int main() { std::vector v{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12}; // 将数据视作表示 2 行每行 6 个 int 的连续内存 auto ms2 = std::mdspan(v.data(), 2, 6); // 将相同数据视作 2 x 3 x 2 的三维数组 auto ms3 = std::mdspan(v.data(), 2, 3, 2); // 使用二维视图写入数据 for (std::size_t i = 0; i != ms2.extent(0); i++) for (std::size_t j = 0; j != ms2.extent(1); j++) ms2[i, j] = i * 1000 + j; // 使用三维视图读回数据 for (std::size_t i = 0; i != ms3.extent(0); i++) { std::println("slice @ i = {}", i); for (std::size_t j = 0; j != ms3.extent(1); j++) { for (std::size_t k = 0; k != ms3.extent(2); k++) std::print("{} ", ms3[i, j, k]); std::println(""); } } }
输出:
slice @ i = 0 0 1 2 3 4 5 slice @ i = 1 1000 1001 1002 1003 1004 1005
参阅
(C++20) |
连续的对象序列上的无所有权视图 (类模板) |
数值数组,数组掩码和数组切分 (类模板) |