std::mdspan

来自cppreference.com
< cpp‎ | container
 
 
 
 
在标头 <mdspan> 定义
template<

    class T,
    class Extents,
    class LayoutPolicy = std::layout_right,
    class AccessorPolicy = std::default_accessor<T>

> class mdspan;
(C++23 起)

std::mdspan 是一种到对象的连续序列的视图,它将其重新解释为多维数组。

mdspan 的每种特化 MDS 均实现 copyable,并且满足:

mdspan 的特化,若其 accessor_typemapping_typedata_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)
(公开静态成员函数)

非成员函数

针对 mdspan 特化的 std::swap 算法
(函数模板)
子视图
(C++26)
返回现存 mdspan 的子集上的视图
(函数模板)
从现存 extents 和分片说明符创建新的 extents
(函数模板)

辅助类型和模板

(C++23)
某秩多维索引空间的一个描述符
(类模板)
(C++23)(C++26)
全动态 std::extents 的方便别名模板
(别名模板)
指示索引访问 mdspan 元素的方式的类型
(类模板)
布局映射策略
列优先多维数组布局映射策略;最左边的尺度具有步幅 1
(类)
行优先多维数组布局映射策略;最右边的尺度具有步幅 1
(类)
具有用户自定义步长的布局映射策略
(类)
具有可大于或等于最左侧尺度的填充跨步的列主序布局映射策略
(类)
具有可大于或等于最右侧尺度的填充跨步的行主序布局映射策略
(类)
子视图辅助项
切片说明符标签,描述指定尺度的全部索引范围
(标签)
切片说明符,表示一组按照偏移量、尺度和跨步三值指定的有规律分布的索引
(类模板)
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)
连续的对象序列上的无所有权视图
(类模板)
数值数组,数组掩码和数组切分
(类模板)