C++23:多维视图(std::mdspan)

编程入门 行业动态 更新时间:2024-10-10 01:17:19

C++23:<a href=https://www.elefans.com/category/jswz/34/1751969.html style=多维视图(std::mdspan)"/>

C++23:多维视图(std::mdspan)

C++23:多维视图(std::mdspan)

介绍

在 C++23 中,std::mdspan 是一个非拥有的多维视图,用于表示连续对象序列。这个连续对象序列可以是一个简单的 C 数组、带有大小的指针、std::arraystd::vectorstd::string

这种多维视图通常被称为多维数组。

多维数组的形状由其维数(也称为秩)和每个维度的大小(也称为扩展)决定。std::mdspan 的大小是所有非零维度的大小的乘积。你可以使用多维索引运算符 [] 来访问 std::mdspan 的元素。

每个 std::mdspan 的维度可以有静态或动态的扩展。静态扩展意味着其长度在编译时指定;动态扩展意味着其长度在运行时指定。

定义

template<class T,class Extents,class LayoutPolicy = std::layout_right,class AccessorPolicy = std::default_accessor<T>
> class mdspan;
  • T: 连续对象序列的类型。
  • Extents: 指定维数及其大小;每个维度可以有静态或动态的扩展。
  • LayoutPolicy: 指定用于访问底层内存的布局策略。
  • AccessorPolicy: 指定如何引用底层元素。

由于 C++17 中的类模板参数推导(CTAD),编译器通常可以自动从初始化器的类型推导出模板参数。

示例

使用动态扩展

#include <mdspan>
#include <iostream>
#include <vector>int main() {std::vector myVec{1, 2, 3, 4, 5, 6, 7, 8};          // (1)std::mdspan m{myVec.data(), 2, 4};                  // (2)std::cout << "m.rank(): " << m.rank() << '\n';      // (4)for (std::size_t i = 0; i < m.extent(0); ++i) {     // (6)for (std::size_t j = 0; j < m.extent(1); ++j) { // (7)std::cout << m[i, j] << ' ';                // (8)}std::cout << '\n';}std::cout << '\n';std::mdspan m2{myVec.data(), 4, 2};                 // (3)std::cout << "m2.rank(): " << m2.rank() << '\n';    // (5)for (std::size_t i = 0; i < m2.extent(0); ++i) {for (std::size_t j = 0; j < m2.extent(1); ++j) {std::cout << m2[i, j] << ' ';  }std::cout << '\n';}}

使用静态和动态扩展

#include <mdspan>
#include <iostream>
#include <string>
#include <vector>
#include <tuple>int main() {std::vector myVec{1, 2, 3, 4, 5, 6, 7, 8};std::mdspan<int, std::extents<std::size_t, 2, 4>> m{myVec.data()}; // (1)std::cout << "m.rank(): " << m.rank() << '\n';for (std::size_t i = 0; i < m.extent(0); ++i) {for (std::size_t j = 0; j < m.extent(1); ++j) {std::cout << m[i, j] << ' ';  }std::cout << '\n';}std::cout << '\n';std::mdspan<int, std::extents<std::size_t, std::dynamic_extent, std::dynamic_extent>> m2{myVec.data(), 4, 2};          // (2)std::cout << "m2.rank(): " << m2.rank() << '\n';for (std::size_t i = 0; i < m2.extent(0); ++i) {for (std::size_t j = 0; j < m2.extent(1); ++j) {std::cout << m2[i, j] << ' ';  }std::cout << '\n';}std::cout << '\n';}

布局策略

std::mdspan 允许您指定用于访问底层内存的布局策略。默认情况下,使用 std::layout_right(C、C++ 或 Python 风格),但您也可以指定 std::layout_left(Fortran 或 MATLAB 风格)。

使用布局策略std::mdspanstd::layout_right遍历两个std::layout_left可以看出差异。

#include <mdspan>
#include <iostream>
#include <vector>int main() {std::vector myVec{1, 2, 3, 4, 5, 6, 7, 8};std::mdspan<int, std::extents<std::size_t,      // (1)std::dynamic_extent, std::dynamic_extent>, std::layout_right> m{myVec.data(), 4, 2};std::cout << "m.rank(): " << m.rank() << '\n';for (std::size_t i = 0; i < m.extent(0); ++i) {for (std::size_t j = 0; j < m.extent(1); ++j) {std::cout << m[i, j] << ' ';  }std::cout << '\n';}std::cout << '\n';std::mdspan<int, std::extents<std::size_t,     // (2)std::dynamic_extent, std::dynamic_extent>, std::layout_left> m2{myVec.data(), 4, 2};std::cout << "m2.rank(): " << m2.rank() << '\n';for (std::size_t i = 0; i < m2.extent(0); ++i) {for (std::size_t j = 0; j < m2.extent(1); ++j) {std::cout << m2[i, j] << ' ';  }std::cout << '\n';}}

接口概览

  • md[ind]: 访问第 ind 个元素。
  • md.size: 返回多维数组的大小。
  • md.rank: 返回多维数组的维数。
  • md.extents(i): 返回第 i 个维度的大小。
  • md.data_handle: 返回指向连续元素序列的指针。

参考:MC++ BLOG – Der Blog für Modernes C++ von Rainer Grimm (modernescpp)

更多推荐

C++23:多维视图(std::mdspan)

本文发布于:2023-11-16 17:14:50,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1628612.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:多维   视图   std   mdspan

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!